@open-mercato/core 0.6.5-develop.5337.1.534b781eac → 0.6.5

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 (350) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/AGENTS.md +1 -1
  3. package/dist/bootstrap.js +46 -6
  4. package/dist/bootstrap.js.map +2 -2
  5. package/dist/generated/entities/organization/index.js +2 -0
  6. package/dist/generated/entities/organization/index.js.map +2 -2
  7. package/dist/generated/entity-fields-registry.js +1 -0
  8. package/dist/generated/entity-fields-registry.js.map +2 -2
  9. package/dist/helpers/integration/crmFixtures.js +4 -0
  10. package/dist/helpers/integration/crmFixtures.js.map +2 -2
  11. package/dist/modules/attachments/api/library/route.js +2 -2
  12. package/dist/modules/attachments/api/library/route.js.map +2 -2
  13. package/dist/modules/attachments/api/route.js +2 -0
  14. package/dist/modules/attachments/api/route.js.map +2 -2
  15. package/dist/modules/attachments/components/AttachmentContentPreview.js +9 -5
  16. package/dist/modules/attachments/components/AttachmentContentPreview.js.map +2 -2
  17. package/dist/modules/attachments/lib/access.js +18 -0
  18. package/dist/modules/attachments/lib/access.js.map +2 -2
  19. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js +3 -2
  20. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js.map +2 -2
  21. package/dist/modules/audit_logs/data/entities.js +2 -1
  22. package/dist/modules/audit_logs/data/entities.js.map +2 -2
  23. package/dist/modules/audit_logs/migrations/Migration20260611104500.js +13 -0
  24. package/dist/modules/audit_logs/migrations/Migration20260611104500.js.map +7 -0
  25. package/dist/modules/audit_logs/services/accessLogService.js +10 -0
  26. package/dist/modules/audit_logs/services/accessLogService.js.map +2 -2
  27. package/dist/modules/auth/api/admin/nav.js +9 -0
  28. package/dist/modules/auth/api/admin/nav.js.map +2 -2
  29. package/dist/modules/auth/api/login.js +4 -13
  30. package/dist/modules/auth/api/login.js.map +2 -2
  31. package/dist/modules/auth/commands/users.js +20 -14
  32. package/dist/modules/auth/commands/users.js.map +2 -2
  33. package/dist/modules/auth/data/entities.js +4 -2
  34. package/dist/modules/auth/data/entities.js.map +2 -2
  35. package/dist/modules/auth/lib/backendChrome.js +35 -2
  36. package/dist/modules/auth/lib/backendChrome.js.map +2 -2
  37. package/dist/modules/auth/lib/consentIntegrity.js +3 -3
  38. package/dist/modules/auth/lib/consentIntegrity.js.map +2 -2
  39. package/dist/modules/auth/migrations/Migration20260610120000.js +30 -0
  40. package/dist/modules/auth/migrations/Migration20260610120000.js.map +7 -0
  41. package/dist/modules/auth/migrations/Migration20260611103000.js +15 -0
  42. package/dist/modules/auth/migrations/Migration20260611103000.js.map +7 -0
  43. package/dist/modules/auth/services/authService.js +5 -3
  44. package/dist/modules/auth/services/authService.js.map +2 -2
  45. package/dist/modules/auth/services/rbacService.js +3 -2
  46. package/dist/modules/auth/services/rbacService.js.map +2 -2
  47. package/dist/modules/catalog/ai-tools/configuration-pack.js.map +1 -1
  48. package/dist/modules/catalog/ai-tools/prices-offers-pack.js.map +1 -1
  49. package/dist/modules/catalog/ai-tools/products-pack.js.map +1 -1
  50. package/dist/modules/catalog/ai-tools/variants-pack.js.map +1 -1
  51. package/dist/modules/communication_channels/data/entities.js.map +1 -1
  52. package/dist/modules/communication_channels/encryption.js.map +1 -1
  53. package/dist/modules/communication_channels/lib/thread-matcher.js.map +1 -1
  54. package/dist/modules/communication_channels/lib/thread-token.js.map +1 -1
  55. package/dist/modules/currencies/api/currencies/route.js +4 -3
  56. package/dist/modules/currencies/api/currencies/route.js.map +2 -2
  57. package/dist/modules/customer_accounts/api/admin/roles.js +2 -1
  58. package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
  59. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js +0 -3
  60. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js.map +2 -2
  61. package/dist/modules/customer_accounts/events.js +1 -1
  62. package/dist/modules/customer_accounts/events.js.map +1 -1
  63. package/dist/modules/customer_accounts/lib/resolveTenantContext.js.map +1 -1
  64. package/dist/modules/customers/acl.js +1 -1
  65. package/dist/modules/customers/acl.js.map +1 -1
  66. package/dist/modules/customers/ai-tools/companies-pack.js.map +1 -1
  67. package/dist/modules/customers/ai-tools/deals-pack.js.map +1 -1
  68. package/dist/modules/customers/ai-tools/people-pack.js.map +1 -1
  69. package/dist/modules/customers/api/companies/route.js +4 -4
  70. package/dist/modules/customers/api/companies/route.js.map +2 -2
  71. package/dist/modules/customers/api/deals/route.js +43 -2
  72. package/dist/modules/customers/api/deals/route.js.map +2 -2
  73. package/dist/modules/customers/api/deals/summary/route.js +402 -0
  74. package/dist/modules/customers/api/deals/summary/route.js.map +7 -0
  75. package/dist/modules/customers/api/people/route.js +4 -4
  76. package/dist/modules/customers/api/people/route.js.map +2 -2
  77. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js +16 -5
  78. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js.map +2 -2
  79. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js +22 -5
  80. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js.map +2 -2
  81. package/dist/modules/customers/backend/customers/deals/[id]/page.js +12 -2
  82. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  83. package/dist/modules/customers/backend/customers/deals/page.js +221 -56
  84. package/dist/modules/customers/backend/customers/deals/page.js.map +3 -3
  85. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +1 -1
  86. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  87. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +18 -0
  88. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  89. package/dist/modules/customers/cli.js +15 -9
  90. package/dist/modules/customers/cli.js.map +2 -2
  91. package/dist/modules/customers/commands/addresses.js +5 -5
  92. package/dist/modules/customers/commands/addresses.js.map +2 -2
  93. package/dist/modules/customers/commands/comments.js +5 -5
  94. package/dist/modules/customers/commands/comments.js.map +2 -2
  95. package/dist/modules/customers/commands/deals.js +2 -2
  96. package/dist/modules/customers/commands/deals.js.map +2 -2
  97. package/dist/modules/customers/commands/entity-roles.js +2 -1
  98. package/dist/modules/customers/commands/entity-roles.js.map +2 -2
  99. package/dist/modules/customers/commands/interactions.js +8 -5
  100. package/dist/modules/customers/commands/interactions.js.map +2 -2
  101. package/dist/modules/customers/commands/shared.js +21 -6
  102. package/dist/modules/customers/commands/shared.js.map +2 -2
  103. package/dist/modules/customers/commands/tags.js +3 -3
  104. package/dist/modules/customers/commands/tags.js.map +2 -2
  105. package/dist/modules/customers/components/DealsKpiStrip.js +282 -0
  106. package/dist/modules/customers/components/DealsKpiStrip.js.map +7 -0
  107. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +0 -1
  108. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +2 -2
  109. package/dist/modules/customers/components/detail/DealForm.js +100 -17
  110. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  111. package/dist/modules/customers/components/detail/PersonDetailTabs.js +11 -3
  112. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  113. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +1 -2
  114. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  115. package/dist/modules/customers/components/detail/assignableStaff.js +21 -8
  116. package/dist/modules/customers/components/detail/assignableStaff.js.map +2 -2
  117. package/dist/modules/customers/components/kpi/PipelineStageBar.js +63 -0
  118. package/dist/modules/customers/components/kpi/PipelineStageBar.js.map +7 -0
  119. package/dist/modules/customers/lib/dealsMetrics.js +82 -0
  120. package/dist/modules/customers/lib/dealsMetrics.js.map +7 -0
  121. package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js.map +1 -1
  122. package/dist/modules/data_sync/api/run.js +1 -1
  123. package/dist/modules/data_sync/api/run.js.map +2 -2
  124. package/dist/modules/directory/api/organization-branding/route.js +214 -0
  125. package/dist/modules/directory/api/organization-branding/route.js.map +7 -0
  126. package/dist/modules/directory/api/organizations/route.js +7 -0
  127. package/dist/modules/directory/api/organizations/route.js.map +3 -3
  128. package/dist/modules/directory/backend/directory/branding/page.js +214 -0
  129. package/dist/modules/directory/backend/directory/branding/page.js.map +7 -0
  130. package/dist/modules/directory/backend/directory/branding/page.meta.js +26 -0
  131. package/dist/modules/directory/backend/directory/branding/page.meta.js.map +7 -0
  132. package/dist/modules/directory/commands/organizations.js +8 -1
  133. package/dist/modules/directory/commands/organizations.js.map +2 -2
  134. package/dist/modules/directory/data/entities.js +3 -0
  135. package/dist/modules/directory/data/entities.js.map +2 -2
  136. package/dist/modules/directory/data/validators.js +9 -0
  137. package/dist/modules/directory/data/validators.js.map +2 -2
  138. package/dist/modules/directory/migrations/Migration20260607222259_directory.js +13 -0
  139. package/dist/modules/directory/migrations/Migration20260607222259_directory.js.map +7 -0
  140. package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js +2 -1
  141. package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js.map +2 -2
  142. package/dist/modules/directory/utils/organizationScope.js +59 -27
  143. package/dist/modules/directory/utils/organizationScope.js.map +2 -2
  144. package/dist/modules/entities/api/definitions.batch.js +2 -1
  145. package/dist/modules/entities/api/definitions.batch.js.map +2 -2
  146. package/dist/modules/entities/api/entities.js +7 -0
  147. package/dist/modules/entities/api/entities.js.map +2 -2
  148. package/dist/modules/entities/api/records.js +26 -15
  149. package/dist/modules/entities/api/records.js.map +2 -2
  150. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +14 -0
  151. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
  152. package/dist/modules/entities/backend/entities/user/[entityId]/records/create/page.js +14 -0
  153. package/dist/modules/entities/backend/entities/user/[entityId]/records/create/page.js.map +2 -2
  154. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +12 -0
  155. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  156. package/dist/modules/entities/components/useRecordsEntityGuard.js +30 -0
  157. package/dist/modules/entities/components/useRecordsEntityGuard.js.map +7 -0
  158. package/dist/modules/payment_gateways/api/transactions/route.js +2 -4
  159. package/dist/modules/payment_gateways/api/transactions/route.js.map +2 -2
  160. package/dist/modules/progress/api/jobs/[id]/route.js +7 -2
  161. package/dist/modules/progress/api/jobs/[id]/route.js.map +2 -2
  162. package/dist/modules/progress/api/jobs/route.js +1 -1
  163. package/dist/modules/progress/api/jobs/route.js.map +2 -2
  164. package/dist/modules/progress/lib/progressServiceImpl.js +8 -2
  165. package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
  166. package/dist/modules/query_index/data/entities.js +2 -1
  167. package/dist/modules/query_index/data/entities.js.map +2 -2
  168. package/dist/modules/query_index/lib/engine.js +4 -2
  169. package/dist/modules/query_index/lib/engine.js.map +2 -2
  170. package/dist/modules/query_index/migrations/Migration20260611103000_query_index.js +16 -0
  171. package/dist/modules/query_index/migrations/Migration20260611103000_query_index.js.map +7 -0
  172. package/dist/modules/resources/api/resources.js +2 -3
  173. package/dist/modules/resources/api/resources.js.map +2 -2
  174. package/dist/modules/sales/api/documents/factory.js +2 -2
  175. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  176. package/dist/modules/sales/commands/documents.js +7 -5
  177. package/dist/modules/sales/commands/documents.js.map +2 -2
  178. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +2 -1
  179. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  180. package/dist/modules/sales/components/documents/salesDocumentsColumns.js +10 -0
  181. package/dist/modules/sales/components/documents/salesDocumentsColumns.js.map +7 -0
  182. package/dist/modules/staff/api/team-members.js +9 -2
  183. package/dist/modules/staff/api/team-members.js.map +2 -2
  184. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +24 -1
  185. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
  186. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +11 -6
  187. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  188. package/dist/modules/staff/commands/team-members.js +1 -1
  189. package/dist/modules/staff/commands/team-members.js.map +2 -2
  190. package/dist/modules/staff/components/TeamMemberForm.js +1 -1
  191. package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
  192. package/dist/modules/staff/lib/scheduleSwitch.js +23 -0
  193. package/dist/modules/staff/lib/scheduleSwitch.js.map +7 -0
  194. package/dist/modules/sync_excel/api/import/route.js +1 -1
  195. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  196. package/dist/modules/workflows/api/definitions/route.js +3 -2
  197. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  198. package/dist/modules/workflows/backend/definitions/create/page.js +1 -2
  199. package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
  200. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +1 -2
  201. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  202. package/dist/modules/workflows/components/DefinitionTriggersEditor.js +1 -2
  203. package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
  204. package/dist/modules/workflows/components/NodeEditDialog.js +4 -13
  205. package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
  206. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js +4 -13
  207. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +2 -2
  208. package/dist/modules/workflows/components/WorkflowGraphImpl.js +1 -4
  209. package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
  210. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +2 -5
  211. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +2 -2
  212. package/generated/entities/organization/index.ts +1 -0
  213. package/generated/entity-fields-registry.ts +1 -0
  214. package/package.json +11 -12
  215. package/src/bootstrap.ts +65 -7
  216. package/src/helpers/integration/crmFixtures.ts +21 -1
  217. package/src/modules/attachments/AGENTS.md +79 -0
  218. package/src/modules/attachments/api/library/route.ts +2 -2
  219. package/src/modules/attachments/api/route.ts +2 -0
  220. package/src/modules/attachments/components/AttachmentContentPreview.tsx +6 -6
  221. package/src/modules/attachments/lib/access.ts +36 -0
  222. package/src/modules/audit_logs/api/audit-logs/actions/redo/route.ts +14 -2
  223. package/src/modules/audit_logs/data/entities.ts +1 -0
  224. package/src/modules/audit_logs/migrations/.snapshot-open-mercato.json +10 -0
  225. package/src/modules/audit_logs/migrations/Migration20260611104500.ts +13 -0
  226. package/src/modules/audit_logs/services/accessLogService.ts +15 -0
  227. package/src/modules/auth/api/admin/nav.ts +9 -0
  228. package/src/modules/auth/api/login.ts +13 -13
  229. package/src/modules/auth/commands/users.ts +32 -15
  230. package/src/modules/auth/data/entities.ts +13 -1
  231. package/src/modules/auth/i18n/de.json +0 -1
  232. package/src/modules/auth/i18n/en.json +0 -1
  233. package/src/modules/auth/i18n/es.json +0 -1
  234. package/src/modules/auth/i18n/pl.json +0 -1
  235. package/src/modules/auth/lib/backendChrome.tsx +37 -1
  236. package/src/modules/auth/lib/consentIntegrity.ts +6 -3
  237. package/src/modules/auth/migrations/.snapshot-open-mercato.json +20 -10
  238. package/src/modules/auth/migrations/Migration20260610120000.ts +53 -0
  239. package/src/modules/auth/migrations/Migration20260611103000.ts +21 -0
  240. package/src/modules/auth/services/authService.ts +24 -4
  241. package/src/modules/auth/services/rbacService.ts +11 -2
  242. package/src/modules/catalog/ai-tools/configuration-pack.ts +1 -1
  243. package/src/modules/catalog/ai-tools/prices-offers-pack.ts +1 -1
  244. package/src/modules/catalog/ai-tools/products-pack.ts +1 -1
  245. package/src/modules/catalog/ai-tools/variants-pack.ts +1 -1
  246. package/src/modules/communication_channels/data/entities.ts +2 -2
  247. package/src/modules/communication_channels/encryption.ts +1 -1
  248. package/src/modules/communication_channels/lib/adapter.ts +1 -1
  249. package/src/modules/communication_channels/lib/thread-matcher.ts +1 -1
  250. package/src/modules/communication_channels/lib/thread-token.ts +1 -1
  251. package/src/modules/currencies/api/currencies/route.ts +4 -3
  252. package/src/modules/customer_accounts/api/admin/roles.ts +2 -1
  253. package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.tsx +0 -3
  254. package/src/modules/customer_accounts/events.ts +1 -1
  255. package/src/modules/customer_accounts/lib/resolveTenantContext.ts +2 -2
  256. package/src/modules/customers/acl.ts +1 -1
  257. package/src/modules/customers/ai-tools/companies-pack.ts +1 -1
  258. package/src/modules/customers/ai-tools/deals-pack.ts +1 -1
  259. package/src/modules/customers/ai-tools/people-pack.ts +1 -1
  260. package/src/modules/customers/api/companies/route.ts +4 -4
  261. package/src/modules/customers/api/deals/route.ts +51 -2
  262. package/src/modules/customers/api/deals/summary/route.ts +496 -0
  263. package/src/modules/customers/api/people/route.ts +4 -4
  264. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.ts +28 -6
  265. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealData.ts +33 -6
  266. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +17 -2
  267. package/src/modules/customers/backend/customers/deals/page.tsx +254 -66
  268. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +1 -2
  269. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +18 -0
  270. package/src/modules/customers/cli.ts +15 -15
  271. package/src/modules/customers/commands/addresses.ts +5 -5
  272. package/src/modules/customers/commands/comments.ts +5 -5
  273. package/src/modules/customers/commands/deals.ts +2 -2
  274. package/src/modules/customers/commands/entity-roles.ts +2 -1
  275. package/src/modules/customers/commands/interactions.ts +8 -5
  276. package/src/modules/customers/commands/shared.ts +26 -4
  277. package/src/modules/customers/commands/tags.ts +3 -3
  278. package/src/modules/customers/components/DealsKpiStrip.tsx +389 -0
  279. package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +0 -1
  280. package/src/modules/customers/components/detail/DealForm.tsx +121 -19
  281. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +12 -2
  282. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +1 -2
  283. package/src/modules/customers/components/detail/assignableStaff.ts +32 -8
  284. package/src/modules/customers/components/kpi/PipelineStageBar.tsx +77 -0
  285. package/src/modules/customers/i18n/de.json +43 -0
  286. package/src/modules/customers/i18n/en.json +43 -0
  287. package/src/modules/customers/i18n/es.json +43 -0
  288. package/src/modules/customers/i18n/pl.json +43 -0
  289. package/src/modules/customers/lib/dealsMetrics.ts +159 -0
  290. package/src/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.ts +1 -1
  291. package/src/modules/data_sync/api/run.ts +1 -1
  292. package/src/modules/directory/api/organization-branding/route.ts +238 -0
  293. package/src/modules/directory/api/organizations/route.ts +7 -0
  294. package/src/modules/directory/backend/directory/branding/page.meta.ts +24 -0
  295. package/src/modules/directory/backend/directory/branding/page.tsx +248 -0
  296. package/src/modules/directory/commands/organizations.ts +9 -1
  297. package/src/modules/directory/data/entities.ts +3 -0
  298. package/src/modules/directory/data/validators.ts +12 -0
  299. package/src/modules/directory/i18n/de.json +21 -0
  300. package/src/modules/directory/i18n/en.json +21 -0
  301. package/src/modules/directory/i18n/es.json +21 -0
  302. package/src/modules/directory/i18n/pl.json +21 -0
  303. package/src/modules/directory/migrations/.snapshot-open-mercato.json +40 -0
  304. package/src/modules/directory/migrations/Migration20260607222259_directory.ts +13 -0
  305. package/src/modules/directory/subscribers/invalidateOrgScopeCache.ts +3 -1
  306. package/src/modules/directory/utils/organizationScope.ts +85 -30
  307. package/src/modules/entities/api/definitions.batch.ts +11 -7
  308. package/src/modules/entities/api/entities.ts +11 -0
  309. package/src/modules/entities/api/records.ts +46 -25
  310. package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +15 -0
  311. package/src/modules/entities/backend/entities/user/[entityId]/records/create/page.tsx +15 -0
  312. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +23 -0
  313. package/src/modules/entities/components/useRecordsEntityGuard.ts +41 -0
  314. package/src/modules/entities/i18n/de.json +1 -0
  315. package/src/modules/entities/i18n/en.json +1 -0
  316. package/src/modules/entities/i18n/es.json +1 -0
  317. package/src/modules/entities/i18n/pl.json +1 -0
  318. package/src/modules/payment_gateways/api/transactions/route.ts +2 -5
  319. package/src/modules/progress/api/jobs/[id]/route.ts +6 -1
  320. package/src/modules/progress/api/jobs/route.ts +1 -1
  321. package/src/modules/progress/lib/progressServiceImpl.ts +7 -1
  322. package/src/modules/query_index/data/entities.ts +1 -0
  323. package/src/modules/query_index/lib/engine.ts +11 -5
  324. package/src/modules/query_index/migrations/.snapshot-open-mercato.json +11 -0
  325. package/src/modules/query_index/migrations/Migration20260611103000_query_index.ts +29 -0
  326. package/src/modules/resources/api/resources.ts +2 -3
  327. package/src/modules/sales/api/documents/factory.ts +2 -2
  328. package/src/modules/sales/commands/documents.ts +7 -5
  329. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +2 -1
  330. package/src/modules/sales/components/documents/salesDocumentsColumns.ts +6 -0
  331. package/src/modules/staff/AGENTS.md +1 -1
  332. package/src/modules/staff/api/team-members.ts +9 -2
  333. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +31 -1
  334. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +18 -8
  335. package/src/modules/staff/commands/team-members.ts +5 -2
  336. package/src/modules/staff/components/TeamMemberForm.tsx +4 -1
  337. package/src/modules/staff/i18n/de.json +1 -0
  338. package/src/modules/staff/i18n/en.json +1 -0
  339. package/src/modules/staff/i18n/es.json +1 -0
  340. package/src/modules/staff/i18n/pl.json +1 -0
  341. package/src/modules/staff/lib/scheduleSwitch.ts +46 -0
  342. package/src/modules/sync_excel/api/import/route.ts +1 -1
  343. package/src/modules/workflows/api/definitions/route.ts +3 -2
  344. package/src/modules/workflows/backend/definitions/create/page.tsx +1 -2
  345. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +1 -2
  346. package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +1 -2
  347. package/src/modules/workflows/components/NodeEditDialog.tsx +1 -4
  348. package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +4 -7
  349. package/src/modules/workflows/components/WorkflowGraphImpl.tsx +1 -2
  350. package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +2 -3
@@ -144,15 +144,15 @@ const createUserCommand = {
144
144
  { tenantId: null, organizationId: parsed.organizationId }
145
145
  );
146
146
  if (!organization) throw new CrudHttpError(400, { error: "Organization not found" });
147
+ const tenantId = organization.tenant?.id ? String(organization.tenant.id) : null;
147
148
  const emailHash = computeEmailHash(parsed.email);
148
- const duplicate = await findOneWithDecryption(em, User, { $or: [{ email: parsed.email }, { emailHash: { $in: emailHashLookupValues(parsed.email) } }], deletedAt: null }, {}, { tenantId: null, organizationId: null });
149
+ const duplicate = await findOneWithDecryption(em, User, { $or: [{ email: parsed.email }, { emailHash: { $in: emailHashLookupValues(parsed.email) } }], deletedAt: null, tenantId }, {}, { tenantId: null, organizationId: null });
149
150
  if (duplicate) await throwDuplicateEmailError();
150
151
  let passwordHash = null;
151
152
  if (parsed.password) {
152
153
  const { hash } = await import("bcryptjs");
153
154
  passwordHash = await hash(parsed.password, 10);
154
155
  }
155
- const tenantId = organization.tenant?.id ? String(organization.tenant.id) : null;
156
156
  const de = ctx.container.resolve("dataEngine");
157
157
  let user;
158
158
  try {
@@ -423,13 +423,27 @@ const updateUserCommand = {
423
423
  const { parsed, custom } = parseWithCustomFields(updateSchema, rawInput);
424
424
  const em = ctx.container.resolve("em");
425
425
  const rolesBefore = Array.isArray(parsed.roles) ? await loadUserRoleNames(em, parsed.id) : null;
426
+ let tenantId;
427
+ if (parsed.organizationId !== void 0) {
428
+ const organization = await findOneWithDecryption(
429
+ em,
430
+ Organization,
431
+ { id: parsed.organizationId },
432
+ { populate: ["tenant"] },
433
+ { tenantId: null, organizationId: parsed.organizationId ?? null }
434
+ );
435
+ if (!organization) throw new CrudHttpError(400, { error: "Organization not found" });
436
+ tenantId = organization.tenant?.id ? String(organization.tenant.id) : null;
437
+ }
426
438
  if (parsed.email !== void 0) {
439
+ const targetTenantId = tenantId !== void 0 ? tenantId : await resolveUserTenantId(em, parsed.id);
427
440
  const duplicate = await findOneWithDecryption(
428
441
  em,
429
442
  User,
430
443
  {
431
444
  $or: [{ email: parsed.email }, { emailHash: { $in: emailHashLookupValues(parsed.email) } }],
432
445
  deletedAt: null,
446
+ tenantId: targetTenantId,
433
447
  id: { $ne: parsed.id }
434
448
  },
435
449
  {},
@@ -446,18 +460,6 @@ const updateUserCommand = {
446
460
  if (parsed.email !== void 0) {
447
461
  emailHash = computeEmailHash(parsed.email);
448
462
  }
449
- let tenantId;
450
- if (parsed.organizationId !== void 0) {
451
- const organization = await findOneWithDecryption(
452
- em,
453
- Organization,
454
- { id: parsed.organizationId },
455
- { populate: ["tenant"] },
456
- { tenantId: null, organizationId: parsed.organizationId ?? null }
457
- );
458
- if (!organization) throw new CrudHttpError(400, { error: "Organization not found" });
459
- tenantId = organization.tenant?.id ? String(organization.tenant.id) : null;
460
- }
461
463
  const actorTenantScope = resolveActorTenantScope(ctx);
462
464
  const updateWhere = { id: parsed.id, deletedAt: null };
463
465
  if (actorTenantScope) updateWhere.tenantId = actorTenantScope;
@@ -908,6 +910,10 @@ function arrayEquals(left, right) {
908
910
  if (left.length !== right.length) return false;
909
911
  return left.every((value, idx) => value === right[idx]);
910
912
  }
913
+ async function resolveUserTenantId(em, id) {
914
+ const existing = await findOneWithDecryption(em, User, { id, deletedAt: null }, {}, { tenantId: null, organizationId: null });
915
+ return existing?.tenantId ? String(existing.tenantId) : null;
916
+ }
911
917
  async function throwDuplicateEmailError() {
912
918
  const { translate } = await resolveTranslations();
913
919
  const message = translate("auth.users.errors.emailExists", "Email already in use");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/auth/commands/users.ts"],
4
- "sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n buildChanges,\n requireId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudEventsConfig, CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { UniqueConstraintViolationException } from '@mikro-orm/core'\nimport type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { User, UserRole, Role, UserAcl, Session, PasswordReset } from '@open-mercato/core/modules/auth/data/entities'\nimport { Organization } from '@open-mercato/core/modules/directory/data/entities'\nimport { E } from '#generated/entities.ids.generated'\nimport { z } from 'zod'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n diffCustomFieldChanges,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { extractUndoPayload, type UndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { normalizeTenantId } from '@open-mercato/core/modules/auth/lib/tenantAccess'\nimport { computeEmailHash, emailHashLookupValues } from '@open-mercato/core/modules/auth/lib/emailHash'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildNotificationFromType } from '@open-mercato/core/modules/notifications/lib/notificationBuilder'\nimport { resolveNotificationService } from '@open-mercato/core/modules/notifications/lib/notificationService'\nimport notificationTypes from '@open-mercato/core/modules/auth/notifications'\nimport { buildPasswordSchema } from '@open-mercato/shared/lib/auth/passwordPolicy'\nimport { sendEmail } from '@open-mercato/shared/lib/email/send'\nimport InviteUserEmail from '@open-mercato/core/modules/auth/emails/InviteUserEmail'\nimport { INVITE_TOKEN_TTL_MS } from '@open-mercato/core/modules/auth/lib/inviteToken'\nimport { getSecurityEmailBaseUrl } from '@open-mercato/shared/lib/url'\nimport { generateAuthToken, hashAuthToken } from '@open-mercato/core/modules/auth/lib/tokenHash'\nimport { normalizeDisplayNameInput } from '@open-mercato/core/modules/auth/lib/displayName'\n\ntype SerializedUser = {\n email: string\n organizationId: string | null\n tenantId: string | null\n roles: string[]\n name: string | null\n isConfirmed: boolean\n custom?: Record<string, unknown>\n}\n\ntype UserAclSnapshot = {\n tenantId: string\n features: string[] | null\n isSuperAdmin: boolean\n organizations: string[] | null\n}\n\ntype UserUndoSnapshot = {\n id: string\n email: string\n organizationId: string | null\n tenantId: string | null\n passwordHash: string | null\n name: string | null\n isConfirmed: boolean\n roles: string[]\n acls: UserAclSnapshot[]\n custom?: Record<string, unknown>\n}\n\ntype UserSnapshots = {\n view: SerializedUser\n undo: UserUndoSnapshot\n}\n\nfunction resolveActorTenantScope(ctx: CommandRuntimeContext): string | null {\n if (ctx.systemActor === true) return null\n const auth = ctx.auth\n if (!auth) return null\n if ((auth as { isSuperAdmin?: boolean }).isSuperAdmin === true) return null\n const actorTenantId = normalizeTenantId(auth.tenantId ?? null) ?? null\n return actorTenantId\n}\n\nfunction assertTargetTenantInScope(actorTenantScope: string | null, targetTenantId: unknown, notFoundError: string): void {\n if (!actorTenantScope) return\n const targetTenant = normalizeTenantId(targetTenantId) ?? null\n if (!targetTenant || targetTenant !== actorTenantScope) {\n throw new CrudHttpError(404, { error: notFoundError })\n }\n}\n\nconst passwordSchema = buildPasswordSchema()\n\nconst displayNameSchema = z.preprocess(\n normalizeDisplayNameInput,\n z.string().trim().min(1).max(120).nullable().optional(),\n)\n\nconst createSchema = z.object({\n email: z.string().email(),\n name: displayNameSchema,\n password: passwordSchema.optional(),\n sendInviteEmail: z.boolean().optional(),\n organizationId: z.string().uuid(),\n roles: z.array(z.string()).optional(),\n}).refine(\n (data) => data.password || data.sendInviteEmail,\n { message: 'Either password or sendInviteEmail is required', path: ['password'] },\n)\n\nconst updateSchema = z.object({\n id: z.string().uuid(),\n email: z.string().email().optional(),\n name: displayNameSchema,\n password: passwordSchema.optional(),\n organizationId: z.string().uuid().optional(),\n roles: z.array(z.string()).optional(),\n})\n\nexport const userCrudEvents: CrudEventsConfig = {\n module: 'auth',\n entity: 'user',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nexport const userCrudIndexer: CrudIndexerConfig = {\n entityType: E.auth.user,\n buildUpsertPayload: (ctx) => ({\n entityType: E.auth.user,\n recordId: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n buildDeletePayload: (ctx) => ({\n entityType: E.auth.user,\n recordId: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nasync function notifyRoleChanges(\n ctx: CommandRuntimeContext,\n user: User,\n assignedRoles: string[],\n revokedRoles: string[],\n): Promise<void> {\n const tenantId = user.tenantId ? String(user.tenantId) : null\n if (!tenantId) return\n const organizationId = user.organizationId ? String(user.organizationId) : null\n\n try {\n const notificationService = resolveNotificationService(ctx.container)\n if (assignedRoles.length) {\n const assignedType = notificationTypes.find((type) => type.type === 'auth.role.assigned')\n if (assignedType) {\n const notificationInput = buildNotificationFromType(assignedType, {\n recipientUserId: String(user.id),\n sourceEntityType: 'auth:user',\n sourceEntityId: String(user.id),\n })\n await notificationService.create(notificationInput, { tenantId, organizationId })\n }\n }\n\n if (revokedRoles.length) {\n const revokedType = notificationTypes.find((type) => type.type === 'auth.role.revoked')\n if (revokedType) {\n const notificationInput = buildNotificationFromType(revokedType, {\n recipientUserId: String(user.id),\n sourceEntityType: 'auth:user',\n sourceEntityId: String(user.id),\n })\n await notificationService.create(notificationInput, { tenantId, organizationId })\n }\n }\n } catch (err) {\n console.error('[auth.users.roles] Failed to create notification:', err)\n }\n}\n\ntype CreateUserResult = { user: User; warning?: 'invite_email_failed' }\n\nconst createUserCommand: CommandHandler<Record<string, unknown>, CreateUserResult> = {\n id: 'auth.users.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(createSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n\n const organization = await findOneWithDecryption(\n em,\n Organization,\n { id: parsed.organizationId },\n { populate: ['tenant'] },\n { tenantId: null, organizationId: parsed.organizationId },\n )\n if (!organization) throw new CrudHttpError(400, { error: 'Organization not found' })\n\n const emailHash = computeEmailHash(parsed.email)\n const duplicate = await findOneWithDecryption(em, User, { $or: [{ email: parsed.email }, { emailHash: { $in: emailHashLookupValues(parsed.email) } }], deletedAt: null } as any, {}, { tenantId: null, organizationId: null })\n if (duplicate) await throwDuplicateEmailError()\n\n let passwordHash: string | null = null\n if (parsed.password) {\n const { hash } = await import('bcryptjs')\n passwordHash = await hash(parsed.password, 10)\n }\n const tenantId = organization.tenant?.id ? String(organization.tenant.id) : null\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let user: User\n try {\n user = await de.createOrmEntity({\n entity: User,\n data: {\n email: parsed.email,\n name: parsed.name,\n emailHash,\n passwordHash,\n isConfirmed: true,\n organizationId: parsed.organizationId,\n tenantId,\n },\n })\n } catch (error) {\n if (isUniqueViolation(error)) await throwDuplicateEmailError()\n throw error\n }\n\n let assignedRoles: string[] = []\n if (Array.isArray(parsed.roles) && parsed.roles.length) {\n await syncUserRoles(em, user, parsed.roles, tenantId)\n assignedRoles = await loadUserRoleNames(em, String(user.id))\n }\n\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: String(user.id),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: tenantId,\n values: custom,\n })\n\n let inviteEmailSent = false\n if (parsed.sendInviteEmail) {\n const inviteResult = await sendInviteToUser(em, user)\n inviteEmailSent = inviteResult.emailSent\n }\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: user,\n identifiers: {\n id: String(user.id),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId,\n },\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n if (assignedRoles.length && !parsed.sendInviteEmail) {\n await notifyRoleChanges(ctx, user, assignedRoles, [])\n }\n\n const warning = (parsed.sendInviteEmail && !inviteEmailSent) ? 'invite_email_failed' as const : undefined\n\n return { user, warning }\n },\n captureAfter: async (_input, { user }, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const roles = await loadUserRoleNames(em, String(user.id))\n const custom = await loadUserCustomSnapshot(\n em,\n String(user.id),\n user.tenantId ? String(user.tenantId) : null,\n user.organizationId ? String(user.organizationId) : null\n )\n return serializeUser(user, roles, custom)\n },\n buildLog: async ({ result: { user }, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const roles = await loadUserRoleNames(em, String(user.id))\n const custom = await loadUserCustomSnapshot(\n em,\n String(user.id),\n user.tenantId ? String(user.tenantId) : null,\n user.organizationId ? String(user.organizationId) : null\n )\n const snapshot = captureUserSnapshots(user, roles, undefined, custom)\n return {\n actionLabel: translate('auth.audit.users.create', 'Create user'),\n resourceKind: 'auth.user',\n resourceId: String(user.id),\n tenantId: user.tenantId ? String(user.tenantId) : null,\n organizationId: user.organizationId ? String(user.organizationId) : null,\n snapshotAfter: snapshot.view,\n payload: {\n undo: {\n after: snapshot.undo,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const userId = typeof logEntry?.resourceId === 'string' ? logEntry.resourceId : null\n if (!userId) return\n const snapshot = logEntry?.snapshotAfter as SerializedUser | undefined\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n\n let removed: User | null = null\n await withAtomicFlush(em, [\n async () => {\n await em.nativeDelete(UserAcl, { user: userId })\n await em.nativeDelete(UserRole, { user: userId })\n await em.nativeDelete(Session, { user: userId })\n await em.nativeDelete(PasswordReset, { user: userId })\n\n if (snapshot?.custom && Object.keys(snapshot.custom).length) {\n const reset = buildCustomFieldResetMap(undefined, snapshot.custom)\n if (Object.keys(reset).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: userId,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n values: reset,\n notify: false,\n })\n }\n }\n removed = await de.deleteOrmEntity({\n entity: User,\n where: { id: userId, deletedAt: null } as FilterQuery<User>,\n soft: false,\n })\n },\n ], { transaction: true })\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: removed,\n identifiers: {\n id: userId,\n organizationId: snapshot?.organizationId ?? null,\n tenantId: snapshot?.tenantId ?? null,\n },\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n await invalidateUserCache(ctx, userId)\n },\n // The create-undo hard-deletes the user, but the after-snapshot persists the\n // original passwordHash (see captureUserSnapshots), so redo restores the row\n // with the SAME id and the SAME hash \u2014 never fabricating credentials (#2506).\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<UserUndoSnapshot>(logEntry)\n if (!after) throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for user create' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n const emailHash = computeEmailHash(after.email)\n\n let user = await findOneWithDecryption(em, User, { id: after.id }, {}, { tenantId: null, organizationId: null })\n await withAtomicFlush(em, [\n async () => {\n if (user) {\n user.deletedAt = null\n user.email = after.email\n user.emailHash = emailHash\n user.organizationId = after.organizationId ?? null\n user.tenantId = after.tenantId ?? null\n user.passwordHash = after.passwordHash ?? null\n user.name = after.name ?? null\n user.isConfirmed = after.isConfirmed\n await em.flush()\n } else {\n user = await de.createOrmEntity({\n entity: User,\n data: {\n id: after.id,\n email: after.email,\n emailHash,\n organizationId: after.organizationId ?? null,\n tenantId: after.tenantId ?? null,\n passwordHash: after.passwordHash ?? null,\n name: after.name ?? null,\n isConfirmed: after.isConfirmed,\n },\n })\n }\n\n if (!user) return\n\n await em.nativeDelete(UserRole, { user: after.id })\n await syncUserRoles(em, user, after.roles, after.tenantId)\n await restoreUserAcls(em, user, after.acls)\n\n if (after.custom && Object.keys(after.custom).length) {\n const reset = buildCustomFieldResetMap(after.custom, undefined)\n if (Object.keys(reset).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: after.id,\n organizationId: after.organizationId ?? null,\n tenantId: after.tenantId ?? null,\n values: reset,\n notify: false,\n })\n }\n }\n },\n ], { transaction: true })\n\n if (!user) throw new CrudHttpError(400, { error: '[internal] redo failed to restore user row' })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: user,\n identifiers: {\n id: after.id,\n organizationId: after.organizationId ?? null,\n tenantId: after.tenantId ?? null,\n },\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n await invalidateUserCache(ctx, after.id)\n\n return { user }\n },\n}\n\nasync function sendInviteToUser(\n em: EntityManager,\n user: User,\n): Promise<{ emailSent: boolean }> {\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 base = getSecurityEmailBaseUrl()\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.invite] Failed to send invitation email:', err)\n emailSent = false\n }\n\n return { emailSent }\n}\n\nfunction isUniqueViolation(error: unknown): boolean {\n if (error instanceof UniqueConstraintViolationException) return true\n if (!error || typeof error !== 'object') return false\n const code = (error as { code?: string }).code\n if (code === '23505') return true\n const messageRaw = (error as { message?: string })?.message\n const message = typeof messageRaw === 'string' ? messageRaw : ''\n return message.toLowerCase().includes('duplicate key')\n}\n\nconst updateUserCommand: CommandHandler<Record<string, unknown>, User> = {\n id: 'auth.users.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(updateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const existing = await findOneWithDecryption(em, User, { id: parsed.id, deletedAt: null }, {}, { tenantId: null, organizationId: null })\n if (!existing) throw new CrudHttpError(404, { error: 'User not found' })\n assertTargetTenantInScope(resolveActorTenantScope(ctx), existing.tenantId, 'User not found')\n const roles = await loadUserRoleNames(em, parsed.id)\n const acls = await loadUserAclSnapshots(em, parsed.id)\n const custom = await loadUserCustomSnapshot(\n em,\n parsed.id,\n existing.tenantId ? String(existing.tenantId) : null,\n existing.organizationId ? String(existing.organizationId) : null\n )\n return { before: captureUserSnapshots(existing, roles, acls, custom) }\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(updateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const rolesBefore = Array.isArray(parsed.roles)\n ? await loadUserRoleNames(em, parsed.id)\n : null\n\n if (parsed.email !== undefined) {\n const duplicate = await findOneWithDecryption(\n em,\n User,\n {\n $or: [{ email: parsed.email }, { emailHash: { $in: emailHashLookupValues(parsed.email) } }],\n deletedAt: null,\n id: { $ne: parsed.id } as any,\n } as FilterQuery<User>,\n {},\n { tenantId: null, organizationId: null },\n )\n if (duplicate) await throwDuplicateEmailError()\n }\n\n let hashed: string | null = null\n let emailHash: string | null = null\n if (parsed.password) {\n const { hash } = await import('bcryptjs')\n hashed = await hash(parsed.password, 10)\n }\n if (parsed.email !== undefined) {\n emailHash = computeEmailHash(parsed.email)\n }\n\n let tenantId: string | null | undefined\n if (parsed.organizationId !== undefined) {\n const organization = await findOneWithDecryption(\n em,\n Organization,\n { id: parsed.organizationId },\n { populate: ['tenant'] },\n { tenantId: null, organizationId: parsed.organizationId ?? null },\n )\n if (!organization) throw new CrudHttpError(400, { error: 'Organization not found' })\n tenantId = organization.tenant?.id ? String(organization.tenant.id) : null\n }\n\n const actorTenantScope = resolveActorTenantScope(ctx)\n const updateWhere: Record<string, unknown> = { id: parsed.id, deletedAt: null }\n if (actorTenantScope) updateWhere.tenantId = actorTenantScope\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let user: User | null\n try {\n user = await de.updateOrmEntity({\n entity: User,\n where: updateWhere as FilterQuery<User>,\n apply: (entity) => {\n if (parsed.email !== undefined) {\n entity.email = parsed.email\n entity.emailHash = emailHash\n }\n if (parsed.name !== undefined) {\n entity.name = parsed.name\n }\n if (parsed.organizationId !== undefined) {\n entity.organizationId = parsed.organizationId\n entity.tenantId = tenantId ?? null\n }\n if (hashed) entity.passwordHash = hashed\n },\n })\n } catch (error) {\n if (isUniqueViolation(error)) await throwDuplicateEmailError()\n throw error\n }\n if (!user) throw new CrudHttpError(404, { error: 'User not found' })\n\n if (hashed) {\n await em.nativeDelete(Session, { user: parsed.id })\n }\n\n if (Array.isArray(parsed.roles)) {\n await syncUserRoles(em, user, parsed.roles, user.tenantId ? String(user.tenantId) : tenantId ?? null)\n }\n\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: String(user.id),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: user.tenantId ? String(user.tenantId) : tenantId ?? null,\n values: custom,\n })\n\n const identifiers = {\n id: String(user.id),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: user.tenantId ? String(user.tenantId) : tenantId ?? null,\n }\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: user,\n identifiers,\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n if (Array.isArray(parsed.roles) && rolesBefore) {\n const rolesAfter = await loadUserRoleNames(em, String(user.id))\n const { assigned, revoked } = diffRoleChanges(rolesBefore, rolesAfter)\n if (assigned.length || revoked.length) {\n await notifyRoleChanges(ctx, user, assigned, revoked)\n }\n }\n\n await invalidateUserCache(ctx, parsed.id)\n\n return user\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const roles = await loadUserRoleNames(em, String(result.id))\n const custom = await loadUserCustomSnapshot(\n em,\n String(result.id),\n result.tenantId ? String(result.tenantId) : null,\n result.organizationId ? String(result.organizationId) : null\n )\n return serializeUser(result, roles, custom)\n },\n buildLog: async ({ result, snapshots, ctx }) => {\n const { translate } = await resolveTranslations()\n const beforeSnapshots = snapshots.before as UserSnapshots | undefined\n const before = beforeSnapshots?.view\n const beforeUndo = beforeSnapshots?.undo ?? null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const afterRoles = await loadUserRoleNames(em, String(result.id))\n const afterCustom = await loadUserCustomSnapshot(\n em,\n String(result.id),\n result.tenantId ? String(result.tenantId) : null,\n result.organizationId ? String(result.organizationId) : null\n )\n const afterSnapshots = captureUserSnapshots(result, afterRoles, undefined, afterCustom)\n const after = afterSnapshots.view\n const changes = buildChanges(before ?? null, after as Record<string, unknown>, ['email', 'organizationId', 'tenantId', 'name', 'isConfirmed'])\n if (before && !arrayEquals(before.roles, afterRoles)) {\n changes.roles = { from: before.roles, to: afterRoles }\n }\n const customDiff = diffCustomFieldChanges(before?.custom, afterCustom)\n for (const [key, diff] of Object.entries(customDiff)) {\n changes[`cf_${key}`] = diff\n }\n return {\n actionLabel: translate('auth.audit.users.update', 'Update user'),\n resourceKind: 'auth.user',\n resourceId: String(result.id),\n tenantId: result.tenantId ? String(result.tenantId) : null,\n organizationId: result.organizationId ? String(result.organizationId) : null,\n changes,\n snapshotBefore: before ?? null,\n snapshotAfter: after,\n payload: {\n undo: {\n before: beforeUndo,\n after: afterSnapshots.undo,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<UndoPayload<UserUndoSnapshot>>(logEntry)\n const before = payload?.before\n const after = payload?.after\n if (!before) return\n const userId = before.id\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n const updated = await de.updateOrmEntity({\n entity: User,\n where: { id: userId, deletedAt: null } as FilterQuery<User>,\n apply: (entity) => {\n entity.email = before.email\n entity.organizationId = before.organizationId ?? null\n entity.tenantId = before.tenantId ?? null\n entity.passwordHash = before.passwordHash ?? null\n entity.name = before.name ?? null\n entity.isConfirmed = before.isConfirmed\n },\n })\n\n if (updated) {\n await syncUserRoles(em, updated, before.roles, before.tenantId)\n await em.flush()\n }\n\n const reset = buildCustomFieldResetMap(before.custom, after?.custom)\n if (Object.keys(reset).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: before.id,\n organizationId: before.organizationId ?? null,\n tenantId: before.tenantId ?? null,\n values: reset,\n notify: false,\n })\n }\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: updated,\n identifiers: {\n id: before.id,\n organizationId: before.organizationId ?? null,\n tenantId: before.tenantId ?? null,\n },\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n await invalidateUserCache(ctx, userId)\n },\n}\n\nconst deleteUserCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, User> = {\n id: 'auth.users.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'User id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const existing = await findOneWithDecryption(em, User, { id, deletedAt: null }, {}, { tenantId: null, organizationId: null })\n if (!existing) return {}\n const actorTenantScope = resolveActorTenantScope(ctx)\n if (actorTenantScope) {\n const targetTenant = normalizeTenantId(existing.tenantId) ?? null\n if (!targetTenant || targetTenant !== actorTenantScope) return {}\n }\n const roles = await loadUserRoleNames(em, id)\n const acls = await loadUserAclSnapshots(em, id)\n const custom = await loadUserCustomSnapshot(\n em,\n id,\n existing.tenantId ? String(existing.tenantId) : null,\n existing.organizationId ? String(existing.organizationId) : null\n )\n return { before: captureUserSnapshots(existing, roles, acls, custom) }\n },\n async execute(input, ctx) {\n const id = requireId(input, 'User id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n const actorTenantScope = resolveActorTenantScope(ctx)\n const deleteWhere: Record<string, unknown> = { id, deletedAt: null }\n if (actorTenantScope) deleteWhere.tenantId = actorTenantScope\n\n let user!: User\n await withAtomicFlush(em, [\n async () => {\n await em.nativeDelete(UserAcl, { user: id })\n await em.nativeDelete(UserRole, { user: id })\n await em.nativeDelete(Session, { user: id })\n await em.nativeDelete(PasswordReset, { user: id })\n const removed = await de.deleteOrmEntity({\n entity: User,\n where: deleteWhere as FilterQuery<User>,\n soft: false,\n })\n if (!removed) throw new CrudHttpError(404, { error: 'User not found' })\n user = removed\n },\n ], { transaction: true })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: user,\n identifiers: {\n id: String(id),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: user.tenantId ? String(user.tenantId) : null,\n },\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n await invalidateUserCache(ctx, id)\n\n return user\n },\n buildLog: async ({ snapshots, input, ctx }) => {\n const { translate } = await resolveTranslations()\n const beforeSnapshots = snapshots.before as UserSnapshots | undefined\n const before = beforeSnapshots?.view\n const beforeUndo = beforeSnapshots?.undo ?? null\n const id = requireId(input, 'User id required')\n return {\n actionLabel: translate('auth.audit.users.delete', 'Delete user'),\n resourceKind: 'auth.user',\n resourceId: id,\n snapshotBefore: before ?? null,\n tenantId: before?.tenantId ?? null,\n organizationId: before?.organizationId ?? null,\n payload: {\n undo: {\n before: beforeUndo,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<UndoPayload<UserUndoSnapshot>>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager)\n let user = await findOneWithDecryption(em, User, { id: before.id }, {}, { tenantId: null, organizationId: null })\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n\n await withAtomicFlush(em, [\n async () => {\n if (user) {\n if (user.deletedAt) {\n user.deletedAt = null\n }\n user.email = before.email\n user.organizationId = before.organizationId ?? null\n user.tenantId = before.tenantId ?? null\n user.passwordHash = before.passwordHash ?? null\n user.name = before.name ?? null\n user.isConfirmed = before.isConfirmed\n await em.flush()\n } else {\n user = await de.createOrmEntity({\n entity: User,\n data: {\n id: before.id,\n email: before.email,\n organizationId: before.organizationId ?? null,\n tenantId: before.tenantId ?? null,\n passwordHash: before.passwordHash ?? null,\n name: before.name ?? null,\n isConfirmed: before.isConfirmed,\n },\n })\n }\n\n if (!user) return\n\n await em.nativeDelete(UserRole, { user: before.id })\n await syncUserRoles(em, user, before.roles, before.tenantId)\n\n await restoreUserAcls(em, user, before.acls)\n\n const reset = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(reset).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: before.id,\n organizationId: before.organizationId ?? null,\n tenantId: before.tenantId ?? null,\n values: reset,\n notify: false,\n })\n }\n },\n ], { transaction: true })\n\n await invalidateUserCache(ctx, before.id)\n },\n}\n\nregisterCommand(createUserCommand)\nregisterCommand(updateUserCommand)\nregisterCommand(deleteUserCommand)\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\nasync function resolveRole(\n em: EntityManager,\n value: string,\n normalizedTenantId: string | null,\n): Promise<Role | null> {\n if (UUID_RE.test(value)) {\n const where: Record<string, unknown> = { id: value }\n if (normalizedTenantId !== null) {\n where.tenantId = normalizedTenantId\n }\n return findOneWithDecryption(em, Role, where as any, {}, { tenantId: normalizedTenantId, organizationId: null })\n }\n return findOneWithDecryption(em, Role, { name: value, tenantId: normalizedTenantId }, {}, { tenantId: normalizedTenantId, organizationId: null })\n}\n\nasync function syncUserRoles(em: EntityManager, user: User, desiredRoles: string[], tenantId: string | null) {\n const unique = Array.from(new Set(desiredRoles.map((role) => role.trim()).filter(Boolean)))\n const normalizedTenantId = normalizeTenantId(tenantId ?? null) ?? null\n\n const resolvedRoles: Role[] = []\n const missingRoles: string[] = []\n for (const value of unique) {\n const role = await resolveRole(em, value, normalizedTenantId)\n if (!role) {\n missingRoles.push(value)\n } else {\n resolvedRoles.push(role)\n }\n }\n\n if (missingRoles.length) {\n const labels = missingRoles.map((n) => `\"${n}\"`).join(', ')\n throw new CrudHttpError(400, { error: `Role(s) not found: ${labels}` })\n }\n\n const desiredIds = new Set(resolvedRoles.map((r) => String(r.id)))\n const currentLinks = await findWithDecryption(em, UserRole, { user }, {}, { tenantId: null, organizationId: null })\n const currentRoleIds = new Map(\n currentLinks.map((link) => {\n const roleId = String(link.role?.id ?? (link.role as unknown as string) ?? '')\n return [roleId, link] as const\n }),\n )\n\n for (const [roleId, link] of currentRoleIds.entries()) {\n if (!desiredIds.has(roleId) && link) {\n em.remove(link)\n }\n }\n\n for (const role of resolvedRoles) {\n if (!currentRoleIds.has(String(role.id))) {\n em.persist(em.create(UserRole, { user, role, createdAt: new Date() }))\n }\n }\n\n await em.flush()\n}\n\nasync function loadUserRoleNames(em: EntityManager, userId: string): Promise<string[]> {\n const links = await findWithDecryption(\n em,\n UserRole,\n { user: userId as unknown as User },\n { populate: ['role'] },\n { tenantId: null, organizationId: null },\n )\n const names = links\n .map((link) => link.role?.name ?? '')\n .filter((name): name is string => !!name)\n return Array.from(new Set(names)).sort((a, b) => a.localeCompare(b))\n}\n\nfunction serializeUser(user: User, roles: string[], custom?: Record<string, unknown> | null): SerializedUser {\n const payload: SerializedUser = {\n email: String(user.email ?? ''),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: user.tenantId ? String(user.tenantId) : null,\n roles,\n name: user.name ? String(user.name) : null,\n isConfirmed: Boolean(user.isConfirmed),\n }\n if (custom && Object.keys(custom).length) payload.custom = custom\n return payload\n}\n\nfunction captureUserSnapshots(\n user: User,\n roles: string[],\n acls: UserAclSnapshot[] = [],\n custom?: Record<string, unknown> | null\n): UserSnapshots {\n return {\n view: serializeUser(user, roles, custom),\n undo: {\n id: String(user.id),\n email: String(user.email ?? ''),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: user.tenantId ? String(user.tenantId) : null,\n passwordHash: user.passwordHash ? String(user.passwordHash) : null,\n name: user.name ? String(user.name) : null,\n isConfirmed: Boolean(user.isConfirmed),\n roles: [...roles],\n acls,\n ...(custom && Object.keys(custom).length ? { custom } : {}),\n },\n }\n}\n\nasync function loadUserAclSnapshots(em: EntityManager, userId: string): Promise<UserAclSnapshot[]> {\n const list = await findWithDecryption(em, UserAcl, { user: userId as unknown as User }, {}, { tenantId: null, organizationId: null })\n return list.map((acl) => ({\n tenantId: String(acl.tenantId),\n features: Array.isArray(acl.featuresJson) ? [...acl.featuresJson] : null,\n isSuperAdmin: Boolean(acl.isSuperAdmin),\n organizations: Array.isArray(acl.organizationsJson) ? [...acl.organizationsJson] : null,\n }))\n}\n\nasync function restoreUserAcls(em: EntityManager, user: User, acls: UserAclSnapshot[]) {\n await em.nativeDelete(UserAcl, { user: String(user.id) })\n for (const acl of acls) {\n const entity = em.create(UserAcl, {\n user,\n tenantId: acl.tenantId,\n featuresJson: acl.features ?? null,\n isSuperAdmin: acl.isSuperAdmin,\n organizationsJson: acl.organizations ?? null,\n createdAt: new Date(),\n })\n em.persist(entity)\n }\n await em.flush()\n}\n\nasync function loadUserCustomSnapshot(\n em: EntityManager,\n id: string,\n tenantId: string | null,\n organizationId: string | null\n): Promise<Record<string, unknown>> {\n return await loadCustomFieldSnapshot(em, {\n entityId: E.auth.user,\n recordId: id,\n tenantId,\n organizationId,\n })\n}\n\nasync function invalidateUserCache(ctx: CommandRuntimeContext, userId: string) {\n try {\n const rbacService = ctx.container.resolve('rbacService') as { invalidateUserCache: (uid: string) => Promise<void> }\n await rbacService.invalidateUserCache(userId)\n } catch {\n // RBAC not available\n }\n\n try {\n const cache = ctx.container.resolve('cache') as { deleteByTags?: (tags: string[]) => Promise<void> }\n if (cache?.deleteByTags) await cache.deleteByTags([`rbac:user:${userId}`])\n } catch {\n // cache not available\n }\n}\n\nfunction diffRoleChanges(before: string[], after: string[]) {\n const beforeSet = new Set(before)\n const afterSet = new Set(after)\n const assigned = after.filter((role) => !beforeSet.has(role))\n const revoked = before.filter((role) => !afterSet.has(role))\n return { assigned, revoked }\n}\n\nfunction arrayEquals(left: string[] | undefined, right: string[]): boolean {\n if (!left) return false\n if (left.length !== right.length) return false\n return left.every((value, idx) => value === right[idx])\n}\n\nasync function throwDuplicateEmailError(): Promise<never> {\n const { translate } = await resolveTranslations()\n const message = translate('auth.users.errors.emailExists', 'Email already in use')\n throw new CrudHttpError(400, {\n error: message,\n fieldErrors: { email: message },\n details: [{ path: ['email'], message, code: 'duplicate', origin: 'validation' }],\n })\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n buildChanges,\n requireId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudEventsConfig, CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { UniqueConstraintViolationException } from '@mikro-orm/core'\nimport type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { User, UserRole, Role, UserAcl, Session, PasswordReset } from '@open-mercato/core/modules/auth/data/entities'\nimport { Organization } from '@open-mercato/core/modules/directory/data/entities'\nimport { E } from '#generated/entities.ids.generated'\nimport { z } from 'zod'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n diffCustomFieldChanges,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { extractUndoPayload, type UndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { normalizeTenantId } from '@open-mercato/core/modules/auth/lib/tenantAccess'\nimport { computeEmailHash, emailHashLookupValues } from '@open-mercato/core/modules/auth/lib/emailHash'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildNotificationFromType } from '@open-mercato/core/modules/notifications/lib/notificationBuilder'\nimport { resolveNotificationService } from '@open-mercato/core/modules/notifications/lib/notificationService'\nimport notificationTypes from '@open-mercato/core/modules/auth/notifications'\nimport { buildPasswordSchema } from '@open-mercato/shared/lib/auth/passwordPolicy'\nimport { sendEmail } from '@open-mercato/shared/lib/email/send'\nimport InviteUserEmail from '@open-mercato/core/modules/auth/emails/InviteUserEmail'\nimport { INVITE_TOKEN_TTL_MS } from '@open-mercato/core/modules/auth/lib/inviteToken'\nimport { getSecurityEmailBaseUrl } from '@open-mercato/shared/lib/url'\nimport { generateAuthToken, hashAuthToken } from '@open-mercato/core/modules/auth/lib/tokenHash'\nimport { normalizeDisplayNameInput } from '@open-mercato/core/modules/auth/lib/displayName'\n\ntype SerializedUser = {\n email: string\n organizationId: string | null\n tenantId: string | null\n roles: string[]\n name: string | null\n isConfirmed: boolean\n custom?: Record<string, unknown>\n}\n\ntype UserAclSnapshot = {\n tenantId: string\n features: string[] | null\n isSuperAdmin: boolean\n organizations: string[] | null\n}\n\ntype UserUndoSnapshot = {\n id: string\n email: string\n organizationId: string | null\n tenantId: string | null\n passwordHash: string | null\n name: string | null\n isConfirmed: boolean\n roles: string[]\n acls: UserAclSnapshot[]\n custom?: Record<string, unknown>\n}\n\ntype UserSnapshots = {\n view: SerializedUser\n undo: UserUndoSnapshot\n}\n\nfunction resolveActorTenantScope(ctx: CommandRuntimeContext): string | null {\n if (ctx.systemActor === true) return null\n const auth = ctx.auth\n if (!auth) return null\n if ((auth as { isSuperAdmin?: boolean }).isSuperAdmin === true) return null\n const actorTenantId = normalizeTenantId(auth.tenantId ?? null) ?? null\n return actorTenantId\n}\n\nfunction assertTargetTenantInScope(actorTenantScope: string | null, targetTenantId: unknown, notFoundError: string): void {\n if (!actorTenantScope) return\n const targetTenant = normalizeTenantId(targetTenantId) ?? null\n if (!targetTenant || targetTenant !== actorTenantScope) {\n throw new CrudHttpError(404, { error: notFoundError })\n }\n}\n\nconst passwordSchema = buildPasswordSchema()\n\nconst displayNameSchema = z.preprocess(\n normalizeDisplayNameInput,\n z.string().trim().min(1).max(120).nullable().optional(),\n)\n\nconst createSchema = z.object({\n email: z.string().email(),\n name: displayNameSchema,\n password: passwordSchema.optional(),\n sendInviteEmail: z.boolean().optional(),\n organizationId: z.string().uuid(),\n roles: z.array(z.string()).optional(),\n}).refine(\n (data) => data.password || data.sendInviteEmail,\n { message: 'Either password or sendInviteEmail is required', path: ['password'] },\n)\n\nconst updateSchema = z.object({\n id: z.string().uuid(),\n email: z.string().email().optional(),\n name: displayNameSchema,\n password: passwordSchema.optional(),\n organizationId: z.string().uuid().optional(),\n roles: z.array(z.string()).optional(),\n})\n\nexport const userCrudEvents: CrudEventsConfig = {\n module: 'auth',\n entity: 'user',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nexport const userCrudIndexer: CrudIndexerConfig = {\n entityType: E.auth.user,\n buildUpsertPayload: (ctx) => ({\n entityType: E.auth.user,\n recordId: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n buildDeletePayload: (ctx) => ({\n entityType: E.auth.user,\n recordId: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nasync function notifyRoleChanges(\n ctx: CommandRuntimeContext,\n user: User,\n assignedRoles: string[],\n revokedRoles: string[],\n): Promise<void> {\n const tenantId = user.tenantId ? String(user.tenantId) : null\n if (!tenantId) return\n const organizationId = user.organizationId ? String(user.organizationId) : null\n\n try {\n const notificationService = resolveNotificationService(ctx.container)\n if (assignedRoles.length) {\n const assignedType = notificationTypes.find((type) => type.type === 'auth.role.assigned')\n if (assignedType) {\n const notificationInput = buildNotificationFromType(assignedType, {\n recipientUserId: String(user.id),\n sourceEntityType: 'auth:user',\n sourceEntityId: String(user.id),\n })\n await notificationService.create(notificationInput, { tenantId, organizationId })\n }\n }\n\n if (revokedRoles.length) {\n const revokedType = notificationTypes.find((type) => type.type === 'auth.role.revoked')\n if (revokedType) {\n const notificationInput = buildNotificationFromType(revokedType, {\n recipientUserId: String(user.id),\n sourceEntityType: 'auth:user',\n sourceEntityId: String(user.id),\n })\n await notificationService.create(notificationInput, { tenantId, organizationId })\n }\n }\n } catch (err) {\n console.error('[auth.users.roles] Failed to create notification:', err)\n }\n}\n\ntype CreateUserResult = { user: User; warning?: 'invite_email_failed' }\n\nconst createUserCommand: CommandHandler<Record<string, unknown>, CreateUserResult> = {\n id: 'auth.users.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(createSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n\n const organization = await findOneWithDecryption(\n em,\n Organization,\n { id: parsed.organizationId },\n { populate: ['tenant'] },\n { tenantId: null, organizationId: parsed.organizationId },\n )\n if (!organization) throw new CrudHttpError(400, { error: 'Organization not found' })\n const tenantId = organization.tenant?.id ? String(organization.tenant.id) : null\n\n const emailHash = computeEmailHash(parsed.email)\n // Email is unique per-tenant, not globally (see Migration20260610120000:\n // users_tenant_email_hash_uniq). Scope the duplicate check to the target tenant so the same\n // email may legitimately exist in other tenants without blocking creation or leaking\n // cross-tenant account existence (#2934).\n const duplicate = await findOneWithDecryption(em, User, { $or: [{ email: parsed.email }, { emailHash: { $in: emailHashLookupValues(parsed.email) } }], deletedAt: null, tenantId } as any, {}, { tenantId: null, organizationId: null })\n if (duplicate) await throwDuplicateEmailError()\n\n let passwordHash: string | null = null\n if (parsed.password) {\n const { hash } = await import('bcryptjs')\n passwordHash = await hash(parsed.password, 10)\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let user: User\n try {\n user = await de.createOrmEntity({\n entity: User,\n data: {\n email: parsed.email,\n name: parsed.name,\n emailHash,\n passwordHash,\n isConfirmed: true,\n organizationId: parsed.organizationId,\n tenantId,\n },\n })\n } catch (error) {\n if (isUniqueViolation(error)) await throwDuplicateEmailError()\n throw error\n }\n\n let assignedRoles: string[] = []\n if (Array.isArray(parsed.roles) && parsed.roles.length) {\n await syncUserRoles(em, user, parsed.roles, tenantId)\n assignedRoles = await loadUserRoleNames(em, String(user.id))\n }\n\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: String(user.id),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: tenantId,\n values: custom,\n })\n\n let inviteEmailSent = false\n if (parsed.sendInviteEmail) {\n const inviteResult = await sendInviteToUser(em, user)\n inviteEmailSent = inviteResult.emailSent\n }\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: user,\n identifiers: {\n id: String(user.id),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId,\n },\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n if (assignedRoles.length && !parsed.sendInviteEmail) {\n await notifyRoleChanges(ctx, user, assignedRoles, [])\n }\n\n const warning = (parsed.sendInviteEmail && !inviteEmailSent) ? 'invite_email_failed' as const : undefined\n\n return { user, warning }\n },\n captureAfter: async (_input, { user }, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const roles = await loadUserRoleNames(em, String(user.id))\n const custom = await loadUserCustomSnapshot(\n em,\n String(user.id),\n user.tenantId ? String(user.tenantId) : null,\n user.organizationId ? String(user.organizationId) : null\n )\n return serializeUser(user, roles, custom)\n },\n buildLog: async ({ result: { user }, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const roles = await loadUserRoleNames(em, String(user.id))\n const custom = await loadUserCustomSnapshot(\n em,\n String(user.id),\n user.tenantId ? String(user.tenantId) : null,\n user.organizationId ? String(user.organizationId) : null\n )\n const snapshot = captureUserSnapshots(user, roles, undefined, custom)\n return {\n actionLabel: translate('auth.audit.users.create', 'Create user'),\n resourceKind: 'auth.user',\n resourceId: String(user.id),\n tenantId: user.tenantId ? String(user.tenantId) : null,\n organizationId: user.organizationId ? String(user.organizationId) : null,\n snapshotAfter: snapshot.view,\n payload: {\n undo: {\n after: snapshot.undo,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const userId = typeof logEntry?.resourceId === 'string' ? logEntry.resourceId : null\n if (!userId) return\n const snapshot = logEntry?.snapshotAfter as SerializedUser | undefined\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n\n let removed: User | null = null\n await withAtomicFlush(em, [\n async () => {\n await em.nativeDelete(UserAcl, { user: userId })\n await em.nativeDelete(UserRole, { user: userId })\n await em.nativeDelete(Session, { user: userId })\n await em.nativeDelete(PasswordReset, { user: userId })\n\n if (snapshot?.custom && Object.keys(snapshot.custom).length) {\n const reset = buildCustomFieldResetMap(undefined, snapshot.custom)\n if (Object.keys(reset).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: userId,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n values: reset,\n notify: false,\n })\n }\n }\n removed = await de.deleteOrmEntity({\n entity: User,\n where: { id: userId, deletedAt: null } as FilterQuery<User>,\n soft: false,\n })\n },\n ], { transaction: true })\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: removed,\n identifiers: {\n id: userId,\n organizationId: snapshot?.organizationId ?? null,\n tenantId: snapshot?.tenantId ?? null,\n },\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n await invalidateUserCache(ctx, userId)\n },\n // The create-undo hard-deletes the user, but the after-snapshot persists the\n // original passwordHash (see captureUserSnapshots), so redo restores the row\n // with the SAME id and the SAME hash \u2014 never fabricating credentials (#2506).\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<UserUndoSnapshot>(logEntry)\n if (!after) throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for user create' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n const emailHash = computeEmailHash(after.email)\n\n let user = await findOneWithDecryption(em, User, { id: after.id }, {}, { tenantId: null, organizationId: null })\n await withAtomicFlush(em, [\n async () => {\n if (user) {\n user.deletedAt = null\n user.email = after.email\n user.emailHash = emailHash\n user.organizationId = after.organizationId ?? null\n user.tenantId = after.tenantId ?? null\n user.passwordHash = after.passwordHash ?? null\n user.name = after.name ?? null\n user.isConfirmed = after.isConfirmed\n await em.flush()\n } else {\n user = await de.createOrmEntity({\n entity: User,\n data: {\n id: after.id,\n email: after.email,\n emailHash,\n organizationId: after.organizationId ?? null,\n tenantId: after.tenantId ?? null,\n passwordHash: after.passwordHash ?? null,\n name: after.name ?? null,\n isConfirmed: after.isConfirmed,\n },\n })\n }\n\n if (!user) return\n\n await em.nativeDelete(UserRole, { user: after.id })\n await syncUserRoles(em, user, after.roles, after.tenantId)\n await restoreUserAcls(em, user, after.acls)\n\n if (after.custom && Object.keys(after.custom).length) {\n const reset = buildCustomFieldResetMap(after.custom, undefined)\n if (Object.keys(reset).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: after.id,\n organizationId: after.organizationId ?? null,\n tenantId: after.tenantId ?? null,\n values: reset,\n notify: false,\n })\n }\n }\n },\n ], { transaction: true })\n\n if (!user) throw new CrudHttpError(400, { error: '[internal] redo failed to restore user row' })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: user,\n identifiers: {\n id: after.id,\n organizationId: after.organizationId ?? null,\n tenantId: after.tenantId ?? null,\n },\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n await invalidateUserCache(ctx, after.id)\n\n return { user }\n },\n}\n\nasync function sendInviteToUser(\n em: EntityManager,\n user: User,\n): Promise<{ emailSent: boolean }> {\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 base = getSecurityEmailBaseUrl()\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.invite] Failed to send invitation email:', err)\n emailSent = false\n }\n\n return { emailSent }\n}\n\nfunction isUniqueViolation(error: unknown): boolean {\n if (error instanceof UniqueConstraintViolationException) return true\n if (!error || typeof error !== 'object') return false\n const code = (error as { code?: string }).code\n if (code === '23505') return true\n const messageRaw = (error as { message?: string })?.message\n const message = typeof messageRaw === 'string' ? messageRaw : ''\n return message.toLowerCase().includes('duplicate key')\n}\n\nconst updateUserCommand: CommandHandler<Record<string, unknown>, User> = {\n id: 'auth.users.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(updateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const existing = await findOneWithDecryption(em, User, { id: parsed.id, deletedAt: null }, {}, { tenantId: null, organizationId: null })\n if (!existing) throw new CrudHttpError(404, { error: 'User not found' })\n assertTargetTenantInScope(resolveActorTenantScope(ctx), existing.tenantId, 'User not found')\n const roles = await loadUserRoleNames(em, parsed.id)\n const acls = await loadUserAclSnapshots(em, parsed.id)\n const custom = await loadUserCustomSnapshot(\n em,\n parsed.id,\n existing.tenantId ? String(existing.tenantId) : null,\n existing.organizationId ? String(existing.organizationId) : null\n )\n return { before: captureUserSnapshots(existing, roles, acls, custom) }\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(updateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const rolesBefore = Array.isArray(parsed.roles)\n ? await loadUserRoleNames(em, parsed.id)\n : null\n\n // Resolve the tenant the user will belong to after this update first, so the email\n // duplicate check below can be scoped to it. Email is unique per-tenant, not globally\n // (see Migration20260610120000: users_tenant_email_hash_uniq) \u2014 a matching email in another\n // tenant must not block the update or leak cross-tenant account existence (#2934).\n let tenantId: string | null | undefined\n if (parsed.organizationId !== undefined) {\n const organization = await findOneWithDecryption(\n em,\n Organization,\n { id: parsed.organizationId },\n { populate: ['tenant'] },\n { tenantId: null, organizationId: parsed.organizationId ?? null },\n )\n if (!organization) throw new CrudHttpError(400, { error: 'Organization not found' })\n tenantId = organization.tenant?.id ? String(organization.tenant.id) : null\n }\n\n if (parsed.email !== undefined) {\n const targetTenantId = tenantId !== undefined\n ? tenantId\n : await resolveUserTenantId(em, parsed.id)\n const duplicate = await findOneWithDecryption(\n em,\n User,\n {\n $or: [{ email: parsed.email }, { emailHash: { $in: emailHashLookupValues(parsed.email) } }],\n deletedAt: null,\n tenantId: targetTenantId,\n id: { $ne: parsed.id } as any,\n } as FilterQuery<User>,\n {},\n { tenantId: null, organizationId: null },\n )\n if (duplicate) await throwDuplicateEmailError()\n }\n\n let hashed: string | null = null\n let emailHash: string | null = null\n if (parsed.password) {\n const { hash } = await import('bcryptjs')\n hashed = await hash(parsed.password, 10)\n }\n if (parsed.email !== undefined) {\n emailHash = computeEmailHash(parsed.email)\n }\n\n const actorTenantScope = resolveActorTenantScope(ctx)\n const updateWhere: Record<string, unknown> = { id: parsed.id, deletedAt: null }\n if (actorTenantScope) updateWhere.tenantId = actorTenantScope\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let user: User | null\n try {\n user = await de.updateOrmEntity({\n entity: User,\n where: updateWhere as FilterQuery<User>,\n apply: (entity) => {\n if (parsed.email !== undefined) {\n entity.email = parsed.email\n entity.emailHash = emailHash\n }\n if (parsed.name !== undefined) {\n entity.name = parsed.name\n }\n if (parsed.organizationId !== undefined) {\n entity.organizationId = parsed.organizationId\n entity.tenantId = tenantId ?? null\n }\n if (hashed) entity.passwordHash = hashed\n },\n })\n } catch (error) {\n if (isUniqueViolation(error)) await throwDuplicateEmailError()\n throw error\n }\n if (!user) throw new CrudHttpError(404, { error: 'User not found' })\n\n if (hashed) {\n await em.nativeDelete(Session, { user: parsed.id })\n }\n\n if (Array.isArray(parsed.roles)) {\n await syncUserRoles(em, user, parsed.roles, user.tenantId ? String(user.tenantId) : tenantId ?? null)\n }\n\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: String(user.id),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: user.tenantId ? String(user.tenantId) : tenantId ?? null,\n values: custom,\n })\n\n const identifiers = {\n id: String(user.id),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: user.tenantId ? String(user.tenantId) : tenantId ?? null,\n }\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: user,\n identifiers,\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n if (Array.isArray(parsed.roles) && rolesBefore) {\n const rolesAfter = await loadUserRoleNames(em, String(user.id))\n const { assigned, revoked } = diffRoleChanges(rolesBefore, rolesAfter)\n if (assigned.length || revoked.length) {\n await notifyRoleChanges(ctx, user, assigned, revoked)\n }\n }\n\n await invalidateUserCache(ctx, parsed.id)\n\n return user\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const roles = await loadUserRoleNames(em, String(result.id))\n const custom = await loadUserCustomSnapshot(\n em,\n String(result.id),\n result.tenantId ? String(result.tenantId) : null,\n result.organizationId ? String(result.organizationId) : null\n )\n return serializeUser(result, roles, custom)\n },\n buildLog: async ({ result, snapshots, ctx }) => {\n const { translate } = await resolveTranslations()\n const beforeSnapshots = snapshots.before as UserSnapshots | undefined\n const before = beforeSnapshots?.view\n const beforeUndo = beforeSnapshots?.undo ?? null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const afterRoles = await loadUserRoleNames(em, String(result.id))\n const afterCustom = await loadUserCustomSnapshot(\n em,\n String(result.id),\n result.tenantId ? String(result.tenantId) : null,\n result.organizationId ? String(result.organizationId) : null\n )\n const afterSnapshots = captureUserSnapshots(result, afterRoles, undefined, afterCustom)\n const after = afterSnapshots.view\n const changes = buildChanges(before ?? null, after as Record<string, unknown>, ['email', 'organizationId', 'tenantId', 'name', 'isConfirmed'])\n if (before && !arrayEquals(before.roles, afterRoles)) {\n changes.roles = { from: before.roles, to: afterRoles }\n }\n const customDiff = diffCustomFieldChanges(before?.custom, afterCustom)\n for (const [key, diff] of Object.entries(customDiff)) {\n changes[`cf_${key}`] = diff\n }\n return {\n actionLabel: translate('auth.audit.users.update', 'Update user'),\n resourceKind: 'auth.user',\n resourceId: String(result.id),\n tenantId: result.tenantId ? String(result.tenantId) : null,\n organizationId: result.organizationId ? String(result.organizationId) : null,\n changes,\n snapshotBefore: before ?? null,\n snapshotAfter: after,\n payload: {\n undo: {\n before: beforeUndo,\n after: afterSnapshots.undo,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<UndoPayload<UserUndoSnapshot>>(logEntry)\n const before = payload?.before\n const after = payload?.after\n if (!before) return\n const userId = before.id\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n const updated = await de.updateOrmEntity({\n entity: User,\n where: { id: userId, deletedAt: null } as FilterQuery<User>,\n apply: (entity) => {\n entity.email = before.email\n entity.organizationId = before.organizationId ?? null\n entity.tenantId = before.tenantId ?? null\n entity.passwordHash = before.passwordHash ?? null\n entity.name = before.name ?? null\n entity.isConfirmed = before.isConfirmed\n },\n })\n\n if (updated) {\n await syncUserRoles(em, updated, before.roles, before.tenantId)\n await em.flush()\n }\n\n const reset = buildCustomFieldResetMap(before.custom, after?.custom)\n if (Object.keys(reset).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: before.id,\n organizationId: before.organizationId ?? null,\n tenantId: before.tenantId ?? null,\n values: reset,\n notify: false,\n })\n }\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: updated,\n identifiers: {\n id: before.id,\n organizationId: before.organizationId ?? null,\n tenantId: before.tenantId ?? null,\n },\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n await invalidateUserCache(ctx, userId)\n },\n}\n\nconst deleteUserCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, User> = {\n id: 'auth.users.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'User id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const existing = await findOneWithDecryption(em, User, { id, deletedAt: null }, {}, { tenantId: null, organizationId: null })\n if (!existing) return {}\n const actorTenantScope = resolveActorTenantScope(ctx)\n if (actorTenantScope) {\n const targetTenant = normalizeTenantId(existing.tenantId) ?? null\n if (!targetTenant || targetTenant !== actorTenantScope) return {}\n }\n const roles = await loadUserRoleNames(em, id)\n const acls = await loadUserAclSnapshots(em, id)\n const custom = await loadUserCustomSnapshot(\n em,\n id,\n existing.tenantId ? String(existing.tenantId) : null,\n existing.organizationId ? String(existing.organizationId) : null\n )\n return { before: captureUserSnapshots(existing, roles, acls, custom) }\n },\n async execute(input, ctx) {\n const id = requireId(input, 'User id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n const actorTenantScope = resolveActorTenantScope(ctx)\n const deleteWhere: Record<string, unknown> = { id, deletedAt: null }\n if (actorTenantScope) deleteWhere.tenantId = actorTenantScope\n\n let user!: User\n await withAtomicFlush(em, [\n async () => {\n await em.nativeDelete(UserAcl, { user: id })\n await em.nativeDelete(UserRole, { user: id })\n await em.nativeDelete(Session, { user: id })\n await em.nativeDelete(PasswordReset, { user: id })\n const removed = await de.deleteOrmEntity({\n entity: User,\n where: deleteWhere as FilterQuery<User>,\n soft: false,\n })\n if (!removed) throw new CrudHttpError(404, { error: 'User not found' })\n user = removed\n },\n ], { transaction: true })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: user,\n identifiers: {\n id: String(id),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: user.tenantId ? String(user.tenantId) : null,\n },\n events: userCrudEvents,\n indexer: userCrudIndexer,\n })\n\n await invalidateUserCache(ctx, id)\n\n return user\n },\n buildLog: async ({ snapshots, input, ctx }) => {\n const { translate } = await resolveTranslations()\n const beforeSnapshots = snapshots.before as UserSnapshots | undefined\n const before = beforeSnapshots?.view\n const beforeUndo = beforeSnapshots?.undo ?? null\n const id = requireId(input, 'User id required')\n return {\n actionLabel: translate('auth.audit.users.delete', 'Delete user'),\n resourceKind: 'auth.user',\n resourceId: id,\n snapshotBefore: before ?? null,\n tenantId: before?.tenantId ?? null,\n organizationId: before?.organizationId ?? null,\n payload: {\n undo: {\n before: beforeUndo,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<UndoPayload<UserUndoSnapshot>>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager)\n let user = await findOneWithDecryption(em, User, { id: before.id }, {}, { tenantId: null, organizationId: null })\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n\n await withAtomicFlush(em, [\n async () => {\n if (user) {\n if (user.deletedAt) {\n user.deletedAt = null\n }\n user.email = before.email\n user.organizationId = before.organizationId ?? null\n user.tenantId = before.tenantId ?? null\n user.passwordHash = before.passwordHash ?? null\n user.name = before.name ?? null\n user.isConfirmed = before.isConfirmed\n await em.flush()\n } else {\n user = await de.createOrmEntity({\n entity: User,\n data: {\n id: before.id,\n email: before.email,\n organizationId: before.organizationId ?? null,\n tenantId: before.tenantId ?? null,\n passwordHash: before.passwordHash ?? null,\n name: before.name ?? null,\n isConfirmed: before.isConfirmed,\n },\n })\n }\n\n if (!user) return\n\n await em.nativeDelete(UserRole, { user: before.id })\n await syncUserRoles(em, user, before.roles, before.tenantId)\n\n await restoreUserAcls(em, user, before.acls)\n\n const reset = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(reset).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.auth.user,\n recordId: before.id,\n organizationId: before.organizationId ?? null,\n tenantId: before.tenantId ?? null,\n values: reset,\n notify: false,\n })\n }\n },\n ], { transaction: true })\n\n await invalidateUserCache(ctx, before.id)\n },\n}\n\nregisterCommand(createUserCommand)\nregisterCommand(updateUserCommand)\nregisterCommand(deleteUserCommand)\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\nasync function resolveRole(\n em: EntityManager,\n value: string,\n normalizedTenantId: string | null,\n): Promise<Role | null> {\n if (UUID_RE.test(value)) {\n const where: Record<string, unknown> = { id: value }\n if (normalizedTenantId !== null) {\n where.tenantId = normalizedTenantId\n }\n return findOneWithDecryption(em, Role, where as any, {}, { tenantId: normalizedTenantId, organizationId: null })\n }\n return findOneWithDecryption(em, Role, { name: value, tenantId: normalizedTenantId }, {}, { tenantId: normalizedTenantId, organizationId: null })\n}\n\nasync function syncUserRoles(em: EntityManager, user: User, desiredRoles: string[], tenantId: string | null) {\n const unique = Array.from(new Set(desiredRoles.map((role) => role.trim()).filter(Boolean)))\n const normalizedTenantId = normalizeTenantId(tenantId ?? null) ?? null\n\n const resolvedRoles: Role[] = []\n const missingRoles: string[] = []\n for (const value of unique) {\n const role = await resolveRole(em, value, normalizedTenantId)\n if (!role) {\n missingRoles.push(value)\n } else {\n resolvedRoles.push(role)\n }\n }\n\n if (missingRoles.length) {\n const labels = missingRoles.map((n) => `\"${n}\"`).join(', ')\n throw new CrudHttpError(400, { error: `Role(s) not found: ${labels}` })\n }\n\n const desiredIds = new Set(resolvedRoles.map((r) => String(r.id)))\n const currentLinks = await findWithDecryption(em, UserRole, { user }, {}, { tenantId: null, organizationId: null })\n const currentRoleIds = new Map(\n currentLinks.map((link) => {\n const roleId = String(link.role?.id ?? (link.role as unknown as string) ?? '')\n return [roleId, link] as const\n }),\n )\n\n for (const [roleId, link] of currentRoleIds.entries()) {\n if (!desiredIds.has(roleId) && link) {\n em.remove(link)\n }\n }\n\n for (const role of resolvedRoles) {\n if (!currentRoleIds.has(String(role.id))) {\n em.persist(em.create(UserRole, { user, role, createdAt: new Date() }))\n }\n }\n\n await em.flush()\n}\n\nasync function loadUserRoleNames(em: EntityManager, userId: string): Promise<string[]> {\n const links = await findWithDecryption(\n em,\n UserRole,\n { user: userId as unknown as User },\n { populate: ['role'] },\n { tenantId: null, organizationId: null },\n )\n const names = links\n .map((link) => link.role?.name ?? '')\n .filter((name): name is string => !!name)\n return Array.from(new Set(names)).sort((a, b) => a.localeCompare(b))\n}\n\nfunction serializeUser(user: User, roles: string[], custom?: Record<string, unknown> | null): SerializedUser {\n const payload: SerializedUser = {\n email: String(user.email ?? ''),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: user.tenantId ? String(user.tenantId) : null,\n roles,\n name: user.name ? String(user.name) : null,\n isConfirmed: Boolean(user.isConfirmed),\n }\n if (custom && Object.keys(custom).length) payload.custom = custom\n return payload\n}\n\nfunction captureUserSnapshots(\n user: User,\n roles: string[],\n acls: UserAclSnapshot[] = [],\n custom?: Record<string, unknown> | null\n): UserSnapshots {\n return {\n view: serializeUser(user, roles, custom),\n undo: {\n id: String(user.id),\n email: String(user.email ?? ''),\n organizationId: user.organizationId ? String(user.organizationId) : null,\n tenantId: user.tenantId ? String(user.tenantId) : null,\n passwordHash: user.passwordHash ? String(user.passwordHash) : null,\n name: user.name ? String(user.name) : null,\n isConfirmed: Boolean(user.isConfirmed),\n roles: [...roles],\n acls,\n ...(custom && Object.keys(custom).length ? { custom } : {}),\n },\n }\n}\n\nasync function loadUserAclSnapshots(em: EntityManager, userId: string): Promise<UserAclSnapshot[]> {\n const list = await findWithDecryption(em, UserAcl, { user: userId as unknown as User }, {}, { tenantId: null, organizationId: null })\n return list.map((acl) => ({\n tenantId: String(acl.tenantId),\n features: Array.isArray(acl.featuresJson) ? [...acl.featuresJson] : null,\n isSuperAdmin: Boolean(acl.isSuperAdmin),\n organizations: Array.isArray(acl.organizationsJson) ? [...acl.organizationsJson] : null,\n }))\n}\n\nasync function restoreUserAcls(em: EntityManager, user: User, acls: UserAclSnapshot[]) {\n await em.nativeDelete(UserAcl, { user: String(user.id) })\n for (const acl of acls) {\n const entity = em.create(UserAcl, {\n user,\n tenantId: acl.tenantId,\n featuresJson: acl.features ?? null,\n isSuperAdmin: acl.isSuperAdmin,\n organizationsJson: acl.organizations ?? null,\n createdAt: new Date(),\n })\n em.persist(entity)\n }\n await em.flush()\n}\n\nasync function loadUserCustomSnapshot(\n em: EntityManager,\n id: string,\n tenantId: string | null,\n organizationId: string | null\n): Promise<Record<string, unknown>> {\n return await loadCustomFieldSnapshot(em, {\n entityId: E.auth.user,\n recordId: id,\n tenantId,\n organizationId,\n })\n}\n\nasync function invalidateUserCache(ctx: CommandRuntimeContext, userId: string) {\n try {\n const rbacService = ctx.container.resolve('rbacService') as { invalidateUserCache: (uid: string) => Promise<void> }\n await rbacService.invalidateUserCache(userId)\n } catch {\n // RBAC not available\n }\n\n try {\n const cache = ctx.container.resolve('cache') as { deleteByTags?: (tags: string[]) => Promise<void> }\n if (cache?.deleteByTags) await cache.deleteByTags([`rbac:user:${userId}`])\n } catch {\n // cache not available\n }\n}\n\nfunction diffRoleChanges(before: string[], after: string[]) {\n const beforeSet = new Set(before)\n const afterSet = new Set(after)\n const assigned = after.filter((role) => !beforeSet.has(role))\n const revoked = before.filter((role) => !afterSet.has(role))\n return { assigned, revoked }\n}\n\nfunction arrayEquals(left: string[] | undefined, right: string[]): boolean {\n if (!left) return false\n if (left.length !== right.length) return false\n return left.every((value, idx) => value === right[idx])\n}\n\nasync function resolveUserTenantId(em: EntityManager, id: string): Promise<string | null> {\n const existing = await findOneWithDecryption(em, User, { id, deletedAt: null }, {}, { tenantId: null, organizationId: null })\n return existing?.tenantId ? String(existing.tenantId) : null\n}\n\nasync function throwDuplicateEmailError(): Promise<never> {\n const { translate } = await resolveTranslations()\n const message = translate('auth.users.errors.emailExists', 'Email already in use')\n throw new CrudHttpError(400, {\n error: message,\n fieldErrors: { email: message },\n details: [{ path: ['email'], message, code: 'duplicate', origin: 'validation' }],\n })\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -25,7 +25,7 @@ __decorateClass([
25
25
  Property({ name: "organization_id", type: "uuid", nullable: true })
26
26
  ], User.prototype, "organizationId", 2);
27
27
  __decorateClass([
28
- Property({ type: "text", unique: true })
28
+ Property({ type: "text" })
29
29
  ], User.prototype, "email", 2);
30
30
  __decorateClass([
31
31
  Property({ name: "email_hash", type: "text", nullable: true }),
@@ -212,7 +212,9 @@ __decorateClass([
212
212
  Property({ name: "deleted_at", type: Date, nullable: true })
213
213
  ], UserRole.prototype, "deletedAt", 2);
214
214
  UserRole = __decorateClass([
215
- Entity({ tableName: "user_roles" })
215
+ Entity({ tableName: "user_roles" }),
216
+ Index({ name: "user_roles_user_id_idx", properties: ["user"] }),
217
+ Index({ name: "user_roles_role_id_idx", properties: ["role"] })
216
218
  ], UserRole);
217
219
  let Session = class {
218
220
  constructor() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/auth/data/entities.ts"],
4
- "sourcesContent": ["import { Entity, Index, ManyToOne, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\n@Entity({ tableName: 'users' })\nexport class User {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ type: 'text', unique: true })\n email!: string\n\n @Property({ name: 'email_hash', type: 'text', nullable: true })\n @Index({ name: 'users_email_hash_idx' })\n emailHash?: string | null\n\n @Property({ type: 'text', nullable: true })\n name?: string | null\n\n @Property({ name: 'password_hash', type: 'text', nullable: true })\n passwordHash?: string | null\n\n @Property({ name: 'is_confirmed', type: 'boolean', default: true })\n isConfirmed: boolean = true\n\n @Property({ name: 'last_login_at', type: Date, nullable: true })\n lastLoginAt?: Date\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date | null\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'roles' })\n@Unique({ properties: ['tenantId', 'name'] })\nexport class Role {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ type: 'text' })\n name!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date | null\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'user_sidebar_preferences' })\n// Uniqueness is enforced by a partial unique index (`user_sidebar_preferences_active_unique_idx`)\n// scoped to live rows (`WHERE deleted_at IS NULL`) and owned by raw SQL in\n// Migration20260427143311. A `@Unique` decorator can't express a partial index,\n// so the entity intentionally omits it \u2014 the migration is the source of truth.\nexport class UserSidebarPreference {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ type: 'text' })\n locale!: string\n\n @Property({ name: 'settings_json', type: 'json', nullable: true })\n settingsJson?: unknown\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'role_sidebar_preferences' })\n// Uniqueness is enforced by a partial unique index (`role_sidebar_preferences_active_unique_idx`)\n// scoped to live rows (`WHERE deleted_at IS NULL`) and owned by raw SQL in\n// Migration20260427143311. A `@Unique` decorator can't express a partial index,\n// so the entity intentionally omits it \u2014 the migration is the source of truth.\nexport class RoleSidebarPreference {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => Role)\n role!: Role\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ type: 'text' })\n locale!: string\n\n @Property({ name: 'settings_json', type: 'json', nullable: true })\n settingsJson?: unknown\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'sidebar_variants' })\n// Uniqueness is enforced by a partial unique index (`sidebar_variants_active_name_unique_idx`)\n// scoped to live rows (`WHERE deleted_at IS NULL`) and owned by raw SQL in\n// Migration20260427143311. A `@Unique` decorator can't express a partial index,\n// so the entity intentionally omits it \u2014 the migration is the source of truth.\nexport class SidebarVariant {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ type: 'text' })\n locale!: string\n\n @Property({ type: 'text' })\n name!: string\n\n @Property({ name: 'settings_json', type: 'json', nullable: true })\n settingsJson?: unknown\n\n @Property({ name: 'is_active', type: 'boolean', default: false })\n isActive: boolean = false\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'user_roles' })\nexport class UserRole {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n @ManyToOne(() => Role)\n role!: Role\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'sessions' })\nexport class Session {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n @Property({ type: 'text', unique: true })\n token!: string\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'last_used_at', type: Date, nullable: true })\n lastUsedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'password_resets' })\nexport class PasswordReset {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n @Property({ type: 'text', unique: true })\n token!: string\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'used_at', type: Date, nullable: true })\n usedAt?: Date\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// RBAC: Role-level ACL\n@Entity({ tableName: 'role_acls' })\nexport class RoleAcl {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => Role)\n role!: Role\n\n // Tenant scope is mandatory for ACL evaluation\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n // Feature list (string-based). Use JSON array to preserve order and allow wildcards like \"example.*\".\n @Property({ name: 'features_json', type: 'json', nullable: true })\n featuresJson?: string[] | null\n\n // If true, user with this role can do everything regardless of features\n @Property({ name: 'is_super_admin', type: 'boolean', default: false })\n isSuperAdmin: boolean = false\n\n // Visible organizations within the tenant; null/empty means all organizations\n @Property({ name: 'organizations_json', type: 'json', nullable: true })\n organizationsJson?: string[] | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// RBAC: Per-user ACL override\n@Entity({ tableName: 'user_acls' })\nexport class UserAcl {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n // Tenant scope is mandatory for ACL evaluation\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n // Feature list (string-based). Use JSON array to preserve order and allow wildcards like \"example.*\".\n @Property({ name: 'features_json', type: 'json', nullable: true })\n featuresJson?: string[] | null\n\n // If true, this user can do everything regardless of features\n @Property({ name: 'is_super_admin', type: 'boolean', default: false })\n isSuperAdmin: boolean = false\n\n // Visible organizations within the tenant; null/empty means all organizations\n @Property({ name: 'organizations_json', type: 'json', nullable: true })\n organizationsJson?: string[] | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'user_consents' })\n@Unique({ properties: ['userId', 'tenantId', 'consentType'] })\nexport class UserConsent {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'user_id', type: 'uuid' })\n userId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'consent_type', type: 'text' })\n consentType!: string\n\n @Property({ name: 'is_granted', type: 'boolean', default: false })\n isGranted: boolean = false\n\n @Property({ name: 'granted_at', type: Date, nullable: true })\n grantedAt?: Date | null\n\n @Property({ name: 'withdrawn_at', type: Date, nullable: true })\n withdrawnAt?: Date | null\n\n @Property({ type: 'text', nullable: true })\n source?: string | null\n\n @Property({ name: 'ip_address', type: 'text', nullable: true })\n ipAddress?: string | null\n\n @Property({ name: 'integrity_hash', type: 'text', nullable: true })\n integrityHash?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Entity, Index, ManyToOne, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\n@Entity({ tableName: 'users' })\n// Email uniqueness is per-tenant, enforced by a partial unique index\n// (`users_tenant_email_hash_uniq`) on `(tenant_id, email_hash)` over live rows\n// (`WHERE deleted_at IS NULL AND email_hash IS NOT NULL`), owned by raw SQL in\n// Migration20260610120000. It keys on the deterministic `email_hash`, not `email`, because\n// `email` is encrypted at rest with a per-row IV (see encryption.ts) \u2014 its ciphertext is\n// non-deterministic, so a unique index on it would not detect duplicates. A `@Unique`\n// decorator can't express a partial, tenant-scoped index, so the entity omits it \u2014 the\n// migration is the source of truth. A global unique constraint contradicts the multi-tenant\n// login flow and leaks cross-tenant account existence (#2934). Mirrors\n// `customer_users_tenant_email_hash_uniq`.\nexport class User {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ type: 'text' })\n email!: string\n\n @Property({ name: 'email_hash', type: 'text', nullable: true })\n @Index({ name: 'users_email_hash_idx' })\n emailHash?: string | null\n\n @Property({ type: 'text', nullable: true })\n name?: string | null\n\n @Property({ name: 'password_hash', type: 'text', nullable: true })\n passwordHash?: string | null\n\n @Property({ name: 'is_confirmed', type: 'boolean', default: true })\n isConfirmed: boolean = true\n\n @Property({ name: 'last_login_at', type: Date, nullable: true })\n lastLoginAt?: Date\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date | null\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'roles' })\n@Unique({ properties: ['tenantId', 'name'] })\nexport class Role {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ type: 'text' })\n name!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date | null\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'user_sidebar_preferences' })\n// Uniqueness is enforced by a partial unique index (`user_sidebar_preferences_active_unique_idx`)\n// scoped to live rows (`WHERE deleted_at IS NULL`) and owned by raw SQL in\n// Migration20260427143311. A `@Unique` decorator can't express a partial index,\n// so the entity intentionally omits it \u2014 the migration is the source of truth.\nexport class UserSidebarPreference {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ type: 'text' })\n locale!: string\n\n @Property({ name: 'settings_json', type: 'json', nullable: true })\n settingsJson?: unknown\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'role_sidebar_preferences' })\n// Uniqueness is enforced by a partial unique index (`role_sidebar_preferences_active_unique_idx`)\n// scoped to live rows (`WHERE deleted_at IS NULL`) and owned by raw SQL in\n// Migration20260427143311. A `@Unique` decorator can't express a partial index,\n// so the entity intentionally omits it \u2014 the migration is the source of truth.\nexport class RoleSidebarPreference {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => Role)\n role!: Role\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ type: 'text' })\n locale!: string\n\n @Property({ name: 'settings_json', type: 'json', nullable: true })\n settingsJson?: unknown\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'sidebar_variants' })\n// Uniqueness is enforced by a partial unique index (`sidebar_variants_active_name_unique_idx`)\n// scoped to live rows (`WHERE deleted_at IS NULL`) and owned by raw SQL in\n// Migration20260427143311. A `@Unique` decorator can't express a partial index,\n// so the entity intentionally omits it \u2014 the migration is the source of truth.\nexport class SidebarVariant {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ type: 'text' })\n locale!: string\n\n @Property({ type: 'text' })\n name!: string\n\n @Property({ name: 'settings_json', type: 'json', nullable: true })\n settingsJson?: unknown\n\n @Property({ name: 'is_active', type: 'boolean', default: false })\n isActive: boolean = false\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'user_roles' })\n@Index({ name: 'user_roles_user_id_idx', properties: ['user'] })\n@Index({ name: 'user_roles_role_id_idx', properties: ['role'] })\nexport class UserRole {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n @ManyToOne(() => Role)\n role!: Role\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'sessions' })\nexport class Session {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n @Property({ type: 'text', unique: true })\n token!: string\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'last_used_at', type: Date, nullable: true })\n lastUsedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'password_resets' })\nexport class PasswordReset {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n @Property({ type: 'text', unique: true })\n token!: string\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'used_at', type: Date, nullable: true })\n usedAt?: Date\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// RBAC: Role-level ACL\n@Entity({ tableName: 'role_acls' })\nexport class RoleAcl {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => Role)\n role!: Role\n\n // Tenant scope is mandatory for ACL evaluation\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n // Feature list (string-based). Use JSON array to preserve order and allow wildcards like \"example.*\".\n @Property({ name: 'features_json', type: 'json', nullable: true })\n featuresJson?: string[] | null\n\n // If true, user with this role can do everything regardless of features\n @Property({ name: 'is_super_admin', type: 'boolean', default: false })\n isSuperAdmin: boolean = false\n\n // Visible organizations within the tenant; null/empty means all organizations\n @Property({ name: 'organizations_json', type: 'json', nullable: true })\n organizationsJson?: string[] | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// RBAC: Per-user ACL override\n@Entity({ tableName: 'user_acls' })\nexport class UserAcl {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => User)\n user!: User\n\n // Tenant scope is mandatory for ACL evaluation\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n // Feature list (string-based). Use JSON array to preserve order and allow wildcards like \"example.*\".\n @Property({ name: 'features_json', type: 'json', nullable: true })\n featuresJson?: string[] | null\n\n // If true, this user can do everything regardless of features\n @Property({ name: 'is_super_admin', type: 'boolean', default: false })\n isSuperAdmin: boolean = false\n\n // Visible organizations within the tenant; null/empty means all organizations\n @Property({ name: 'organizations_json', type: 'json', nullable: true })\n organizationsJson?: string[] | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'user_consents' })\n@Unique({ properties: ['userId', 'tenantId', 'consentType'] })\nexport class UserConsent {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'user_id', type: 'uuid' })\n userId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'consent_type', type: 'text' })\n consentType!: string\n\n @Property({ name: 'is_granted', type: 'boolean', default: false })\n isGranted: boolean = false\n\n @Property({ name: 'granted_at', type: Date, nullable: true })\n grantedAt?: Date | null\n\n @Property({ name: 'withdrawn_at', type: Date, nullable: true })\n withdrawnAt?: Date | null\n\n @Property({ type: 'text', nullable: true })\n source?: string | null\n\n @Property({ name: 'ip_address', type: 'text', nullable: true })\n ipAddress?: string | null\n\n @Property({ name: 'integrity_hash', type: 'text', nullable: true })\n integrityHash?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -9,9 +9,15 @@ import { resolveRegisteredLucideIconNode } from "@open-mercato/ui/backend/icons/
9
9
  import { profilePathPrefixes, profileSections } from "./profile-sections.js";
10
10
  import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
11
11
  import { filterGrantsByEnabledModules } from "@open-mercato/shared/security/enabledModulesRegistry";
12
- import { resolveFeatureCheckContext } from "@open-mercato/core/modules/directory/utils/organizationScope";
12
+ import {
13
+ getSelectedOrganizationFromRequest,
14
+ resolveFeatureCheckContext
15
+ } from "@open-mercato/core/modules/directory/utils/organizationScope";
16
+ import { isAllOrganizationsSelection } from "@open-mercato/core/modules/directory/constants";
17
+ import { Organization } from "@open-mercato/core/modules/directory/data/entities";
13
18
  import { CustomEntity } from "@open-mercato/core/modules/entities/data/entities";
14
19
  import { Role } from "@open-mercato/core/modules/auth/data/entities";
20
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
15
21
  import {
16
22
  applySidebarPreference,
17
23
  loadFirstRoleSidebarPreference,
@@ -276,6 +282,32 @@ async function resolveBackendChromePayload({
276
282
  translate
277
283
  )
278
284
  );
285
+ const requestOrganizationId = request ? getSelectedOrganizationFromRequest(request) : null;
286
+ const fallbackOrganizationId = selectedOrganizationId ?? requestOrganizationId ?? auth.orgId ?? null;
287
+ const brandOrganizationId = scopedOrganizationId ?? (fallbackOrganizationId && !isAllOrganizationsSelection(fallbackOrganizationId) ? fallbackOrganizationId : null);
288
+ let brand = null;
289
+ if (brandOrganizationId && scopedTenantId) {
290
+ try {
291
+ const organization = await findOneWithDecryption(
292
+ em,
293
+ Organization,
294
+ { id: brandOrganizationId, tenant: scopedTenantId, deletedAt: null },
295
+ void 0,
296
+ { tenantId: scopedTenantId, organizationId: brandOrganizationId }
297
+ );
298
+ if (organization?.logoUrl) {
299
+ brand = {
300
+ name: organization.name,
301
+ logo: {
302
+ src: organization.logoUrl,
303
+ alt: `${organization.name} logo`
304
+ }
305
+ };
306
+ }
307
+ } catch {
308
+ brand = null;
309
+ }
310
+ }
279
311
  return {
280
312
  groups: appliedGroups.map(({ weight: _weight, ...group }) => group),
281
313
  settingsSections,
@@ -283,7 +315,8 @@ async function resolveBackendChromePayload({
283
315
  profileSections: await serializeSectionGroups(profileSections),
284
316
  profilePathPrefixes,
285
317
  grantedFeatures,
286
- roles: Array.isArray(auth.roles) ? auth.roles : []
318
+ roles: Array.isArray(auth.roles) ? auth.roles : [],
319
+ brand
287
320
  };
288
321
  }
289
322
  export {