@open-mercato/core 0.5.1-develop.2691.d8a0934b37 → 0.5.1-develop.2694.732417c5ec

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 (414) hide show
  1. package/dist/modules/api_keys/data/entities.js +1 -1
  2. package/dist/modules/api_keys/data/entities.js.map +1 -1
  3. package/dist/modules/api_keys/services/apiKeyService.js +5 -5
  4. package/dist/modules/api_keys/services/apiKeyService.js.map +2 -2
  5. package/dist/modules/attachments/api/library/[id]/route.js +1 -1
  6. package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
  7. package/dist/modules/attachments/api/library/route.js +7 -9
  8. package/dist/modules/attachments/api/library/route.js.map +2 -2
  9. package/dist/modules/attachments/api/partitions/route.js +3 -3
  10. package/dist/modules/attachments/api/partitions/route.js.map +2 -2
  11. package/dist/modules/attachments/api/route.js +6 -5
  12. package/dist/modules/attachments/api/route.js.map +2 -2
  13. package/dist/modules/attachments/api/transfer/route.js +1 -1
  14. package/dist/modules/attachments/api/transfer/route.js.map +2 -2
  15. package/dist/modules/attachments/data/entities.js +2 -1
  16. package/dist/modules/attachments/data/entities.js.map +2 -2
  17. package/dist/modules/attachments/lib/ocrQueue.js +1 -1
  18. package/dist/modules/attachments/lib/ocrQueue.js.map +2 -2
  19. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +2 -2
  20. package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
  21. package/dist/modules/audit_logs/data/entities.js +1 -1
  22. package/dist/modules/audit_logs/data/entities.js.map +1 -1
  23. package/dist/modules/audit_logs/services/actionLogService.js +77 -70
  24. package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
  25. package/dist/modules/auth/api/roles/acl/route.js +1 -1
  26. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  27. package/dist/modules/auth/api/users/acl/route.js +2 -2
  28. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  29. package/dist/modules/auth/api/users/resend-invite/route.js +1 -1
  30. package/dist/modules/auth/api/users/resend-invite/route.js.map +2 -2
  31. package/dist/modules/auth/cli.js +12 -6
  32. package/dist/modules/auth/cli.js.map +2 -2
  33. package/dist/modules/auth/commands/users.js +1 -1
  34. package/dist/modules/auth/commands/users.js.map +2 -2
  35. package/dist/modules/auth/data/entities.js +1 -1
  36. package/dist/modules/auth/data/entities.js.map +2 -2
  37. package/dist/modules/auth/lib/setup-app.js +3 -3
  38. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  39. package/dist/modules/auth/services/authService.js +2 -2
  40. package/dist/modules/auth/services/authService.js.map +2 -2
  41. package/dist/modules/business_rules/api/rules/route.js +3 -3
  42. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  43. package/dist/modules/business_rules/api/sets/[id]/members/route.js +7 -4
  44. package/dist/modules/business_rules/api/sets/[id]/members/route.js.map +2 -2
  45. package/dist/modules/business_rules/api/sets/route.js +3 -3
  46. package/dist/modules/business_rules/api/sets/route.js.map +2 -2
  47. package/dist/modules/business_rules/cli.js +1 -1
  48. package/dist/modules/business_rules/cli.js.map +2 -2
  49. package/dist/modules/business_rules/data/entities.js +2 -9
  50. package/dist/modules/business_rules/data/entities.js.map +2 -2
  51. package/dist/modules/business_rules/lib/rule-engine.js +1 -1
  52. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  53. package/dist/modules/catalog/api/option-schemas/route.js +0 -1
  54. package/dist/modules/catalog/api/option-schemas/route.js.map +2 -2
  55. package/dist/modules/catalog/data/entities.js +2 -11
  56. package/dist/modules/catalog/data/entities.js.map +2 -2
  57. package/dist/modules/configs/data/entities.js +2 -1
  58. package/dist/modules/configs/data/entities.js.map +2 -2
  59. package/dist/modules/currencies/commands/fetch-configs.js +3 -3
  60. package/dist/modules/currencies/commands/fetch-configs.js.map +2 -2
  61. package/dist/modules/currencies/data/entities.js +1 -1
  62. package/dist/modules/currencies/data/entities.js.map +2 -2
  63. package/dist/modules/customer_accounts/api/signup.js +1 -1
  64. package/dist/modules/customer_accounts/api/signup.js.map +2 -2
  65. package/dist/modules/customer_accounts/data/entities.js +1 -1
  66. package/dist/modules/customer_accounts/data/entities.js.map +2 -2
  67. package/dist/modules/customer_accounts/services/customerInvitationService.js +1 -1
  68. package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
  69. package/dist/modules/customer_accounts/services/customerSessionService.js +1 -1
  70. package/dist/modules/customer_accounts/services/customerSessionService.js.map +2 -2
  71. package/dist/modules/customer_accounts/services/customerTokenService.js +12 -7
  72. package/dist/modules/customer_accounts/services/customerTokenService.js.map +2 -2
  73. package/dist/modules/customers/api/interactions/conflicts/route.js +19 -17
  74. package/dist/modules/customers/api/interactions/conflicts/route.js.map +2 -2
  75. package/dist/modules/customers/api/interactions/counts/route.js +7 -6
  76. package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
  77. package/dist/modules/customers/api/interactions/route.js +28 -42
  78. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  79. package/dist/modules/customers/api/utils.js +29 -24
  80. package/dist/modules/customers/api/utils.js.map +2 -2
  81. package/dist/modules/customers/cli.js +45 -40
  82. package/dist/modules/customers/cli.js.map +2 -2
  83. package/dist/modules/customers/commands/dictionaries.js +1 -1
  84. package/dist/modules/customers/commands/dictionaries.js.map +2 -2
  85. package/dist/modules/customers/commands/tags.js +1 -1
  86. package/dist/modules/customers/commands/tags.js.map +2 -2
  87. package/dist/modules/customers/data/entities.js +2 -12
  88. package/dist/modules/customers/data/entities.js.map +2 -2
  89. package/dist/modules/customers/lib/interactionProjection.js +18 -15
  90. package/dist/modules/customers/lib/interactionProjection.js.map +2 -2
  91. package/dist/modules/customers/lib/personCompanyLinkTable.js +6 -8
  92. package/dist/modules/customers/lib/personCompanyLinkTable.js.map +2 -2
  93. package/dist/modules/dashboards/api/roles/widgets/route.js +1 -1
  94. package/dist/modules/dashboards/api/roles/widgets/route.js.map +2 -2
  95. package/dist/modules/dashboards/api/users/widgets/route.js +1 -1
  96. package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
  97. package/dist/modules/dashboards/data/entities.js +1 -1
  98. package/dist/modules/dashboards/data/entities.js.map +1 -1
  99. package/dist/modules/data_sync/api/mappings/route.js +1 -1
  100. package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
  101. package/dist/modules/data_sync/data/entities.js +2 -1
  102. package/dist/modules/data_sync/data/entities.js.map +2 -2
  103. package/dist/modules/data_sync/lib/id-mapping.js +1 -1
  104. package/dist/modules/data_sync/lib/id-mapping.js.map +2 -2
  105. package/dist/modules/data_sync/lib/sync-run-service.js +1 -1
  106. package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
  107. package/dist/modules/dictionaries/commands/factory.js +1 -1
  108. package/dist/modules/dictionaries/commands/factory.js.map +2 -2
  109. package/dist/modules/dictionaries/data/entities.js +2 -9
  110. package/dist/modules/dictionaries/data/entities.js.map +2 -2
  111. package/dist/modules/directory/commands/organizations.js +4 -4
  112. package/dist/modules/directory/commands/organizations.js.map +2 -2
  113. package/dist/modules/directory/data/entities.js +2 -1
  114. package/dist/modules/directory/data/entities.js.map +2 -2
  115. package/dist/modules/entities/api/definitions.js +2 -2
  116. package/dist/modules/entities/api/definitions.js.map +2 -2
  117. package/dist/modules/entities/api/encryption.js +2 -2
  118. package/dist/modules/entities/api/encryption.js.map +2 -2
  119. package/dist/modules/entities/api/relations/options.js +2 -2
  120. package/dist/modules/entities/api/relations/options.js.map +2 -2
  121. package/dist/modules/entities/cli.js +4 -4
  122. package/dist/modules/entities/cli.js.map +2 -2
  123. package/dist/modules/entities/data/entities.js +1 -1
  124. package/dist/modules/entities/data/entities.js.map +2 -2
  125. package/dist/modules/entities/lib/field-definitions.js +2 -2
  126. package/dist/modules/entities/lib/field-definitions.js.map +2 -2
  127. package/dist/modules/entities/lib/register.js +1 -1
  128. package/dist/modules/entities/lib/register.js.map +2 -2
  129. package/dist/modules/feature_toggles/data/entities.js +2 -9
  130. package/dist/modules/feature_toggles/data/entities.js.map +2 -2
  131. package/dist/modules/inbox_ops/api/proposals/counts/route.js +3 -6
  132. package/dist/modules/inbox_ops/api/proposals/counts/route.js.map +2 -2
  133. package/dist/modules/inbox_ops/data/entities.js +2 -8
  134. package/dist/modules/inbox_ops/data/entities.js.map +2 -2
  135. package/dist/modules/inbox_ops/lib/messagesIntegration.js +6 -6
  136. package/dist/modules/inbox_ops/lib/messagesIntegration.js.map +2 -2
  137. package/dist/modules/integrations/data/entities.js +2 -1
  138. package/dist/modules/integrations/data/entities.js.map +2 -2
  139. package/dist/modules/integrations/lib/credentials-service.js +1 -1
  140. package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
  141. package/dist/modules/integrations/lib/log-service.js +1 -1
  142. package/dist/modules/integrations/lib/log-service.js.map +2 -2
  143. package/dist/modules/integrations/lib/state-service.js +1 -1
  144. package/dist/modules/integrations/lib/state-service.js.map +2 -2
  145. package/dist/modules/messages/api/route.js +90 -93
  146. package/dist/modules/messages/api/route.js.map +2 -2
  147. package/dist/modules/messages/api/unread-count/route.js +8 -7
  148. package/dist/modules/messages/api/unread-count/route.js.map +2 -2
  149. package/dist/modules/messages/commands/confirmations.js +1 -1
  150. package/dist/modules/messages/commands/confirmations.js.map +2 -2
  151. package/dist/modules/messages/commands/messages.js +3 -3
  152. package/dist/modules/messages/commands/messages.js.map +2 -2
  153. package/dist/modules/messages/data/entities.js +2 -1
  154. package/dist/modules/messages/data/entities.js.map +2 -2
  155. package/dist/modules/messages/lib/email-sender.js +1 -1
  156. package/dist/modules/messages/lib/email-sender.js.map +2 -2
  157. package/dist/modules/messages/lib/searchLookup.js +8 -8
  158. package/dist/modules/messages/lib/searchLookup.js.map +2 -2
  159. package/dist/modules/messages/lib/tokenConsumption.js +9 -4
  160. package/dist/modules/messages/lib/tokenConsumption.js.map +2 -2
  161. package/dist/modules/notifications/data/entities.js +2 -1
  162. package/dist/modules/notifications/data/entities.js.map +2 -2
  163. package/dist/modules/notifications/lib/notificationRecipients.js +15 -5
  164. package/dist/modules/notifications/lib/notificationRecipients.js.map +2 -2
  165. package/dist/modules/notifications/lib/notificationService.js +39 -34
  166. package/dist/modules/notifications/lib/notificationService.js.map +2 -2
  167. package/dist/modules/notifications/workers/create-notification.worker.js +14 -13
  168. package/dist/modules/notifications/workers/create-notification.worker.js.map +2 -2
  169. package/dist/modules/payment_gateways/api/transactions/route.js +2 -2
  170. package/dist/modules/payment_gateways/api/transactions/route.js.map +2 -2
  171. package/dist/modules/payment_gateways/data/entities.js +2 -1
  172. package/dist/modules/payment_gateways/data/entities.js.map +2 -2
  173. package/dist/modules/payment_gateways/lib/gateway-service.js +1 -1
  174. package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
  175. package/dist/modules/payment_gateways/lib/webhook-utils.js +2 -2
  176. package/dist/modules/payment_gateways/lib/webhook-utils.js.map +2 -2
  177. package/dist/modules/perspectives/data/entities.js +1 -1
  178. package/dist/modules/perspectives/data/entities.js.map +2 -2
  179. package/dist/modules/planner/data/entities.js +1 -1
  180. package/dist/modules/planner/data/entities.js.map +2 -2
  181. package/dist/modules/progress/data/entities.js +2 -1
  182. package/dist/modules/progress/data/entities.js.map +2 -2
  183. package/dist/modules/progress/lib/progressServiceImpl.js +1 -1
  184. package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
  185. package/dist/modules/query_index/api/status.js +66 -57
  186. package/dist/modules/query_index/api/status.js.map +2 -2
  187. package/dist/modules/query_index/cli.js +39 -24
  188. package/dist/modules/query_index/cli.js.map +2 -2
  189. package/dist/modules/query_index/data/entities.js +1 -1
  190. package/dist/modules/query_index/data/entities.js.map +2 -2
  191. package/dist/modules/query_index/di.js +25 -13
  192. package/dist/modules/query_index/di.js.map +2 -2
  193. package/dist/modules/query_index/lib/batch.js +31 -33
  194. package/dist/modules/query_index/lib/batch.js.map +2 -2
  195. package/dist/modules/query_index/lib/coverage.js +63 -50
  196. package/dist/modules/query_index/lib/coverage.js.map +2 -2
  197. package/dist/modules/query_index/lib/engine.js +592 -588
  198. package/dist/modules/query_index/lib/engine.js.map +2 -2
  199. package/dist/modules/query_index/lib/indexer.js +74 -47
  200. package/dist/modules/query_index/lib/indexer.js.map +2 -2
  201. package/dist/modules/query_index/lib/jobs.js +37 -24
  202. package/dist/modules/query_index/lib/jobs.js.map +2 -2
  203. package/dist/modules/query_index/lib/purge.js +19 -11
  204. package/dist/modules/query_index/lib/purge.js.map +2 -2
  205. package/dist/modules/query_index/lib/reindexer.js +47 -44
  206. package/dist/modules/query_index/lib/reindexer.js.map +2 -2
  207. package/dist/modules/query_index/lib/search-tokens.js +47 -25
  208. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  209. package/dist/modules/query_index/lib/stale.js +14 -12
  210. package/dist/modules/query_index/lib/stale.js.map +2 -2
  211. package/dist/modules/query_index/lib/subscriber-scope.js +2 -2
  212. package/dist/modules/query_index/lib/subscriber-scope.js.map +2 -2
  213. package/dist/modules/query_index/subscribers/delete_one.js +3 -2
  214. package/dist/modules/query_index/subscribers/delete_one.js.map +2 -2
  215. package/dist/modules/resources/commands/tag-assignments.js +1 -1
  216. package/dist/modules/resources/commands/tag-assignments.js.map +2 -2
  217. package/dist/modules/resources/commands/tags.js +1 -1
  218. package/dist/modules/resources/commands/tags.js.map +2 -2
  219. package/dist/modules/resources/data/entities.js +2 -1
  220. package/dist/modules/resources/data/entities.js.map +2 -2
  221. package/dist/modules/sales/commands/documentAddresses.js +2 -2
  222. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  223. package/dist/modules/sales/commands/notes.js.map +2 -2
  224. package/dist/modules/sales/commands/tags.js +1 -1
  225. package/dist/modules/sales/commands/tags.js.map +2 -2
  226. package/dist/modules/sales/data/enrichers.js +9 -8
  227. package/dist/modules/sales/data/enrichers.js.map +2 -2
  228. package/dist/modules/sales/data/entities.js +2 -11
  229. package/dist/modules/sales/data/entities.js.map +2 -2
  230. package/dist/modules/shipping_carriers/data/entities.js +2 -1
  231. package/dist/modules/shipping_carriers/data/entities.js.map +2 -2
  232. package/dist/modules/shipping_carriers/lib/shipping-service.js +1 -1
  233. package/dist/modules/shipping_carriers/lib/shipping-service.js.map +2 -2
  234. package/dist/modules/shipping_carriers/lib/webhook-utils.js +2 -2
  235. package/dist/modules/shipping_carriers/lib/webhook-utils.js.map +2 -2
  236. package/dist/modules/staff/data/entities.js +1 -1
  237. package/dist/modules/staff/data/entities.js.map +2 -2
  238. package/dist/modules/translations/api/[entityType]/[entityId]/route.js +3 -5
  239. package/dist/modules/translations/api/[entityType]/[entityId]/route.js.map +2 -2
  240. package/dist/modules/translations/api/context.js +2 -2
  241. package/dist/modules/translations/api/context.js.map +2 -2
  242. package/dist/modules/translations/commands/translations.js +46 -39
  243. package/dist/modules/translations/commands/translations.js.map +2 -2
  244. package/dist/modules/translations/components/TranslationManager.js +19 -10
  245. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  246. package/dist/modules/translations/data/entities.js +1 -1
  247. package/dist/modules/translations/data/entities.js.map +2 -2
  248. package/dist/modules/translations/lib/apply.js +4 -4
  249. package/dist/modules/translations/lib/apply.js.map +2 -2
  250. package/dist/modules/translations/lib/batch.js +3 -2
  251. package/dist/modules/translations/lib/batch.js.map +2 -2
  252. package/dist/modules/translations/subscribers/cleanup.js +3 -5
  253. package/dist/modules/translations/subscribers/cleanup.js.map +2 -2
  254. package/dist/modules/workflows/api/definitions/route.js +1 -1
  255. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  256. package/dist/modules/workflows/cli.js +5 -5
  257. package/dist/modules/workflows/cli.js.map +2 -2
  258. package/dist/modules/workflows/data/entities.js +2 -1
  259. package/dist/modules/workflows/data/entities.js.map +2 -2
  260. package/dist/modules/workflows/lib/event-logger.js +2 -2
  261. package/dist/modules/workflows/lib/event-logger.js.map +2 -2
  262. package/dist/modules/workflows/lib/seeds.js +16 -1
  263. package/dist/modules/workflows/lib/seeds.js.map +2 -2
  264. package/dist/modules/workflows/lib/step-handler.js +3 -3
  265. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  266. package/dist/modules/workflows/lib/task-handler.js +1 -1
  267. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  268. package/dist/modules/workflows/lib/transition-handler.js +1 -1
  269. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  270. package/dist/modules/workflows/lib/workflow-executor.js +2 -2
  271. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  272. package/jest.config.cjs +4 -2
  273. package/package.json +3 -3
  274. package/src/modules/api_keys/data/entities.ts +1 -1
  275. package/src/modules/api_keys/services/apiKeyService.ts +5 -5
  276. package/src/modules/attachments/api/library/[id]/route.ts +1 -1
  277. package/src/modules/attachments/api/library/route.ts +10 -12
  278. package/src/modules/attachments/api/partitions/route.ts +3 -3
  279. package/src/modules/attachments/api/route.ts +10 -8
  280. package/src/modules/attachments/api/transfer/route.ts +1 -1
  281. package/src/modules/attachments/data/entities.ts +2 -1
  282. package/src/modules/attachments/lib/ocrQueue.ts +1 -1
  283. package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +4 -4
  284. package/src/modules/audit_logs/api/audit-logs/actions/route.ts +4 -4
  285. package/src/modules/audit_logs/data/entities.ts +1 -1
  286. package/src/modules/audit_logs/services/actionLogService.ts +96 -87
  287. package/src/modules/auth/api/roles/acl/route.ts +1 -1
  288. package/src/modules/auth/api/users/acl/route.ts +2 -2
  289. package/src/modules/auth/api/users/resend-invite/route.ts +1 -1
  290. package/src/modules/auth/cli.ts +46 -40
  291. package/src/modules/auth/commands/users.ts +1 -1
  292. package/src/modules/auth/data/entities.ts +1 -1
  293. package/src/modules/auth/lib/setup-app.ts +3 -3
  294. package/src/modules/auth/services/authService.ts +2 -2
  295. package/src/modules/business_rules/api/rules/route.ts +3 -3
  296. package/src/modules/business_rules/api/sets/[id]/members/route.ts +7 -4
  297. package/src/modules/business_rules/api/sets/route.ts +3 -3
  298. package/src/modules/business_rules/cli.ts +1 -1
  299. package/src/modules/business_rules/data/entities.ts +2 -9
  300. package/src/modules/business_rules/lib/rule-engine.ts +1 -1
  301. package/src/modules/catalog/api/option-schemas/route.ts +0 -1
  302. package/src/modules/catalog/data/entities.ts +2 -11
  303. package/src/modules/configs/data/entities.ts +2 -1
  304. package/src/modules/currencies/commands/fetch-configs.ts +3 -3
  305. package/src/modules/currencies/data/entities.ts +1 -1
  306. package/src/modules/customer_accounts/api/signup.ts +1 -1
  307. package/src/modules/customer_accounts/data/entities.ts +1 -1
  308. package/src/modules/customer_accounts/services/customerInvitationService.ts +1 -1
  309. package/src/modules/customer_accounts/services/customerSessionService.ts +1 -1
  310. package/src/modules/customer_accounts/services/customerTokenService.ts +26 -15
  311. package/src/modules/customers/api/interactions/conflicts/route.ts +26 -23
  312. package/src/modules/customers/api/interactions/counts/route.ts +13 -11
  313. package/src/modules/customers/api/interactions/route.ts +32 -44
  314. package/src/modules/customers/api/utils.ts +45 -37
  315. package/src/modules/customers/cli.ts +88 -67
  316. package/src/modules/customers/commands/dictionaries.ts +1 -1
  317. package/src/modules/customers/commands/tags.ts +1 -1
  318. package/src/modules/customers/data/entities.ts +2 -12
  319. package/src/modules/customers/lib/interactionProjection.ts +36 -25
  320. package/src/modules/customers/lib/personCompanyLinkTable.ts +13 -18
  321. package/src/modules/dashboards/api/roles/widgets/route.ts +1 -1
  322. package/src/modules/dashboards/api/users/widgets/route.ts +1 -1
  323. package/src/modules/dashboards/data/entities.ts +1 -1
  324. package/src/modules/data_sync/api/mappings/route.ts +1 -1
  325. package/src/modules/data_sync/data/entities.ts +2 -1
  326. package/src/modules/data_sync/lib/id-mapping.ts +1 -1
  327. package/src/modules/data_sync/lib/sync-run-service.ts +1 -1
  328. package/src/modules/dictionaries/commands/factory.ts +1 -1
  329. package/src/modules/dictionaries/data/entities.ts +2 -9
  330. package/src/modules/directory/commands/organizations.ts +4 -4
  331. package/src/modules/directory/data/entities.ts +2 -1
  332. package/src/modules/entities/api/definitions.ts +2 -2
  333. package/src/modules/entities/api/encryption.ts +2 -2
  334. package/src/modules/entities/api/relations/options.ts +8 -3
  335. package/src/modules/entities/cli.ts +4 -4
  336. package/src/modules/entities/data/entities.ts +1 -1
  337. package/src/modules/entities/lib/field-definitions.ts +2 -2
  338. package/src/modules/entities/lib/register.ts +1 -1
  339. package/src/modules/feature_toggles/data/entities.ts +2 -9
  340. package/src/modules/inbox_ops/api/proposals/counts/route.ts +10 -10
  341. package/src/modules/inbox_ops/data/entities.ts +2 -8
  342. package/src/modules/inbox_ops/lib/messagesIntegration.ts +12 -11
  343. package/src/modules/integrations/data/entities.ts +2 -1
  344. package/src/modules/integrations/lib/credentials-service.ts +1 -1
  345. package/src/modules/integrations/lib/log-service.ts +1 -1
  346. package/src/modules/integrations/lib/state-service.ts +1 -1
  347. package/src/modules/messages/api/route.ts +134 -123
  348. package/src/modules/messages/api/unread-count/route.ts +19 -16
  349. package/src/modules/messages/commands/confirmations.ts +1 -1
  350. package/src/modules/messages/commands/messages.ts +3 -3
  351. package/src/modules/messages/data/entities.ts +2 -1
  352. package/src/modules/messages/lib/email-sender.ts +1 -1
  353. package/src/modules/messages/lib/searchLookup.ts +16 -13
  354. package/src/modules/messages/lib/tokenConsumption.ts +16 -8
  355. package/src/modules/notifications/data/entities.ts +2 -1
  356. package/src/modules/notifications/lib/notificationRecipients.ts +42 -26
  357. package/src/modules/notifications/lib/notificationService.ts +53 -42
  358. package/src/modules/notifications/workers/create-notification.worker.ts +20 -17
  359. package/src/modules/payment_gateways/api/transactions/route.ts +2 -2
  360. package/src/modules/payment_gateways/data/entities.ts +2 -1
  361. package/src/modules/payment_gateways/lib/gateway-service.ts +1 -1
  362. package/src/modules/payment_gateways/lib/webhook-utils.ts +2 -2
  363. package/src/modules/perspectives/data/entities.ts +1 -1
  364. package/src/modules/planner/data/entities.ts +1 -1
  365. package/src/modules/progress/data/entities.ts +2 -1
  366. package/src/modules/progress/lib/progressServiceImpl.ts +1 -1
  367. package/src/modules/query_index/api/status.ts +85 -71
  368. package/src/modules/query_index/cli.ts +51 -31
  369. package/src/modules/query_index/data/entities.ts +1 -1
  370. package/src/modules/query_index/di.ts +41 -16
  371. package/src/modules/query_index/lib/batch.ts +68 -55
  372. package/src/modules/query_index/lib/coverage.ts +115 -88
  373. package/src/modules/query_index/lib/engine.ts +1036 -1096
  374. package/src/modules/query_index/lib/indexer.ts +115 -79
  375. package/src/modules/query_index/lib/jobs.ts +51 -31
  376. package/src/modules/query_index/lib/purge.ts +25 -19
  377. package/src/modules/query_index/lib/reindexer.ts +97 -84
  378. package/src/modules/query_index/lib/search-tokens.ts +67 -36
  379. package/src/modules/query_index/lib/stale.ts +14 -17
  380. package/src/modules/query_index/lib/subscriber-scope.ts +6 -5
  381. package/src/modules/query_index/subscribers/delete_one.ts +9 -6
  382. package/src/modules/resources/commands/tag-assignments.ts +1 -1
  383. package/src/modules/resources/commands/tags.ts +1 -1
  384. package/src/modules/resources/data/entities.ts +2 -1
  385. package/src/modules/sales/commands/documentAddresses.ts +2 -2
  386. package/src/modules/sales/commands/notes.ts +1 -1
  387. package/src/modules/sales/commands/tags.ts +1 -1
  388. package/src/modules/sales/data/enrichers.ts +17 -13
  389. package/src/modules/sales/data/entities.ts +2 -11
  390. package/src/modules/shipping_carriers/data/entities.ts +2 -1
  391. package/src/modules/shipping_carriers/lib/shipping-service.ts +1 -1
  392. package/src/modules/shipping_carriers/lib/webhook-utils.ts +2 -2
  393. package/src/modules/staff/data/entities.ts +1 -1
  394. package/src/modules/translations/api/[entityType]/[entityId]/route.ts +14 -11
  395. package/src/modules/translations/api/context.ts +4 -4
  396. package/src/modules/translations/commands/translations.ts +116 -81
  397. package/src/modules/translations/components/TranslationManager.tsx +23 -14
  398. package/src/modules/translations/data/entities.ts +1 -1
  399. package/src/modules/translations/i18n/de.json +1 -0
  400. package/src/modules/translations/i18n/en.json +1 -0
  401. package/src/modules/translations/i18n/es.json +1 -0
  402. package/src/modules/translations/i18n/pl.json +1 -0
  403. package/src/modules/translations/lib/apply.ts +6 -6
  404. package/src/modules/translations/lib/batch.ts +9 -7
  405. package/src/modules/translations/subscribers/cleanup.ts +10 -11
  406. package/src/modules/workflows/api/definitions/route.ts +1 -1
  407. package/src/modules/workflows/cli.ts +5 -5
  408. package/src/modules/workflows/data/entities.ts +2 -1
  409. package/src/modules/workflows/lib/event-logger.ts +2 -2
  410. package/src/modules/workflows/lib/seeds.ts +16 -1
  411. package/src/modules/workflows/lib/step-handler.ts +3 -3
  412. package/src/modules/workflows/lib/task-handler.ts +1 -1
  413. package/src/modules/workflows/lib/transition-handler.ts +1 -1
  414. package/src/modules/workflows/lib/workflow-executor.ts +2 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/auth/api/users/acl/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { logCrudAccess } from '@open-mercato/shared/lib/crud/factory'\nimport { forbidden } from '@open-mercato/shared/lib/crud/errors'\nimport { UserAcl } from '@open-mercato/core/modules/auth/data/entities'\n\nconst getSchema = z.object({ userId: z.string().uuid() })\nconst putSchema = z.object({\n userId: z.string().uuid(),\n isSuperAdmin: z.boolean().optional(),\n features: z.array(z.string()).optional(),\n organizations: z.array(z.string()).nullable().optional(),\n})\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['auth.acl.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['auth.acl.manage'] },\n}\n\nconst userAclResponseSchema = z.object({\n hasCustomAcl: z.boolean(),\n isSuperAdmin: z.boolean(),\n features: z.array(z.string()),\n organizations: z.array(z.string()).nullable(),\n})\n\nconst userAclUpdateResponseSchema = z.object({\n ok: z.literal(true),\n sanitized: z.boolean(),\n})\n\nconst userAclErrorSchema = z.object({ error: z.string() })\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n const url = new URL(req.url)\n const parsed = getSchema.safeParse({ userId: url.searchParams.get('userId') })\n if (!parsed.success) return NextResponse.json({ error: 'Invalid input' }, { status: 400 })\n const container = await createRequestContainer()\n const em = container.resolve('em') as any\n const acl = await em.findOne(UserAcl, { user: parsed.data.userId as any, tenantId: auth.tenantId as any })\n const response = acl\n ? {\n hasCustomAcl: true,\n isSuperAdmin: !!acl.isSuperAdmin,\n features: Array.isArray(acl.featuresJson) ? acl.featuresJson : [],\n organizations: Array.isArray(acl.organizationsJson) ? acl.organizationsJson : null,\n }\n : { hasCustomAcl: false, isSuperAdmin: false, features: [], organizations: null }\n\n await logCrudAccess({\n container,\n auth,\n request: req,\n items: [{ id: parsed.data.userId, ...response }],\n idField: 'id',\n resourceKind: 'auth.user_acl',\n organizationId: auth.orgId ?? null,\n tenantId: auth.tenantId ?? null,\n query: { userId: parsed.data.userId },\n accessType: 'read:item',\n })\n\n return NextResponse.json(response)\n}\n\nexport async function PUT(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n const body = await req.json().catch(() => ({}))\n const parsed = putSchema.safeParse(body)\n if (!parsed.success) return NextResponse.json({ error: 'Invalid input' }, { status: 400 })\n const container = await createRequestContainer()\n const em = container.resolve('em') as any\n const rbacService = container.resolve('rbacService') as any\n\n const actorAcl = auth.sub\n ? await rbacService.loadAcl(auth.sub, { tenantId: auth.tenantId ?? null, organizationId: auth.orgId ?? null })\n : null\n const actorIsSuperAdmin = !!actorAcl?.isSuperAdmin\n\n const requestedFeatures = normalizeFeatureList(parsed.data.features)\n const organizations = Array.isArray(parsed.data.organizations) ? parsed.data.organizations : null\n\n let acl = await em.findOne(UserAcl, { user: parsed.data.userId as any, tenantId: auth.tenantId as any })\n const existingIsSuperAdmin = acl ? !!acl.isSuperAdmin : false\n const existingFeatures = acl && Array.isArray(acl.featuresJson) ? normalizeFeatureList(acl.featuresJson) : []\n\n const effectiveFeatures = actorIsSuperAdmin\n ? requestedFeatures\n : sanitizeTenantFeatures(requestedFeatures)\n\n const requestedIsSuperAdmin = parsed.data.isSuperAdmin ?? false\n let effectiveIsSuperAdmin = requestedIsSuperAdmin\n\n if (!actorIsSuperAdmin) {\n if (requestedIsSuperAdmin && !existingIsSuperAdmin) {\n throw forbidden('Only super administrators can grant super admin access.')\n }\n if (existingIsSuperAdmin && requestedIsSuperAdmin === false) {\n effectiveIsSuperAdmin = false\n } else {\n effectiveIsSuperAdmin = existingIsSuperAdmin\n }\n }\n\n const hasCustomAcl = effectiveIsSuperAdmin || effectiveFeatures.length > 0\n\n if (!hasCustomAcl) {\n if (acl) await em.removeAndFlush(acl)\n } else {\n if (!acl) {\n acl = em.create(UserAcl, { user: parsed.data.userId as any, tenantId: auth.tenantId as any })\n }\n const aclRecord = acl as any\n aclRecord.isSuperAdmin = effectiveIsSuperAdmin\n aclRecord.featuresJson = effectiveFeatures\n aclRecord.organizationsJson = organizations\n await em.persistAndFlush(acl)\n }\n\n // Invalidate cache for this user\n await rbacService.invalidateUserCache(parsed.data.userId)\n try {\n const cache = container.resolve('cache') as any\n if (cache) await cache.deleteByTags([`rbac:user:${parsed.data.userId}`])\n } catch {}\n\n return NextResponse.json({\n ok: true,\n sanitized: !actorIsSuperAdmin && (hasRestrictedChanges(requestedFeatures, effectiveFeatures, existingFeatures) || requestedIsSuperAdmin !== effectiveIsSuperAdmin),\n })\n}\n\nfunction normalizeFeatureList(features: unknown): string[] {\n if (!Array.isArray(features)) return []\n const dedup = new Set<string>()\n for (const value of features) {\n if (typeof value !== 'string') continue\n const trimmed = value.trim()\n if (!trimmed) continue\n dedup.add(trimmed)\n }\n return Array.from(dedup)\n}\n\nfunction sanitizeTenantFeatures(features: string[]): string[] {\n return features.filter((feature) => !isTenantRestrictedFeature(feature))\n}\n\nfunction isTenantRestrictedFeature(feature: string): boolean {\n if (feature === '*' || feature === 'directory.*') return true\n if (feature.startsWith('directory.tenants')) return true\n return false\n}\n\nfunction hasRestrictedChanges(requested: string[], effective: string[], existing: string[]): boolean {\n if (requested.length === effective.length) return false\n const effectiveSet = new Set(effective)\n const existingSet = new Set(existing)\n // If the effective set matches existing, we only trimmed restricted duplicates and should not report\n if (effectiveSet.size === existingSet.size) {\n let identical = true\n for (const value of effectiveSet) {\n if (!existingSet.has(value)) {\n identical = false\n break\n }\n }\n if (identical) return false\n }\n return true\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Authentication & Accounts',\n summary: 'User ACL management',\n methods: {\n GET: {\n summary: 'Fetch user ACL',\n description: 'Returns custom ACL overrides for a user within the current tenant, if any.',\n query: getSchema,\n responses: [\n { status: 200, description: 'User ACL entry', schema: userAclResponseSchema },\n { status: 400, description: 'Invalid user id', schema: userAclErrorSchema },\n { status: 401, description: 'Unauthorized', schema: userAclErrorSchema },\n ],\n },\n PUT: {\n summary: 'Update user ACL',\n description: 'Configures per-user ACL overrides, including super admin access, feature list, and organization scope.',\n requestBody: {\n contentType: 'application/json',\n schema: putSchema,\n },\n responses: [\n { status: 200, description: 'User ACL updated', schema: userAclUpdateResponseSchema },\n { status: 400, description: 'Invalid payload', schema: userAclErrorSchema },\n { status: 401, description: 'Unauthorized', schema: userAclErrorSchema },\n { status: 403, description: 'Insufficient privileges to modify ACL', schema: userAclErrorSchema },\n ],\n },\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { logCrudAccess } from '@open-mercato/shared/lib/crud/factory'\nimport { forbidden } from '@open-mercato/shared/lib/crud/errors'\nimport { UserAcl } from '@open-mercato/core/modules/auth/data/entities'\n\nconst getSchema = z.object({ userId: z.string().uuid() })\nconst putSchema = z.object({\n userId: z.string().uuid(),\n isSuperAdmin: z.boolean().optional(),\n features: z.array(z.string()).optional(),\n organizations: z.array(z.string()).nullable().optional(),\n})\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['auth.acl.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['auth.acl.manage'] },\n}\n\nconst userAclResponseSchema = z.object({\n hasCustomAcl: z.boolean(),\n isSuperAdmin: z.boolean(),\n features: z.array(z.string()),\n organizations: z.array(z.string()).nullable(),\n})\n\nconst userAclUpdateResponseSchema = z.object({\n ok: z.literal(true),\n sanitized: z.boolean(),\n})\n\nconst userAclErrorSchema = z.object({ error: z.string() })\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n const url = new URL(req.url)\n const parsed = getSchema.safeParse({ userId: url.searchParams.get('userId') })\n if (!parsed.success) return NextResponse.json({ error: 'Invalid input' }, { status: 400 })\n const container = await createRequestContainer()\n const em = container.resolve('em') as any\n const acl = await em.findOne(UserAcl, { user: parsed.data.userId as any, tenantId: auth.tenantId as any })\n const response = acl\n ? {\n hasCustomAcl: true,\n isSuperAdmin: !!acl.isSuperAdmin,\n features: Array.isArray(acl.featuresJson) ? acl.featuresJson : [],\n organizations: Array.isArray(acl.organizationsJson) ? acl.organizationsJson : null,\n }\n : { hasCustomAcl: false, isSuperAdmin: false, features: [], organizations: null }\n\n await logCrudAccess({\n container,\n auth,\n request: req,\n items: [{ id: parsed.data.userId, ...response }],\n idField: 'id',\n resourceKind: 'auth.user_acl',\n organizationId: auth.orgId ?? null,\n tenantId: auth.tenantId ?? null,\n query: { userId: parsed.data.userId },\n accessType: 'read:item',\n })\n\n return NextResponse.json(response)\n}\n\nexport async function PUT(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n const body = await req.json().catch(() => ({}))\n const parsed = putSchema.safeParse(body)\n if (!parsed.success) return NextResponse.json({ error: 'Invalid input' }, { status: 400 })\n const container = await createRequestContainer()\n const em = container.resolve('em') as any\n const rbacService = container.resolve('rbacService') as any\n\n const actorAcl = auth.sub\n ? await rbacService.loadAcl(auth.sub, { tenantId: auth.tenantId ?? null, organizationId: auth.orgId ?? null })\n : null\n const actorIsSuperAdmin = !!actorAcl?.isSuperAdmin\n\n const requestedFeatures = normalizeFeatureList(parsed.data.features)\n const organizations = Array.isArray(parsed.data.organizations) ? parsed.data.organizations : null\n\n let acl = await em.findOne(UserAcl, { user: parsed.data.userId as any, tenantId: auth.tenantId as any })\n const existingIsSuperAdmin = acl ? !!acl.isSuperAdmin : false\n const existingFeatures = acl && Array.isArray(acl.featuresJson) ? normalizeFeatureList(acl.featuresJson) : []\n\n const effectiveFeatures = actorIsSuperAdmin\n ? requestedFeatures\n : sanitizeTenantFeatures(requestedFeatures)\n\n const requestedIsSuperAdmin = parsed.data.isSuperAdmin ?? false\n let effectiveIsSuperAdmin = requestedIsSuperAdmin\n\n if (!actorIsSuperAdmin) {\n if (requestedIsSuperAdmin && !existingIsSuperAdmin) {\n throw forbidden('Only super administrators can grant super admin access.')\n }\n if (existingIsSuperAdmin && requestedIsSuperAdmin === false) {\n effectiveIsSuperAdmin = false\n } else {\n effectiveIsSuperAdmin = existingIsSuperAdmin\n }\n }\n\n const hasCustomAcl = effectiveIsSuperAdmin || effectiveFeatures.length > 0\n\n if (!hasCustomAcl) {\n if (acl) await em.remove(acl).flush()\n } else {\n if (!acl) {\n acl = em.create(UserAcl, { user: parsed.data.userId as any, tenantId: auth.tenantId as any })\n }\n const aclRecord = acl as any\n aclRecord.isSuperAdmin = effectiveIsSuperAdmin\n aclRecord.featuresJson = effectiveFeatures\n aclRecord.organizationsJson = organizations\n await em.persist(acl).flush()\n }\n\n // Invalidate cache for this user\n await rbacService.invalidateUserCache(parsed.data.userId)\n try {\n const cache = container.resolve('cache') as any\n if (cache) await cache.deleteByTags([`rbac:user:${parsed.data.userId}`])\n } catch {}\n\n return NextResponse.json({\n ok: true,\n sanitized: !actorIsSuperAdmin && (hasRestrictedChanges(requestedFeatures, effectiveFeatures, existingFeatures) || requestedIsSuperAdmin !== effectiveIsSuperAdmin),\n })\n}\n\nfunction normalizeFeatureList(features: unknown): string[] {\n if (!Array.isArray(features)) return []\n const dedup = new Set<string>()\n for (const value of features) {\n if (typeof value !== 'string') continue\n const trimmed = value.trim()\n if (!trimmed) continue\n dedup.add(trimmed)\n }\n return Array.from(dedup)\n}\n\nfunction sanitizeTenantFeatures(features: string[]): string[] {\n return features.filter((feature) => !isTenantRestrictedFeature(feature))\n}\n\nfunction isTenantRestrictedFeature(feature: string): boolean {\n if (feature === '*' || feature === 'directory.*') return true\n if (feature.startsWith('directory.tenants')) return true\n return false\n}\n\nfunction hasRestrictedChanges(requested: string[], effective: string[], existing: string[]): boolean {\n if (requested.length === effective.length) return false\n const effectiveSet = new Set(effective)\n const existingSet = new Set(existing)\n // If the effective set matches existing, we only trimmed restricted duplicates and should not report\n if (effectiveSet.size === existingSet.size) {\n let identical = true\n for (const value of effectiveSet) {\n if (!existingSet.has(value)) {\n identical = false\n break\n }\n }\n if (identical) return false\n }\n return true\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Authentication & Accounts',\n summary: 'User ACL management',\n methods: {\n GET: {\n summary: 'Fetch user ACL',\n description: 'Returns custom ACL overrides for a user within the current tenant, if any.',\n query: getSchema,\n responses: [\n { status: 200, description: 'User ACL entry', schema: userAclResponseSchema },\n { status: 400, description: 'Invalid user id', schema: userAclErrorSchema },\n { status: 401, description: 'Unauthorized', schema: userAclErrorSchema },\n ],\n },\n PUT: {\n summary: 'Update user ACL',\n description: 'Configures per-user ACL overrides, including super admin access, feature list, and organization scope.',\n requestBody: {\n contentType: 'application/json',\n schema: putSchema,\n },\n responses: [\n { status: 200, description: 'User ACL updated', schema: userAclUpdateResponseSchema },\n { status: 400, description: 'Invalid payload', schema: userAclErrorSchema },\n { status: 401, description: 'Unauthorized', schema: userAclErrorSchema },\n { status: 403, description: 'Insufficient privileges to modify ACL', schema: userAclErrorSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -110,7 +110,7 @@ async function POST(req) {
110
110
  const tokenHash = hashAuthToken(rawToken);
111
111
  const expiresAt = new Date(Date.now() + INVITE_TOKEN_TTL_MS);
112
112
  const row = em.create(PasswordReset, { user, token: tokenHash, expiresAt, createdAt: /* @__PURE__ */ new Date() });
113
- await em.persistAndFlush(row);
113
+ await em.persist(row).flush();
114
114
  const inviteUrl = `${base}/reset/${rawToken}`;
115
115
  const { translate } = await resolveTranslations();
116
116
  const subject = translate("auth.email.invite.subject", "You have been invited");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/auth/api/users/resend-invite/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { User, PasswordReset } from '@open-mercato/core/modules/auth/data/entities'\nimport { sendEmail } from '@open-mercato/shared/lib/email/send'\nimport InviteUserEmail from '@open-mercato/core/modules/auth/emails/InviteUserEmail'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport { readEndpointRateLimitConfig } from '@open-mercato/shared/lib/ratelimit/config'\nimport { checkAuthRateLimit } from '@open-mercato/core/modules/auth/lib/rateLimitCheck'\nimport { validateCrudMutationGuard, runCrudMutationGuardAfterSuccess } from '@open-mercato/shared/lib/crud/mutation-guard'\nimport { INVITE_TOKEN_TTL_MS } from '@open-mercato/core/modules/auth/lib/inviteToken'\nimport { getSecurityEmailBaseUrl, mapSecurityEmailUrlError } from '@open-mercato/shared/lib/url'\nimport { generateAuthToken, hashAuthToken } from '@open-mercato/core/modules/auth/lib/tokenHash'\nimport type { EntityManager } from '@mikro-orm/postgresql'\n\nconst resendInviteRateLimitConfig = readEndpointRateLimitConfig('RESEND_INVITE', {\n points: 3, duration: 300, blockDuration: 300, keyPrefix: 'resend-invite',\n})\n\nconst requestSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst responseSchema = z.object({\n ok: z.literal(true),\n})\n\nconst errorSchema = z.object({\n error: z.string(),\n})\n\nconst validationErrorSchema = z.object({\n error: z.string(),\n fieldErrors: z.record(z.string(), z.array(z.string())).optional(),\n})\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['auth.users.create'] },\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: resendInviteRateLimitConfig,\n })\n if (rateLimitError) return rateLimitError\n\n const body = await readJsonSafe(req, {})\n const parsed = requestSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json(\n { error: 'Validation failed', fieldErrors: parsed.error.flatten().fieldErrors },\n { status: 422 },\n )\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n\n let isSuperAdmin = false\n try {\n if (auth.sub) {\n const rbacService = container.resolve('rbacService') as {\n loadAcl: (userId: string, scope: { tenantId: string | null; organizationId: string | null }) => Promise<{ isSuperAdmin?: boolean } | null>\n }\n const acl = await rbacService.loadAcl(auth.sub, {\n tenantId: auth.tenantId ?? null,\n organizationId: auth.orgId ?? null,\n })\n isSuperAdmin = !!acl?.isSuperAdmin\n }\n } catch (err) {\n console.error('[auth.users.resend-invite] Failed to resolve rbac:', err)\n }\n\n const where: Record<string, unknown> = { id: parsed.data.id, deletedAt: null }\n if (!isSuperAdmin) {\n if (!auth.tenantId) return NextResponse.json({ error: 'User not found' }, { status: 404 })\n where.tenantId = auth.tenantId\n }\n\n const user = await em.findOne(User, where as any)\n if (!user) return NextResponse.json({ error: 'User not found' }, { status: 404 })\n\n if (user.passwordHash) {\n return NextResponse.json({ error: 'User already has a password' }, { status: 409 })\n }\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: user.tenantId ? String(user.tenantId) : auth.tenantId ?? '',\n organizationId: user.organizationId ? String(user.organizationId) : null,\n userId: auth.sub ?? '',\n resourceKind: 'auth.user',\n resourceId: String(user.id),\n operation: 'custom',\n requestMethod: 'POST',\n requestHeaders: req.headers,\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n let base: string\n try {\n base = getSecurityEmailBaseUrl(req.url)\n } catch (error) {\n const mapped = mapSecurityEmailUrlError(error, {\n scope: 'auth.users.resend-invite',\n configMessage: 'Invitation email is not configured',\n })\n if (mapped) return NextResponse.json(mapped.body, { status: mapped.status })\n throw error\n }\n\n await em.nativeUpdate(\n PasswordReset,\n { user: user.id, usedAt: null } as any,\n { usedAt: new Date() },\n )\n\n const rawToken = generateAuthToken()\n const tokenHash = hashAuthToken(rawToken)\n const expiresAt = new Date(Date.now() + INVITE_TOKEN_TTL_MS)\n const row = em.create(PasswordReset, { user, token: tokenHash, expiresAt, createdAt: new Date() })\n await em.persistAndFlush(row)\n\n const inviteUrl = `${base}/reset/${rawToken}`\n\n const { translate } = await resolveTranslations()\n const subject = translate('auth.email.invite.subject', 'You have been invited')\n const copy = {\n preview: translate('auth.email.invite.preview', 'Set up your account'),\n title: translate('auth.email.invite.title', 'You have been invited'),\n body: translate('auth.email.invite.body', 'An administrator has created an account for you. Click the link below to set your password. This link will expire in 48 hours.'),\n cta: translate('auth.email.invite.cta', 'Set up your password'),\n hint: translate('auth.email.invite.hint', 'If you did not expect this invitation, you can safely ignore this email.'),\n }\n\n let emailSent = true\n try {\n await sendEmail({ to: user.email, subject, react: InviteUserEmail({ inviteUrl, copy }) })\n } catch (err) {\n console.error('[auth.users.resend-invite] Failed to send invitation email:', err)\n emailSent = false\n }\n\n if (guardResult?.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: user.tenantId ? String(user.tenantId) : auth.tenantId ?? '',\n organizationId: user.organizationId ? String(user.organizationId) : null,\n userId: auth.sub ?? '',\n resourceKind: 'auth.user',\n resourceId: String(user.id),\n operation: 'custom',\n requestMethod: 'POST',\n requestHeaders: req.headers,\n metadata: guardResult.metadata,\n })\n }\n\n if (!emailSent) {\n return NextResponse.json({ ok: true, warning: 'invite_email_failed' })\n }\n\n return NextResponse.json({ ok: true })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Authentication & Accounts',\n summary: 'Resend user invite',\n methods: {\n POST: {\n summary: 'Resend invitation email',\n description: 'Resends the invitation email to a user who has not yet set up their password. Generates a new 48-hour setup token and invalidates prior tokens.',\n requestBody: {\n contentType: 'application/json',\n schema: requestSchema,\n },\n responses: [\n { status: 200, description: 'Invite email sent', schema: responseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid request origin', schema: errorSchema },\n { status: 404, description: 'User not found', schema: errorSchema },\n { status: 409, description: 'User already has a password', schema: errorSchema },\n { status: 422, description: 'Validation error', schema: validationErrorSchema },\n { status: 429, description: 'Rate limit exceeded', schema: rateLimitErrorSchema },\n { status: 500, description: 'Invitation email origin is not configured', schema: errorSchema },\n ],\n },\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { User, PasswordReset } from '@open-mercato/core/modules/auth/data/entities'\nimport { sendEmail } from '@open-mercato/shared/lib/email/send'\nimport InviteUserEmail from '@open-mercato/core/modules/auth/emails/InviteUserEmail'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport { readEndpointRateLimitConfig } from '@open-mercato/shared/lib/ratelimit/config'\nimport { checkAuthRateLimit } from '@open-mercato/core/modules/auth/lib/rateLimitCheck'\nimport { validateCrudMutationGuard, runCrudMutationGuardAfterSuccess } from '@open-mercato/shared/lib/crud/mutation-guard'\nimport { INVITE_TOKEN_TTL_MS } from '@open-mercato/core/modules/auth/lib/inviteToken'\nimport { getSecurityEmailBaseUrl, mapSecurityEmailUrlError } from '@open-mercato/shared/lib/url'\nimport { generateAuthToken, hashAuthToken } from '@open-mercato/core/modules/auth/lib/tokenHash'\nimport type { EntityManager } from '@mikro-orm/postgresql'\n\nconst resendInviteRateLimitConfig = readEndpointRateLimitConfig('RESEND_INVITE', {\n points: 3, duration: 300, blockDuration: 300, keyPrefix: 'resend-invite',\n})\n\nconst requestSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst responseSchema = z.object({\n ok: z.literal(true),\n})\n\nconst errorSchema = z.object({\n error: z.string(),\n})\n\nconst validationErrorSchema = z.object({\n error: z.string(),\n fieldErrors: z.record(z.string(), z.array(z.string())).optional(),\n})\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['auth.users.create'] },\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: resendInviteRateLimitConfig,\n })\n if (rateLimitError) return rateLimitError\n\n const body = await readJsonSafe(req, {})\n const parsed = requestSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json(\n { error: 'Validation failed', fieldErrors: parsed.error.flatten().fieldErrors },\n { status: 422 },\n )\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n\n let isSuperAdmin = false\n try {\n if (auth.sub) {\n const rbacService = container.resolve('rbacService') as {\n loadAcl: (userId: string, scope: { tenantId: string | null; organizationId: string | null }) => Promise<{ isSuperAdmin?: boolean } | null>\n }\n const acl = await rbacService.loadAcl(auth.sub, {\n tenantId: auth.tenantId ?? null,\n organizationId: auth.orgId ?? null,\n })\n isSuperAdmin = !!acl?.isSuperAdmin\n }\n } catch (err) {\n console.error('[auth.users.resend-invite] Failed to resolve rbac:', err)\n }\n\n const where: Record<string, unknown> = { id: parsed.data.id, deletedAt: null }\n if (!isSuperAdmin) {\n if (!auth.tenantId) return NextResponse.json({ error: 'User not found' }, { status: 404 })\n where.tenantId = auth.tenantId\n }\n\n const user = await em.findOne(User, where as any)\n if (!user) return NextResponse.json({ error: 'User not found' }, { status: 404 })\n\n if (user.passwordHash) {\n return NextResponse.json({ error: 'User already has a password' }, { status: 409 })\n }\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: user.tenantId ? String(user.tenantId) : auth.tenantId ?? '',\n organizationId: user.organizationId ? String(user.organizationId) : null,\n userId: auth.sub ?? '',\n resourceKind: 'auth.user',\n resourceId: String(user.id),\n operation: 'custom',\n requestMethod: 'POST',\n requestHeaders: req.headers,\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n let base: string\n try {\n base = getSecurityEmailBaseUrl(req.url)\n } catch (error) {\n const mapped = mapSecurityEmailUrlError(error, {\n scope: 'auth.users.resend-invite',\n configMessage: 'Invitation email is not configured',\n })\n if (mapped) return NextResponse.json(mapped.body, { status: mapped.status })\n throw error\n }\n\n await em.nativeUpdate(\n PasswordReset,\n { user: user.id, usedAt: null } as any,\n { usedAt: new Date() },\n )\n\n const rawToken = generateAuthToken()\n const tokenHash = hashAuthToken(rawToken)\n const expiresAt = new Date(Date.now() + INVITE_TOKEN_TTL_MS)\n const row = em.create(PasswordReset, { user, token: tokenHash, expiresAt, createdAt: new Date() })\n await em.persist(row).flush()\n\n const inviteUrl = `${base}/reset/${rawToken}`\n\n const { translate } = await resolveTranslations()\n const subject = translate('auth.email.invite.subject', 'You have been invited')\n const copy = {\n preview: translate('auth.email.invite.preview', 'Set up your account'),\n title: translate('auth.email.invite.title', 'You have been invited'),\n body: translate('auth.email.invite.body', 'An administrator has created an account for you. Click the link below to set your password. This link will expire in 48 hours.'),\n cta: translate('auth.email.invite.cta', 'Set up your password'),\n hint: translate('auth.email.invite.hint', 'If you did not expect this invitation, you can safely ignore this email.'),\n }\n\n let emailSent = true\n try {\n await sendEmail({ to: user.email, subject, react: InviteUserEmail({ inviteUrl, copy }) })\n } catch (err) {\n console.error('[auth.users.resend-invite] Failed to send invitation email:', err)\n emailSent = false\n }\n\n if (guardResult?.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: user.tenantId ? String(user.tenantId) : auth.tenantId ?? '',\n organizationId: user.organizationId ? String(user.organizationId) : null,\n userId: auth.sub ?? '',\n resourceKind: 'auth.user',\n resourceId: String(user.id),\n operation: 'custom',\n requestMethod: 'POST',\n requestHeaders: req.headers,\n metadata: guardResult.metadata,\n })\n }\n\n if (!emailSent) {\n return NextResponse.json({ ok: true, warning: 'invite_email_failed' })\n }\n\n return NextResponse.json({ ok: true })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Authentication & Accounts',\n summary: 'Resend user invite',\n methods: {\n POST: {\n summary: 'Resend invitation email',\n description: 'Resends the invitation email to a user who has not yet set up their password. Generates a new 48-hour setup token and invalidates prior tokens.',\n requestBody: {\n contentType: 'application/json',\n schema: requestSchema,\n },\n responses: [\n { status: 200, description: 'Invite email sent', schema: responseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid request origin', schema: errorSchema },\n { status: 404, description: 'User not found', schema: errorSchema },\n { status: 409, description: 'User already has a password', schema: errorSchema },\n { status: 422, description: 'Validation error', schema: validationErrorSchema },\n { status: 429, description: 'Rate limit exceeded', schema: rateLimitErrorSchema },\n { status: 500, description: 'Invitation email origin is not configured', schema: errorSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,MAAM,qBAAqB;AACpC,SAAS,iBAAiB;AAC1B,OAAO,qBAAqB;AAC5B,SAAS,2BAA2B;AACpC,SAAS,oBAAoB;AAC7B,SAAS,4BAA4B;AACrC,SAAS,mCAAmC;AAC5C,SAAS,0BAA0B;AACnC,SAAS,2BAA2B,wCAAwC;AAC5E,SAAS,2BAA2B;AACpC,SAAS,yBAAyB,gCAAgC;AAClE,SAAS,mBAAmB,qBAAqB;AAGjD,MAAM,8BAA8B,4BAA4B,iBAAiB;AAAA,EAC/E,QAAQ;AAAA,EAAG,UAAU;AAAA,EAAK,eAAe;AAAA,EAAK,WAAW;AAC3D,CAAC;AAED,MAAM,gBAAgB,EAAE,OAAO;AAAA,EAC7B,IAAI,EAAE,OAAO,EAAE,KAAK;AACtB,CAAC;AAED,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,IAAI,EAAE,QAAQ,IAAI;AACpB,CAAC;AAED,MAAM,cAAc,EAAE,OAAO;AAAA,EAC3B,OAAO,EAAE,OAAO;AAClB,CAAC;AAED,MAAM,wBAAwB,EAAE,OAAO;AAAA,EACrC,OAAO,EAAE,OAAO;AAAA,EAChB,aAAa,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,SAAS;AAClE,CAAC;AAEM,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,mBAAmB,EAAE;AACpE;AAEA,eAAsB,KAAK,KAAc;AACvC,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,KAAM,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAE9E,QAAM,EAAE,OAAO,eAAe,IAAI,MAAM,mBAAmB;AAAA,IACzD;AAAA,IACA,UAAU;AAAA,EACZ,CAAC;AACD,MAAI,eAAgB,QAAO;AAE3B,QAAM,OAAO,MAAM,aAAa,KAAK,CAAC,CAAC;AACvC,QAAM,SAAS,cAAc,UAAU,IAAI;AAC3C,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,aAAa;AAAA,MAClB,EAAE,OAAO,qBAAqB,aAAa,OAAO,MAAM,QAAQ,EAAE,YAAY;AAAA,MAC9E,EAAE,QAAQ,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,KAAK,UAAU,QAAQ,IAAI;AAEjC,MAAI,eAAe;AACnB,MAAI;AACF,QAAI,KAAK,KAAK;AACZ,YAAM,cAAc,UAAU,QAAQ,aAAa;AAGnD,YAAM,MAAM,MAAM,YAAY,QAAQ,KAAK,KAAK;AAAA,QAC9C,UAAU,KAAK,YAAY;AAAA,QAC3B,gBAAgB,KAAK,SAAS;AAAA,MAChC,CAAC;AACD,qBAAe,CAAC,CAAC,KAAK;AAAA,IACxB;AAAA,EACF,SAAS,KAAK;AACZ,YAAQ,MAAM,sDAAsD,GAAG;AAAA,EACzE;AAEA,QAAM,QAAiC,EAAE,IAAI,OAAO,KAAK,IAAI,WAAW,KAAK;AAC7E,MAAI,CAAC,cAAc;AACjB,QAAI,CAAC,KAAK,SAAU,QAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AACzF,UAAM,WAAW,KAAK;AAAA,EACxB;AAEA,QAAM,OAAO,MAAM,GAAG,QAAQ,MAAM,KAAY;AAChD,MAAI,CAAC,KAAM,QAAO,aAAa,KAAK,EAAE,OAAO,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAEhF,MAAI,KAAK,cAAc;AACrB,WAAO,aAAa,KAAK,EAAE,OAAO,8BAA8B,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACpF;AAEA,QAAM,cAAc,MAAM,0BAA0B,WAAW;AAAA,IAC7D,UAAU,KAAK,WAAW,OAAO,KAAK,QAAQ,IAAI,KAAK,YAAY;AAAA,IACnE,gBAAgB,KAAK,iBAAiB,OAAO,KAAK,cAAc,IAAI;AAAA,IACpE,QAAQ,KAAK,OAAO;AAAA,IACpB,cAAc;AAAA,IACd,YAAY,OAAO,KAAK,EAAE;AAAA,IAC1B,WAAW;AAAA,IACX,eAAe;AAAA,IACf,gBAAgB,IAAI;AAAA,EACtB,CAAC;AACD,MAAI,eAAe,CAAC,YAAY,IAAI;AAClC,WAAO,aAAa,KAAK,YAAY,MAAM,EAAE,QAAQ,YAAY,OAAO,CAAC;AAAA,EAC3E;AAEA,MAAI;AACJ,MAAI;AACF,WAAO,wBAAwB,IAAI,GAAG;AAAA,EACxC,SAAS,OAAO;AACd,UAAM,SAAS,yBAAyB,OAAO;AAAA,MAC7C,OAAO;AAAA,MACP,eAAe;AAAA,IACjB,CAAC;AACD,QAAI,OAAQ,QAAO,aAAa,KAAK,OAAO,MAAM,EAAE,QAAQ,OAAO,OAAO,CAAC;AAC3E,UAAM;AAAA,EACR;AAEA,QAAM,GAAG;AAAA,IACP;AAAA,IACA,EAAE,MAAM,KAAK,IAAI,QAAQ,KAAK;AAAA,IAC9B,EAAE,QAAQ,oBAAI,KAAK,EAAE;AAAA,EACvB;AAEA,QAAM,WAAW,kBAAkB;AACnC,QAAM,YAAY,cAAc,QAAQ;AACxC,QAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,mBAAmB;AAC3D,QAAM,MAAM,GAAG,OAAO,eAAe,EAAE,MAAM,OAAO,WAAW,WAAW,WAAW,oBAAI,KAAK,EAAE,CAAC;AACjG,QAAM,GAAG,QAAQ,GAAG,EAAE,MAAM;AAE5B,QAAM,YAAY,GAAG,IAAI,UAAU,QAAQ;AAE3C,QAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,QAAM,UAAU,UAAU,6BAA6B,uBAAuB;AAC9E,QAAM,OAAO;AAAA,IACX,SAAS,UAAU,6BAA6B,qBAAqB;AAAA,IACrE,OAAO,UAAU,2BAA2B,uBAAuB;AAAA,IACnE,MAAM,UAAU,0BAA0B,gIAAgI;AAAA,IAC1K,KAAK,UAAU,yBAAyB,sBAAsB;AAAA,IAC9D,MAAM,UAAU,0BAA0B,0EAA0E;AAAA,EACtH;AAEA,MAAI,YAAY;AAChB,MAAI;AACF,UAAM,UAAU,EAAE,IAAI,KAAK,OAAO,SAAS,OAAO,gBAAgB,EAAE,WAAW,KAAK,CAAC,EAAE,CAAC;AAAA,EAC1F,SAAS,KAAK;AACZ,YAAQ,MAAM,+DAA+D,GAAG;AAChF,gBAAY;AAAA,EACd;AAEA,MAAI,aAAa,uBAAuB;AACtC,UAAM,iCAAiC,WAAW;AAAA,MAChD,UAAU,KAAK,WAAW,OAAO,KAAK,QAAQ,IAAI,KAAK,YAAY;AAAA,MACnE,gBAAgB,KAAK,iBAAiB,OAAO,KAAK,cAAc,IAAI;AAAA,MACpE,QAAQ,KAAK,OAAO;AAAA,MACpB,cAAc;AAAA,MACd,YAAY,OAAO,KAAK,EAAE;AAAA,MAC1B,WAAW;AAAA,MACX,eAAe;AAAA,MACf,gBAAgB,IAAI;AAAA,MACpB,UAAU,YAAY;AAAA,IACxB,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,WAAW;AACd,WAAO,aAAa,KAAK,EAAE,IAAI,MAAM,SAAS,sBAAsB,CAAC;AAAA,EACvE;AAEA,SAAO,aAAa,KAAK,EAAE,IAAI,KAAK,CAAC;AACvC;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa;AAAA,QACX,aAAa;AAAA,QACb,QAAQ;AAAA,MACV;AAAA,MACA,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,eAAe;AAAA,MAC1E;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,0BAA0B,QAAQ,YAAY;AAAA,QAC1E,EAAE,QAAQ,KAAK,aAAa,kBAAkB,QAAQ,YAAY;AAAA,QAClE,EAAE,QAAQ,KAAK,aAAa,+BAA+B,QAAQ,YAAY;AAAA,QAC/E,EAAE,QAAQ,KAAK,aAAa,oBAAoB,QAAQ,sBAAsB;AAAA,QAC9E,EAAE,QAAQ,KAAK,aAAa,uBAAuB,QAAQ,qBAAqB;AAAA,QAChF,EAAE,QAAQ,KAAK,aAAa,6CAA6C,QAAQ,YAAY;AAAA,MAC/F;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -54,17 +54,23 @@ const addUser = {
54
54
  organizationId: org.id,
55
55
  tenantId: org.tenant.id
56
56
  });
57
- await em.persistAndFlush(u);
57
+ await em.persist(u).flush();
58
58
  if (rolesCsv) {
59
59
  const names = rolesCsv.split(",").map((s) => s.trim()).filter(Boolean);
60
60
  for (const name of names) {
61
61
  let role = await em.findOne(Role, { name, tenantId: normalizedTenantId });
62
+ if (!role && normalizedTenantId !== null) {
63
+ role = await em.findOne(Role, { name, tenantId: null });
64
+ }
62
65
  if (!role) {
63
66
  role = em.create(Role, { name, tenantId: normalizedTenantId, createdAt: /* @__PURE__ */ new Date() });
64
- await em.persistAndFlush(role);
67
+ await em.persist(role).flush();
68
+ } else if (normalizedTenantId !== null && role.tenantId !== normalizedTenantId) {
69
+ role.tenantId = normalizedTenantId;
70
+ await em.persist(role).flush();
65
71
  }
66
72
  const link = em.create(UserRole, { user: u, role });
67
- await em.persistAndFlush(link);
73
+ await em.persist(link).flush();
68
74
  }
69
75
  }
70
76
  console.log("User created with id", u.id);
@@ -358,9 +364,9 @@ const addOrganization = {
358
364
  const { resolve } = await createRequestContainer();
359
365
  const em = resolve("em");
360
366
  const tenant = em.create(Tenant, { name: `${name} Tenant` });
361
- await em.persistAndFlush(tenant);
367
+ await em.persist(tenant).flush();
362
368
  const org = em.create(Organization, { name, tenant });
363
- await em.persistAndFlush(org);
369
+ await em.persist(org).flush();
364
370
  await rebuildHierarchyForTenant(em, String(tenant.id));
365
371
  console.log("Organization created with id", org.id, "in tenant", tenant.id);
366
372
  }
@@ -551,7 +557,7 @@ const setPassword = {
551
557
  return;
552
558
  }
553
559
  user.passwordHash = await hash(password, 10);
554
- await em.persistAndFlush(user);
560
+ await em.persist(user).flush();
555
561
  console.log(`\u2705 Password updated successfully for user: ${email}`);
556
562
  }
557
563
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/auth/cli.ts"],
4
- "sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { hash } from 'bcryptjs'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { User, Role, UserRole } from '@open-mercato/core/modules/auth/data/entities'\nimport { Tenant, Organization } from '@open-mercato/core/modules/directory/data/entities'\nimport { rebuildHierarchyForTenant } from '@open-mercato/core/modules/directory/lib/hierarchy'\nimport { ensureRoles, setupInitialTenant } from './lib/setup-app'\nimport { normalizeTenantId } from './lib/tenantAccess'\nimport { computeEmailHash } from './lib/emailHash'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\nimport { decryptWithAesGcm } from '@open-mercato/shared/lib/encryption/aes'\nimport { env } from 'process'\nimport type { KmsService, TenantDek } from '@open-mercato/shared/lib/encryption/kms'\nimport crypto from 'node:crypto'\nimport { formatPasswordRequirements, getPasswordPolicy, validatePassword } from '@open-mercato/shared/lib/auth/passwordPolicy'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\nimport { getCliModules } from '@open-mercato/shared/modules/registry'\n\nconst addUser: ModuleCli = {\n command: 'add-user',\n async run(rest) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 2) {\n const k = rest[i]?.replace(/^--/, '')\n const v = rest[i + 1]\n if (k) args[k] = v\n }\n const email = args.email\n const password = args.password\n const organizationId = String(args.organizationId ?? args.orgId ?? args.org)\n const rolesCsv = (args.roles ?? '').trim()\n if (!email || !password || !organizationId) {\n console.error('Usage: mercato auth add-user --email <email> --password <password> --organizationId <id> [--roles customer,employee]')\n return\n }\n if (!ensurePasswordPolicy(password)) return\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n const org =\n (await findOneWithDecryption(\n em,\n Organization,\n { id: organizationId },\n { populate: ['tenant'] },\n { tenantId: null, organizationId },\n )) ?? null\n if (!org) throw new Error('Organization not found')\n const orgTenantId = org.tenant?.id ? String(org.tenant.id) : null\n const normalizedTenantId = normalizeTenantId(orgTenantId ?? null) ?? null\n const u = em.create(User, {\n email,\n emailHash: computeEmailHash(email),\n passwordHash: await hash(password, 10),\n isConfirmed: true,\n organizationId: org.id,\n tenantId: org.tenant.id,\n })\n await em.persistAndFlush(u)\n if (rolesCsv) {\n const names = rolesCsv.split(',').map(s => s.trim()).filter(Boolean)\n for (const name of names) {\n let role = await em.findOne(Role, { name, tenantId: normalizedTenantId })\n if (!role) {\n role = em.create(Role, { name, tenantId: normalizedTenantId, createdAt: new Date() })\n await em.persistAndFlush(role)\n }\n const link = em.create(UserRole, { user: u, role })\n await em.persistAndFlush(link)\n }\n }\n console.log('User created with id', u.id)\n },\n}\n\nfunction parseArgs(rest: string[]) {\n const args: Record<string, string | boolean> = {}\n for (let i = 0; i < rest.length; i++) {\n const a = rest[i]\n if (!a) continue\n if (a.startsWith('--')) {\n const [k, v] = a.replace(/^--/, '').split('=')\n if (v !== undefined) args[k] = v\n else if (rest[i + 1] && !rest[i + 1]!.startsWith('--')) { args[k] = rest[i + 1]!; i++ }\n else args[k] = true\n }\n }\n return args\n}\n\nfunction normalizeKeyInput(value: string): string {\n return value.trim().replace(/(?:^['\"]|['\"]$)/g, '')\n}\n\nfunction hashSecret(value: string | null | undefined): string | null {\n if (!value) return null\n return crypto.createHash('sha256').update(normalizeKeyInput(value)).digest('hex').slice(0, 12)\n}\n\nfunction ensurePasswordPolicy(password: string): boolean {\n const policy = getPasswordPolicy()\n const result = validatePassword(password, policy)\n if (result.ok) return true\n const requirements = formatPasswordRequirements(policy, (_key, fallback) => fallback)\n const suffix = requirements ? `: ${requirements}` : ''\n console.error(`Password does not meet the requirements${suffix}.`)\n return false\n}\n\nasync function withEncryptionDebugDisabled<T>(fn: () => Promise<T>): Promise<T> {\n const previous = process.env.TENANT_DATA_ENCRYPTION_DEBUG\n process.env.TENANT_DATA_ENCRYPTION_DEBUG = 'no'\n try {\n return await fn()\n } finally {\n if (previous === undefined) {\n delete process.env.TENANT_DATA_ENCRYPTION_DEBUG\n } else {\n process.env.TENANT_DATA_ENCRYPTION_DEBUG = previous\n }\n }\n}\n\nclass DerivedKeyKmsService implements KmsService {\n private root: Buffer\n constructor(secret: string) {\n this.root = crypto.createHash('sha256').update(normalizeKeyInput(secret)).digest()\n }\n\n isHealthy(): boolean {\n return true\n }\n\n private deriveKey(tenantId: string): string {\n const iterations = 310_000\n const keyLength = 32\n const derived = crypto.pbkdf2Sync(this.root, tenantId, iterations, keyLength, 'sha512')\n return derived.toString('base64')\n }\n\n async getTenantDek(tenantId: string): Promise<TenantDek | null> {\n if (!tenantId) return null\n return { tenantId, key: this.deriveKey(tenantId), fetchedAt: Date.now() }\n }\n\n async createTenantDek(tenantId: string): Promise<TenantDek | null> {\n return this.getTenantDek(tenantId)\n }\n}\n\nfunction fingerprintDek(dek: TenantDek | null): string | null {\n if (!dek?.key) return null\n return crypto.createHash('sha256').update(dek.key).digest('hex').slice(0, 12)\n}\n\nfunction decryptWithOldKey(\n payload: string,\n dek: TenantDek | null,\n): string | null {\n if (!dek?.key) return null\n return decryptWithAesGcm(payload, dek.key)\n}\n\nconst seedRoles: ModuleCli = {\n command: 'seed-roles',\n async run(rest) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 2) {\n const key = rest[i]?.replace(/^--/, '')\n if (!key) continue\n const value = rest[i + 1]\n if (value) args[key] = value\n }\n const tenantId = args.tenantId ?? args.tenant ?? args.tenant_id ?? null\n const { resolve } = await createRequestContainer()\n const em = resolve<EntityManager>('em')\n if (tenantId) {\n await ensureRoles(em, { tenantId })\n console.log('\uD83D\uDEE1\uFE0F Roles ensured for tenant', tenantId)\n return\n }\n const tenants = await em.find(Tenant, {})\n if (!tenants.length) {\n console.log('No tenants found; nothing to seed.')\n return\n }\n for (const tenant of tenants) {\n const id = tenant.id ? String(tenant.id) : null\n if (!id) continue\n await ensureRoles(em, { tenantId: id })\n console.log('\uD83D\uDEE1\uFE0F Roles ensured for tenant', id)\n }\n },\n}\n\nconst rotateEncryptionKey: ModuleCli = {\n command: 'rotate-encryption-key',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = (args.tenantId as string) ?? (args.tenant as string) ?? (args.tenant_id as string) ?? null\n const organizationId = (args.organizationId as string) ?? (args.orgId as string) ?? (args.org as string) ?? null\n const oldKey = (args['old-key'] as string) ?? (args.oldKey as string) ?? null\n const dryRun = Boolean(args['dry-run'] || args.dry)\n const debug = Boolean(args.debug)\n const rotate = Boolean(oldKey)\n if (rotate && !tenantId) {\n console.warn(\n '\u26A0\uFE0F Rotating with --old-key across all tenants. A single old key should normally target one tenant; consider --tenant.',\n )\n }\n if (!isTenantDataEncryptionEnabled()) {\n console.error('TENANT_DATA_ENCRYPTION is disabled; aborting.')\n return\n }\n const { resolve } = await createRequestContainer()\n const em = resolve<EntityManager>('em')\n const encryptionService = new TenantDataEncryptionService(em as any, { kms: createKmsService() })\n const oldKms = rotate && oldKey ? new DerivedKeyKmsService(oldKey) : null\n if (debug) {\n console.log('[rotate-encryption-key]', {\n hasOldKey: Boolean(oldKey),\n rotate,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n })\n console.log('[rotate-encryption-key] key fingerprints', {\n oldKey: hashSecret(oldKey),\n currentKey: hashSecret(process.env.TENANT_DATA_ENCRYPTION_FALLBACK_KEY),\n })\n }\n if (!encryptionService.isEnabled()) {\n console.error('Encryption service is not enabled (KMS unhealthy or no DEK). Aborting.')\n return\n }\n const conn: any = (em as any).getConnection?.()\n if (!conn || typeof conn.execute !== 'function') {\n console.error('Unable to access raw connection; aborting.')\n return\n }\n const meta = (em as any)?.getMetadata?.()?.get?.(User)\n const tableName = meta?.tableName || 'users'\n const schema = meta?.schema\n const qualifiedTable = schema ? `\"${schema}\".\"${tableName}\"` : `\"${tableName}\"`\n const isEncryptedPayload = (value: unknown): boolean => {\n if (typeof value !== 'string') return false\n const parts = value.split(':')\n return parts.length === 4 && parts[3] === 'v1'\n }\n const printedDek = new Set<string>()\n const oldDekCache = new Map<string, TenantDek | null>()\n const processScope = async (scopeTenantId: string, scopeOrganizationId: string): Promise<number> => {\n if (debug && !printedDek.has(scopeTenantId)) {\n printedDek.add(scopeTenantId)\n const [oldDek, newDek] = await Promise.all([\n oldKms?.getTenantDek(scopeTenantId) ?? Promise.resolve(null),\n encryptionService.getDek(scopeTenantId),\n ])\n console.log('[rotate-encryption-key] dek fingerprints', {\n tenantId: scopeTenantId,\n oldKey: fingerprintDek(oldDek),\n currentKey: fingerprintDek(newDek),\n })\n }\n const rawRows = await conn.execute(\n `select id, email, email_hash from ${qualifiedTable} where tenant_id = ? and organization_id = ?`,\n [scopeTenantId, scopeOrganizationId],\n )\n const rows = Array.isArray(rawRows) ? rawRows : []\n const pending = rotate\n ? rows\n : rows.filter((row: any) => !isEncryptedPayload(row?.email))\n if (!pending.length) return 0\n console.log(\n `Found ${pending.length} auth user records to process for org=${scopeOrganizationId}${dryRun ? ' (dry-run)' : ''}.`\n )\n if (dryRun) return 0\n const ids = pending.map((row: any) => String(row.id))\n const users = rotate\n ? await em.find(\n User,\n { id: { $in: ids }, tenantId: scopeTenantId, organizationId: scopeOrganizationId },\n )\n : await findWithDecryption(\n em,\n User,\n { id: { $in: ids }, tenantId: scopeTenantId, organizationId: scopeOrganizationId },\n {},\n { tenantId: scopeTenantId, organizationId: scopeOrganizationId, encryptionService },\n )\n const usersById = new Map(users.map((user) => [String(user.id), user]))\n let updated = 0\n for (const row of pending) {\n const user = usersById.get(String(row.id))\n if (!user) continue\n const rawEmail = typeof row.email === 'string' ? row.email : String(row.email ?? '')\n if (!rawEmail) continue\n if (rotate && (!isEncryptedPayload(rawEmail) || !oldKms)) {\n continue\n }\n let plainEmail = rawEmail\n if (rotate && isEncryptedPayload(rawEmail) && oldKms) {\n if (debug) {\n console.log('[rotate-encryption-key] decrypting', {\n userId: row.id,\n tenantId: scopeTenantId,\n organizationId: scopeOrganizationId,\n })\n }\n let oldDek = oldDekCache.get(scopeTenantId) ?? null\n if (!oldDekCache.has(scopeTenantId)) {\n oldDek = await oldKms.getTenantDek(scopeTenantId)\n oldDekCache.set(scopeTenantId, oldDek)\n }\n const maybeEmail = decryptWithOldKey(rawEmail, oldDek)\n if (typeof maybeEmail !== 'string' || isEncryptedPayload(maybeEmail)) continue\n plainEmail = maybeEmail\n }\n if (!plainEmail) continue\n const encrypted = await encryptionService.encryptEntityPayload(\n 'auth:user',\n { email: plainEmail },\n scopeTenantId,\n scopeOrganizationId,\n )\n const nextEmail = encrypted.email as string | undefined\n if (nextEmail && nextEmail !== user.email) {\n user.email = nextEmail as any\n user.emailHash = (encrypted as any).emailHash ?? computeEmailHash(plainEmail)\n em.persist(user)\n updated += 1\n }\n }\n if (updated > 0) {\n await em.flush()\n }\n return updated\n }\n\n if (tenantId && organizationId) {\n const updated = await processScope(String(tenantId), String(organizationId))\n if (!updated) {\n console.log('All auth user emails already encrypted for the selected scope.')\n } else {\n console.log(`Encrypted ${updated} auth user email(s).`)\n }\n return\n }\n\n const organizations = await em.find(Organization, {})\n if (!organizations.length) {\n console.log('No organizations found; nothing to encrypt.')\n return\n }\n let total = 0\n for (const org of organizations) {\n const scopeTenantId = org.tenant?.id ? String(org.tenant.id) : org.tenant.id ? String(org.tenant.id) : null\n const scopeOrganizationId = org.id ? String(org.id) : null\n if (!scopeTenantId || !scopeOrganizationId) continue\n total += await processScope(scopeTenantId, scopeOrganizationId)\n }\n if (total > 0) {\n console.log(`Encrypted ${total} auth user email(s) across all organizations.`)\n } else {\n console.log('All auth user emails already encrypted across all organizations.')\n }\n },\n}\n\n// will be exported at the bottom with all commands\n\nconst addOrganization: ModuleCli = {\n command: 'add-org',\n async run(rest) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 2) {\n const k = rest[i]?.replace(/^--/, '')\n const v = rest[i + 1]\n if (k) args[k] = v\n }\n const name = args.name || args.orgName\n if (!name) {\n console.error('Usage: mercato auth add-org --name <organization name>')\n return\n }\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n // Create tenant implicitly for simplicity\n const tenant = em.create(Tenant, { name: `${name} Tenant` })\n await em.persistAndFlush(tenant)\n const org = em.create(Organization, { name, tenant })\n await em.persistAndFlush(org)\n await rebuildHierarchyForTenant(em, String(tenant.id))\n console.log('Organization created with id', org.id, 'in tenant', tenant.id)\n },\n}\n\nconst setupApp: ModuleCli = {\n command: 'setup',\n async run(rest) {\n const args = parseArgs(rest)\n const orgName = typeof args.orgName === 'string'\n ? args.orgName\n : typeof args.name === 'string'\n ? args.name\n : undefined\n const email = typeof args.email === 'string' ? args.email : undefined\n const password = typeof args.password === 'string' ? args.password : undefined\n const rolesCsv = typeof args.roles === 'string'\n ? args.roles.trim()\n : 'superadmin,admin,employee'\n const skipPasswordPolicyRaw =\n args['skip-password-policy'] ??\n args.skipPasswordPolicy ??\n args['allow-weak-password'] ??\n args.allowWeakPassword\n const skipPasswordPolicy = typeof skipPasswordPolicyRaw === 'boolean'\n ? skipPasswordPolicyRaw\n : parseBooleanToken(typeof skipPasswordPolicyRaw === 'string' ? skipPasswordPolicyRaw : null) ?? false\n if (!orgName || !email || !password) {\n console.error('Usage: mercato auth setup --orgName <name> --email <email> --password <password> [--roles superadmin,admin,employee] [--skip-password-policy]')\n return\n }\n if (!skipPasswordPolicy && !ensurePasswordPolicy(password)) return\n if (skipPasswordPolicy) {\n console.warn('\u26A0\uFE0F Password policy validation skipped for setup.')\n }\n const { resolve } = await createRequestContainer()\n const em = resolve<EntityManager>('em')\n const roleNames = rolesCsv\n ? rolesCsv.split(',').map((s) => s.trim()).filter(Boolean)\n : undefined\n\n try {\n const result = await setupInitialTenant(em, {\n orgName,\n roleNames,\n primaryUser: { email, password, confirm: true },\n includeDerivedUsers: true,\n modules: getCliModules(),\n })\n\n if (result.reusedExistingUser) {\n console.log('\u26A0\uFE0F Existing initial user detected during setup.')\n console.log(`\u26A0\uFE0F Email: ${email}`)\n console.log('\u26A0\uFE0F Updated roles if missing and reused tenant/organization.')\n }\n\n if(env.NODE_ENV !== 'test') { \n for (const snapshot of result.users) {\n if (snapshot.created) {\n if (snapshot.user.email === email && password) {\n console.log('\uD83C\uDF89 Created user', snapshot.user.email, 'password:', password)\n } else {\n console.log('\uD83C\uDF89 Created user', snapshot.user.email)\n }\n } else {\n console.log(`Updated user ${snapshot.user.email}`)\n }\n }\n }\n\n if(env.NODE_ENV !== 'test') console.log('\u2705 Setup complete:', { tenantId: result.tenantId, organizationId: result.organizationId })\n } catch (err) {\n if (err instanceof Error && err.message === 'USER_EXISTS') {\n console.error('Setup aborted: user already exists with the provided email.')\n return\n }\n throw err\n }\n },\n}\n\nconst listOrganizations: ModuleCli = {\n command: 'list-orgs',\n async run() {\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n const orgs = await findWithDecryption(\n em,\n Organization,\n {},\n { populate: ['tenant'] },\n { tenantId: null, organizationId: null },\n )\n \n if (orgs.length === 0) {\n console.log('No organizations found')\n return\n }\n \n console.log(`Found ${orgs.length} organization(s):`)\n console.log('')\n console.log('ID | Name | Tenant ID | Created')\n console.log('-------------------------------------|-------------------------|-------------------------------------|-------------------')\n \n for (const org of orgs) {\n const created = org.createdAt ? new Date(org.createdAt).toLocaleDateString() : 'N/A'\n const id = org.id || 'N/A'\n const tenantId = org.tenant?.id || 'N/A'\n const name = (org.name || 'Unnamed').padEnd(23)\n console.log(`${id.padEnd(35)} | ${name} | ${tenantId.padEnd(35)} | ${created}`)\n }\n },\n}\n\nconst listTenants: ModuleCli = {\n command: 'list-tenants',\n async run() {\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n const tenants = await em.find(Tenant, {})\n \n if (tenants.length === 0) {\n console.log('No tenants found')\n return\n }\n \n console.log(`Found ${tenants.length} tenant(s):`)\n console.log('')\n console.log('ID | Name | Created')\n console.log('-------------------------------------|-------------------------|-------------------')\n \n for (const tenant of tenants) {\n const created = tenant.createdAt ? new Date(tenant.createdAt).toLocaleDateString() : 'N/A'\n const id = tenant.id || 'N/A'\n const name = (tenant.name || 'Unnamed').padEnd(23)\n console.log(`${id.padEnd(35)} | ${name} | ${created}`)\n }\n },\n}\n\nconst listUsers: ModuleCli = {\n command: 'list-users',\n async run(rest) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 2) {\n const k = rest[i]?.replace(/^--/, '')\n const v = rest[i + 1]\n if (k) args[k] = v\n }\n \n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n \n // Build query with optional filters\n const where: any = {}\n if (args.organizationId || args.orgId || args.org) {\n where.organizationId = args.organizationId || args.orgId || args.org\n }\n if (args.tenantId || args.tenant) {\n where.tenantId = args.tenantId || args.tenant\n }\n \n const users = await em.find(User, where)\n \n if (users.length === 0) {\n console.log('No users found')\n return\n }\n \n console.log(`Found ${users.length} user(s):`)\n console.log('')\n console.log('ID | Email | Name | Organization ID | Tenant ID | Roles')\n console.log('-------------------------------------|-------------------------|-------------------------|---------------------|---------------------|-------------------')\n \n for (const user of users) {\n // Get user roles separately\n const userRoles = await findWithDecryption(\n em,\n UserRole,\n { user: user.id },\n { populate: ['role'] },\n { tenantId: user.tenantId ?? null, organizationId: user.organizationId ?? null },\n )\n const roles = userRoles.map((ur: any) => ur.role?.name).filter(Boolean).join(', ') || 'None'\n \n // Get organization and tenant names if IDs exist\n let orgName = 'N/A'\n let tenantName = 'N/A'\n \n if (user.organizationId) {\n const org = await em.findOne(Organization, { id: user.organizationId })\n orgName = org?.name?.substring(0, 19) + '...' || user.organizationId.substring(0, 8) + '...'\n }\n \n if (user.tenantId) {\n const tenant = await em.findOne(Tenant, { id: user.tenantId })\n tenantName = tenant?.name?.substring(0, 19) + '...' || user.tenantId.substring(0, 8) + '...'\n }\n \n const id = user.id || 'N/A'\n const email = (user.email || 'N/A').padEnd(23)\n const name = (user.name || 'Unnamed').padEnd(23)\n \n console.log(`${id.padEnd(35)} | ${email} | ${name} | ${orgName.padEnd(19)} | ${tenantName.padEnd(19)} | ${roles}`)\n }\n },\n}\n\nconst setPassword: ModuleCli = {\n command: 'set-password',\n async run(rest) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 2) {\n const k = rest[i]?.replace(/^--/, '')\n const v = rest[i + 1]\n if (k) args[k] = v\n }\n \n const email = args.email\n const password = args.password\n \n if (!email || !password) {\n console.error('Usage: mercato auth set-password --email <email> --password <newPassword>')\n return\n }\n if (!ensurePasswordPolicy(password)) return\n \n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n const emailHash = computeEmailHash(email)\n const user = await em.findOne(User, { $or: [{ email }, { emailHash }] })\n \n if (!user) {\n console.error(`User with email \"${email}\" not found`)\n return\n }\n \n user.passwordHash = await hash(password, 10)\n await em.persistAndFlush(user)\n \n console.log(`\u2705 Password updated successfully for user: ${email}`)\n },\n}\n\n// Export the full CLI list\nexport default [addUser, seedRoles, rotateEncryptionKey, addOrganization, setupApp, listOrganizations, listTenants, listUsers, setPassword]\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { hash } from 'bcryptjs'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { User, Role, UserRole } from '@open-mercato/core/modules/auth/data/entities'\nimport { Tenant, Organization } from '@open-mercato/core/modules/directory/data/entities'\nimport { rebuildHierarchyForTenant } from '@open-mercato/core/modules/directory/lib/hierarchy'\nimport { ensureRoles, setupInitialTenant } from './lib/setup-app'\nimport { normalizeTenantId } from './lib/tenantAccess'\nimport { computeEmailHash } from './lib/emailHash'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\nimport { decryptWithAesGcm } from '@open-mercato/shared/lib/encryption/aes'\nimport { env } from 'process'\nimport type { KmsService, TenantDek } from '@open-mercato/shared/lib/encryption/kms'\nimport crypto from 'node:crypto'\nimport { formatPasswordRequirements, getPasswordPolicy, validatePassword } from '@open-mercato/shared/lib/auth/passwordPolicy'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\nimport { getCliModules } from '@open-mercato/shared/modules/registry'\n\nconst addUser: ModuleCli = {\n command: 'add-user',\n async run(rest) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 2) {\n const k = rest[i]?.replace(/^--/, '')\n const v = rest[i + 1]\n if (k) args[k] = v\n }\n const email = args.email\n const password = args.password\n const organizationId = String(args.organizationId ?? args.orgId ?? args.org)\n const rolesCsv = (args.roles ?? '').trim()\n if (!email || !password || !organizationId) {\n console.error('Usage: mercato auth add-user --email <email> --password <password> --organizationId <id> [--roles customer,employee]')\n return\n }\n if (!ensurePasswordPolicy(password)) return\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n const org =\n (await findOneWithDecryption(\n em,\n Organization,\n { id: organizationId },\n { populate: ['tenant'] },\n { tenantId: null, organizationId },\n )) ?? null\n if (!org) throw new Error('Organization not found')\n const orgTenantId = org.tenant?.id ? String(org.tenant.id) : null\n const normalizedTenantId = normalizeTenantId(orgTenantId ?? null) ?? null\n const u = em.create(User, {\n email,\n emailHash: computeEmailHash(email),\n passwordHash: await hash(password, 10),\n isConfirmed: true,\n organizationId: org.id,\n tenantId: org.tenant.id,\n })\n await em.persist(u).flush()\n if (rolesCsv) {\n const names = rolesCsv.split(',').map(s => s.trim()).filter(Boolean)\n for (const name of names) {\n let role = await em.findOne(Role, { name, tenantId: normalizedTenantId })\n if (!role && normalizedTenantId !== null) {\n role = await em.findOne(Role, { name, tenantId: null })\n }\n if (!role) {\n role = em.create(Role, { name, tenantId: normalizedTenantId, createdAt: new Date() })\n await em.persist(role).flush()\n } else if (normalizedTenantId !== null && role.tenantId !== normalizedTenantId) {\n role.tenantId = normalizedTenantId\n await em.persist(role).flush()\n }\n const link = em.create(UserRole, { user: u, role })\n await em.persist(link).flush()\n }\n }\n console.log('User created with id', u.id)\n },\n}\n\nfunction parseArgs(rest: string[]) {\n const args: Record<string, string | boolean> = {}\n for (let i = 0; i < rest.length; i++) {\n const a = rest[i]\n if (!a) continue\n if (a.startsWith('--')) {\n const [k, v] = a.replace(/^--/, '').split('=')\n if (v !== undefined) args[k] = v\n else if (rest[i + 1] && !rest[i + 1]!.startsWith('--')) { args[k] = rest[i + 1]!; i++ }\n else args[k] = true\n }\n }\n return args\n}\n\nfunction normalizeKeyInput(value: string): string {\n return value.trim().replace(/(?:^['\"]|['\"]$)/g, '')\n}\n\nfunction hashSecret(value: string | null | undefined): string | null {\n if (!value) return null\n return crypto.createHash('sha256').update(normalizeKeyInput(value)).digest('hex').slice(0, 12)\n}\n\nfunction ensurePasswordPolicy(password: string): boolean {\n const policy = getPasswordPolicy()\n const result = validatePassword(password, policy)\n if (result.ok) return true\n const requirements = formatPasswordRequirements(policy, (_key, fallback) => fallback)\n const suffix = requirements ? `: ${requirements}` : ''\n console.error(`Password does not meet the requirements${suffix}.`)\n return false\n}\n\nasync function withEncryptionDebugDisabled<T>(fn: () => Promise<T>): Promise<T> {\n const previous = process.env.TENANT_DATA_ENCRYPTION_DEBUG\n process.env.TENANT_DATA_ENCRYPTION_DEBUG = 'no'\n try {\n return await fn()\n } finally {\n if (previous === undefined) {\n delete process.env.TENANT_DATA_ENCRYPTION_DEBUG\n } else {\n process.env.TENANT_DATA_ENCRYPTION_DEBUG = previous\n }\n }\n}\n\nclass DerivedKeyKmsService implements KmsService {\n private root: Buffer\n constructor(secret: string) {\n this.root = crypto.createHash('sha256').update(normalizeKeyInput(secret)).digest()\n }\n\n isHealthy(): boolean {\n return true\n }\n\n private deriveKey(tenantId: string): string {\n const iterations = 310_000\n const keyLength = 32\n const derived = crypto.pbkdf2Sync(this.root, tenantId, iterations, keyLength, 'sha512')\n return derived.toString('base64')\n }\n\n async getTenantDek(tenantId: string): Promise<TenantDek | null> {\n if (!tenantId) return null\n return { tenantId, key: this.deriveKey(tenantId), fetchedAt: Date.now() }\n }\n\n async createTenantDek(tenantId: string): Promise<TenantDek | null> {\n return this.getTenantDek(tenantId)\n }\n}\n\nfunction fingerprintDek(dek: TenantDek | null): string | null {\n if (!dek?.key) return null\n return crypto.createHash('sha256').update(dek.key).digest('hex').slice(0, 12)\n}\n\nfunction decryptWithOldKey(\n payload: string,\n dek: TenantDek | null,\n): string | null {\n if (!dek?.key) return null\n return decryptWithAesGcm(payload, dek.key)\n}\n\nconst seedRoles: ModuleCli = {\n command: 'seed-roles',\n async run(rest) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 2) {\n const key = rest[i]?.replace(/^--/, '')\n if (!key) continue\n const value = rest[i + 1]\n if (value) args[key] = value\n }\n const tenantId = args.tenantId ?? args.tenant ?? args.tenant_id ?? null\n const { resolve } = await createRequestContainer()\n const em = resolve<EntityManager>('em')\n if (tenantId) {\n await ensureRoles(em, { tenantId })\n console.log('\uD83D\uDEE1\uFE0F Roles ensured for tenant', tenantId)\n return\n }\n const tenants = await em.find(Tenant, {})\n if (!tenants.length) {\n console.log('No tenants found; nothing to seed.')\n return\n }\n for (const tenant of tenants) {\n const id = tenant.id ? String(tenant.id) : null\n if (!id) continue\n await ensureRoles(em, { tenantId: id })\n console.log('\uD83D\uDEE1\uFE0F Roles ensured for tenant', id)\n }\n },\n}\n\nconst rotateEncryptionKey: ModuleCli = {\n command: 'rotate-encryption-key',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = (args.tenantId as string) ?? (args.tenant as string) ?? (args.tenant_id as string) ?? null\n const organizationId = (args.organizationId as string) ?? (args.orgId as string) ?? (args.org as string) ?? null\n const oldKey = (args['old-key'] as string) ?? (args.oldKey as string) ?? null\n const dryRun = Boolean(args['dry-run'] || args.dry)\n const debug = Boolean(args.debug)\n const rotate = Boolean(oldKey)\n if (rotate && !tenantId) {\n console.warn(\n '\u26A0\uFE0F Rotating with --old-key across all tenants. A single old key should normally target one tenant; consider --tenant.',\n )\n }\n if (!isTenantDataEncryptionEnabled()) {\n console.error('TENANT_DATA_ENCRYPTION is disabled; aborting.')\n return\n }\n const { resolve } = await createRequestContainer()\n const em = resolve<EntityManager>('em')\n const encryptionService = new TenantDataEncryptionService(em as any, { kms: createKmsService() })\n const oldKms = rotate && oldKey ? new DerivedKeyKmsService(oldKey) : null\n if (debug) {\n console.log('[rotate-encryption-key]', {\n hasOldKey: Boolean(oldKey),\n rotate,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n })\n console.log('[rotate-encryption-key] key fingerprints', {\n oldKey: hashSecret(oldKey),\n currentKey: hashSecret(process.env.TENANT_DATA_ENCRYPTION_FALLBACK_KEY),\n })\n }\n if (!encryptionService.isEnabled()) {\n console.error('Encryption service is not enabled (KMS unhealthy or no DEK). Aborting.')\n return\n }\n const conn: any = (em as any).getConnection?.()\n if (!conn || typeof conn.execute !== 'function') {\n console.error('Unable to access raw connection; aborting.')\n return\n }\n const meta = (em as any)?.getMetadata?.()?.get?.(User)\n const tableName = meta?.tableName || 'users'\n const schema = meta?.schema\n const qualifiedTable = schema ? `\"${schema}\".\"${tableName}\"` : `\"${tableName}\"`\n const isEncryptedPayload = (value: unknown): boolean => {\n if (typeof value !== 'string') return false\n const parts = value.split(':')\n return parts.length === 4 && parts[3] === 'v1'\n }\n const printedDek = new Set<string>()\n const oldDekCache = new Map<string, TenantDek | null>()\n const processScope = async (scopeTenantId: string, scopeOrganizationId: string): Promise<number> => {\n if (debug && !printedDek.has(scopeTenantId)) {\n printedDek.add(scopeTenantId)\n const [oldDek, newDek] = await Promise.all([\n oldKms?.getTenantDek(scopeTenantId) ?? Promise.resolve(null),\n encryptionService.getDek(scopeTenantId),\n ])\n console.log('[rotate-encryption-key] dek fingerprints', {\n tenantId: scopeTenantId,\n oldKey: fingerprintDek(oldDek),\n currentKey: fingerprintDek(newDek),\n })\n }\n const rawRows = await conn.execute(\n `select id, email, email_hash from ${qualifiedTable} where tenant_id = ? and organization_id = ?`,\n [scopeTenantId, scopeOrganizationId],\n )\n const rows = Array.isArray(rawRows) ? rawRows : []\n const pending = rotate\n ? rows\n : rows.filter((row: any) => !isEncryptedPayload(row?.email))\n if (!pending.length) return 0\n console.log(\n `Found ${pending.length} auth user records to process for org=${scopeOrganizationId}${dryRun ? ' (dry-run)' : ''}.`\n )\n if (dryRun) return 0\n const ids = pending.map((row: any) => String(row.id))\n const users = rotate\n ? await em.find(\n User,\n { id: { $in: ids }, tenantId: scopeTenantId, organizationId: scopeOrganizationId },\n )\n : await findWithDecryption(\n em,\n User,\n { id: { $in: ids }, tenantId: scopeTenantId, organizationId: scopeOrganizationId },\n {},\n { tenantId: scopeTenantId, organizationId: scopeOrganizationId, encryptionService },\n )\n const usersById = new Map(users.map((user) => [String(user.id), user]))\n let updated = 0\n for (const row of pending) {\n const user = usersById.get(String(row.id))\n if (!user) continue\n const rawEmail = typeof row.email === 'string' ? row.email : String(row.email ?? '')\n if (!rawEmail) continue\n if (rotate && (!isEncryptedPayload(rawEmail) || !oldKms)) {\n continue\n }\n let plainEmail = rawEmail\n if (rotate && isEncryptedPayload(rawEmail) && oldKms) {\n if (debug) {\n console.log('[rotate-encryption-key] decrypting', {\n userId: row.id,\n tenantId: scopeTenantId,\n organizationId: scopeOrganizationId,\n })\n }\n let oldDek = oldDekCache.get(scopeTenantId) ?? null\n if (!oldDekCache.has(scopeTenantId)) {\n oldDek = await oldKms.getTenantDek(scopeTenantId)\n oldDekCache.set(scopeTenantId, oldDek)\n }\n const maybeEmail = decryptWithOldKey(rawEmail, oldDek)\n if (typeof maybeEmail !== 'string' || isEncryptedPayload(maybeEmail)) continue\n plainEmail = maybeEmail\n }\n if (!plainEmail) continue\n const encrypted = await encryptionService.encryptEntityPayload(\n 'auth:user',\n { email: plainEmail },\n scopeTenantId,\n scopeOrganizationId,\n )\n const nextEmail = encrypted.email as string | undefined\n if (nextEmail && nextEmail !== user.email) {\n user.email = nextEmail as any\n user.emailHash = (encrypted as any).emailHash ?? computeEmailHash(plainEmail)\n em.persist(user)\n updated += 1\n }\n }\n if (updated > 0) {\n await em.flush()\n }\n return updated\n }\n\n if (tenantId && organizationId) {\n const updated = await processScope(String(tenantId), String(organizationId))\n if (!updated) {\n console.log('All auth user emails already encrypted for the selected scope.')\n } else {\n console.log(`Encrypted ${updated} auth user email(s).`)\n }\n return\n }\n\n const organizations = await em.find(Organization, {})\n if (!organizations.length) {\n console.log('No organizations found; nothing to encrypt.')\n return\n }\n let total = 0\n for (const org of organizations) {\n const scopeTenantId = org.tenant?.id ? String(org.tenant.id) : org.tenant.id ? String(org.tenant.id) : null\n const scopeOrganizationId = org.id ? String(org.id) : null\n if (!scopeTenantId || !scopeOrganizationId) continue\n total += await processScope(scopeTenantId, scopeOrganizationId)\n }\n if (total > 0) {\n console.log(`Encrypted ${total} auth user email(s) across all organizations.`)\n } else {\n console.log('All auth user emails already encrypted across all organizations.')\n }\n },\n}\n\n// will be exported at the bottom with all commands\n\nconst addOrganization: ModuleCli = {\n command: 'add-org',\n async run(rest) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 2) {\n const k = rest[i]?.replace(/^--/, '')\n const v = rest[i + 1]\n if (k) args[k] = v\n }\n const name = args.name || args.orgName\n if (!name) {\n console.error('Usage: mercato auth add-org --name <organization name>')\n return\n }\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n // Create tenant implicitly for simplicity\n const tenant = em.create(Tenant, { name: `${name} Tenant` })\n await em.persist(tenant).flush()\n const org = em.create(Organization, { name, tenant })\n await em.persist(org).flush()\n await rebuildHierarchyForTenant(em, String(tenant.id))\n console.log('Organization created with id', org.id, 'in tenant', tenant.id)\n },\n}\n\nconst setupApp: ModuleCli = {\n command: 'setup',\n async run(rest) {\n const args = parseArgs(rest)\n const orgName = typeof args.orgName === 'string'\n ? args.orgName\n : typeof args.name === 'string'\n ? args.name\n : undefined\n const email = typeof args.email === 'string' ? args.email : undefined\n const password = typeof args.password === 'string' ? args.password : undefined\n const rolesCsv = typeof args.roles === 'string'\n ? args.roles.trim()\n : 'superadmin,admin,employee'\n const skipPasswordPolicyRaw =\n args['skip-password-policy'] ??\n args.skipPasswordPolicy ??\n args['allow-weak-password'] ??\n args.allowWeakPassword\n const skipPasswordPolicy = typeof skipPasswordPolicyRaw === 'boolean'\n ? skipPasswordPolicyRaw\n : parseBooleanToken(typeof skipPasswordPolicyRaw === 'string' ? skipPasswordPolicyRaw : null) ?? false\n if (!orgName || !email || !password) {\n console.error('Usage: mercato auth setup --orgName <name> --email <email> --password <password> [--roles superadmin,admin,employee] [--skip-password-policy]')\n return\n }\n if (!skipPasswordPolicy && !ensurePasswordPolicy(password)) return\n if (skipPasswordPolicy) {\n console.warn('\u26A0\uFE0F Password policy validation skipped for setup.')\n }\n const { resolve } = await createRequestContainer()\n const em = resolve<EntityManager>('em')\n const roleNames = rolesCsv\n ? rolesCsv.split(',').map((s) => s.trim()).filter(Boolean)\n : undefined\n\n try {\n const result = await setupInitialTenant(em, {\n orgName,\n roleNames,\n primaryUser: { email, password, confirm: true },\n includeDerivedUsers: true,\n modules: getCliModules(),\n })\n\n if (result.reusedExistingUser) {\n console.log('\u26A0\uFE0F Existing initial user detected during setup.')\n console.log(`\u26A0\uFE0F Email: ${email}`)\n console.log('\u26A0\uFE0F Updated roles if missing and reused tenant/organization.')\n }\n\n if (env.NODE_ENV !== 'test') {\n for (const snapshot of result.users) {\n if (snapshot.created) {\n if (snapshot.user.email === email && password) {\n console.log('\uD83C\uDF89 Created user', snapshot.user.email, 'password:', password)\n } else {\n console.log('\uD83C\uDF89 Created user', snapshot.user.email)\n }\n } else {\n console.log(`Updated user ${snapshot.user.email}`)\n }\n }\n }\n\n if (env.NODE_ENV !== 'test') console.log('\u2705 Setup complete:', { tenantId: result.tenantId, organizationId: result.organizationId })\n } catch (err) {\n if (err instanceof Error && err.message === 'USER_EXISTS') {\n console.error('Setup aborted: user already exists with the provided email.')\n return\n }\n throw err\n }\n },\n}\n\nconst listOrganizations: ModuleCli = {\n command: 'list-orgs',\n async run() {\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n const orgs = await findWithDecryption(\n em,\n Organization,\n {},\n { populate: ['tenant'] },\n { tenantId: null, organizationId: null },\n )\n\n if (orgs.length === 0) {\n console.log('No organizations found')\n return\n }\n\n console.log(`Found ${orgs.length} organization(s):`)\n console.log('')\n console.log('ID | Name | Tenant ID | Created')\n console.log('-------------------------------------|-------------------------|-------------------------------------|-------------------')\n\n for (const org of orgs) {\n const created = org.createdAt ? new Date(org.createdAt).toLocaleDateString() : 'N/A'\n const id = org.id || 'N/A'\n const tenantId = org.tenant?.id || 'N/A'\n const name = (org.name || 'Unnamed').padEnd(23)\n console.log(`${id.padEnd(35)} | ${name} | ${tenantId.padEnd(35)} | ${created}`)\n }\n },\n}\n\nconst listTenants: ModuleCli = {\n command: 'list-tenants',\n async run() {\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n const tenants = await em.find(Tenant, {})\n\n if (tenants.length === 0) {\n console.log('No tenants found')\n return\n }\n\n console.log(`Found ${tenants.length} tenant(s):`)\n console.log('')\n console.log('ID | Name | Created')\n console.log('-------------------------------------|-------------------------|-------------------')\n\n for (const tenant of tenants) {\n const created = tenant.createdAt ? new Date(tenant.createdAt).toLocaleDateString() : 'N/A'\n const id = tenant.id || 'N/A'\n const name = (tenant.name || 'Unnamed').padEnd(23)\n console.log(`${id.padEnd(35)} | ${name} | ${created}`)\n }\n },\n}\n\nconst listUsers: ModuleCli = {\n command: 'list-users',\n async run(rest) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 2) {\n const k = rest[i]?.replace(/^--/, '')\n const v = rest[i + 1]\n if (k) args[k] = v\n }\n\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n\n // Build query with optional filters\n const where: any = {}\n if (args.organizationId || args.orgId || args.org) {\n where.organizationId = args.organizationId || args.orgId || args.org\n }\n if (args.tenantId || args.tenant) {\n where.tenantId = args.tenantId || args.tenant\n }\n\n const users = await em.find(User, where)\n\n if (users.length === 0) {\n console.log('No users found')\n return\n }\n\n console.log(`Found ${users.length} user(s):`)\n console.log('')\n console.log('ID | Email | Name | Organization ID | Tenant ID | Roles')\n console.log('-------------------------------------|-------------------------|-------------------------|---------------------|---------------------|-------------------')\n\n for (const user of users) {\n // Get user roles separately\n const userRoles = await findWithDecryption(\n em,\n UserRole,\n { user: user.id },\n { populate: ['role'] },\n { tenantId: user.tenantId ?? null, organizationId: user.organizationId ?? null },\n )\n const roles = userRoles.map((ur: any) => ur.role?.name).filter(Boolean).join(', ') || 'None'\n\n // Get organization and tenant names if IDs exist\n let orgName = 'N/A'\n let tenantName = 'N/A'\n\n if (user.organizationId) {\n const org = await em.findOne(Organization, { id: user.organizationId })\n orgName = org?.name?.substring(0, 19) + '...' || user.organizationId.substring(0, 8) + '...'\n }\n\n if (user.tenantId) {\n const tenant = await em.findOne(Tenant, { id: user.tenantId })\n tenantName = tenant?.name?.substring(0, 19) + '...' || user.tenantId.substring(0, 8) + '...'\n }\n\n const id = user.id || 'N/A'\n const email = (user.email || 'N/A').padEnd(23)\n const name = (user.name || 'Unnamed').padEnd(23)\n\n console.log(`${id.padEnd(35)} | ${email} | ${name} | ${orgName.padEnd(19)} | ${tenantName.padEnd(19)} | ${roles}`)\n }\n },\n}\n\nconst setPassword: ModuleCli = {\n command: 'set-password',\n async run(rest) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 2) {\n const k = rest[i]?.replace(/^--/, '')\n const v = rest[i + 1]\n if (k) args[k] = v\n }\n\n const email = args.email\n const password = args.password\n\n if (!email || !password) {\n console.error('Usage: mercato auth set-password --email <email> --password <newPassword>')\n return\n }\n if (!ensurePasswordPolicy(password)) return\n\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as any\n const emailHash = computeEmailHash(email)\n const user = await em.findOne(User, { $or: [{ email }, { emailHash }] })\n\n if (!user) {\n console.error(`User with email \"${email}\" not found`)\n return\n }\n\n user.passwordHash = await hash(password, 10)\n await em.persist(user).flush()\n\n console.log(`\u2705 Password updated successfully for user: ${email}`)\n },\n}\n\n// Export the full CLI list\nexport default [addUser, seedRoles, rotateEncryptionKey, addOrganization, setupApp, listOrganizations, listTenants, listUsers, setPassword]\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -267,7 +267,7 @@ async function sendInviteToUser(em, user) {
267
267
  const tokenHash = hashAuthToken(rawToken);
268
268
  const expiresAt = new Date(Date.now() + INVITE_TOKEN_TTL_MS);
269
269
  const row = em.create(PasswordReset, { user, token: tokenHash, expiresAt, createdAt: /* @__PURE__ */ new Date() });
270
- await em.persistAndFlush(row);
270
+ await em.persist(row).flush();
271
271
  const base = getSecurityEmailBaseUrl();
272
272
  const inviteUrl = `${base}/reset/${rawToken}`;
273
273
  const { translate } = await resolveTranslations();