@open-mercato/core 0.4.2-canary-3b5064ce72 → 0.4.2-canary-7732371765

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 (497) hide show
  1. package/dist/generated/entities.ids.generated.js +1 -5
  2. package/dist/generated/entities.ids.generated.js.map +2 -2
  3. package/dist/generated/entity-fields-registry.js +0 -2
  4. package/dist/generated/entity-fields-registry.js.map +2 -2
  5. package/dist/modules/api_docs/frontend/docs/api/page.js +2 -3
  6. package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
  7. package/dist/modules/api_keys/backend/api-keys/page.js +1 -1
  8. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  9. package/dist/modules/attachments/components/AttachmentLibrary.js +0 -4
  10. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  11. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +0 -2
  12. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  13. package/dist/modules/auth/api/admin/nav.js +3 -4
  14. package/dist/modules/auth/api/admin/nav.js.map +2 -2
  15. package/dist/modules/auth/api/login.js +6 -25
  16. package/dist/modules/auth/api/login.js.map +2 -2
  17. package/dist/modules/auth/api/reset/confirm.js +2 -25
  18. package/dist/modules/auth/api/reset/confirm.js.map +2 -2
  19. package/dist/modules/auth/api/reset.js +0 -23
  20. package/dist/modules/auth/api/reset.js.map +2 -2
  21. package/dist/modules/auth/api/sidebar/preferences/route.js +9 -14
  22. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  23. package/dist/modules/auth/api/users/route.js +2 -4
  24. package/dist/modules/auth/api/users/route.js.map +2 -2
  25. package/dist/modules/auth/backend/roles/[id]/edit/page.js +1 -4
  26. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  27. package/dist/modules/auth/backend/roles/page.js +3 -3
  28. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  29. package/dist/modules/auth/backend/users/[id]/edit/page.js +3 -18
  30. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  31. package/dist/modules/auth/backend/users/create/page.js +2 -15
  32. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  33. package/dist/modules/auth/backend/users/page.js +3 -3
  34. package/dist/modules/auth/backend/users/page.js.map +2 -2
  35. package/dist/modules/auth/cli.js +11 -25
  36. package/dist/modules/auth/cli.js.map +2 -2
  37. package/dist/modules/auth/commands/users.js +2 -59
  38. package/dist/modules/auth/commands/users.js.map +2 -2
  39. package/dist/modules/auth/data/validators.js +3 -6
  40. package/dist/modules/auth/data/validators.js.map +2 -2
  41. package/dist/modules/auth/frontend/login.js +3 -112
  42. package/dist/modules/auth/frontend/login.js.map +2 -2
  43. package/dist/modules/auth/frontend/reset/[token]/page.js +10 -20
  44. package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
  45. package/dist/modules/auth/lib/setup-app.js +8 -42
  46. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  47. package/dist/modules/auth/services/authService.js +3 -24
  48. package/dist/modules/auth/services/authService.js.map +2 -2
  49. package/dist/modules/business_rules/api/execute/route.js +1 -7
  50. package/dist/modules/business_rules/api/execute/route.js.map +2 -2
  51. package/dist/modules/business_rules/backend/rules/page.js +0 -4
  52. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  53. package/dist/modules/business_rules/backend/sets/page.js +0 -3
  54. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  55. package/dist/modules/business_rules/cli.js +1 -2
  56. package/dist/modules/business_rules/cli.js.map +2 -2
  57. package/dist/modules/business_rules/lib/rule-engine.js +3 -33
  58. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  59. package/dist/modules/catalog/components/PriceKindSettings.js +0 -2
  60. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  61. package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -2
  62. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  63. package/dist/modules/catalog/components/products/ProductsDataTable.js +0 -2
  64. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  65. package/dist/modules/configs/cli.js +0 -6
  66. package/dist/modules/configs/cli.js.map +2 -2
  67. package/dist/modules/configs/components/CachePanel.js +4 -4
  68. package/dist/modules/configs/components/CachePanel.js.map +2 -2
  69. package/dist/modules/configs/lib/system-status.js +1 -48
  70. package/dist/modules/configs/lib/system-status.js.map +2 -2
  71. package/dist/modules/configs/lib/upgrade-actions.js +0 -18
  72. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  73. package/dist/modules/currencies/backend/currencies/page.js +0 -3
  74. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  75. package/dist/modules/currencies/backend/exchange-rates/page.js +0 -2
  76. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  77. package/dist/modules/customers/backend/customers/companies/page.js +0 -3
  78. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  79. package/dist/modules/customers/backend/customers/deals/page.js +0 -3
  80. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  81. package/dist/modules/customers/backend/customers/people/page.js +0 -3
  82. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  83. package/dist/modules/customers/commands/deals.js +0 -31
  84. package/dist/modules/customers/commands/deals.js.map +2 -2
  85. package/dist/modules/customers/components/CustomerTodosTable.js +0 -1
  86. package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
  87. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js +1 -2
  88. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js.map +2 -2
  89. package/dist/modules/customers/widgets/dashboard/new-customers/widget.js +1 -2
  90. package/dist/modules/customers/widgets/dashboard/new-customers/widget.js.map +2 -2
  91. package/dist/modules/customers/widgets/dashboard/new-deals/widget.js +1 -2
  92. package/dist/modules/customers/widgets/dashboard/new-deals/widget.js.map +2 -2
  93. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js +1 -2
  94. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js.map +2 -2
  95. package/dist/modules/dashboards/cli.js +5 -44
  96. package/dist/modules/dashboards/cli.js.map +2 -2
  97. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +11 -16
  98. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +3 -3
  99. package/dist/modules/dashboards/services/widgetDataService.js +3 -139
  100. package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
  101. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js +1 -2
  102. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js.map +2 -2
  103. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js +1 -2
  104. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js.map +2 -2
  105. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js +1 -2
  106. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js.map +2 -2
  107. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js +1 -2
  108. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js.map +2 -2
  109. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +1 -2
  110. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
  111. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js +1 -2
  112. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js.map +2 -2
  113. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js +1 -2
  114. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js.map +2 -2
  115. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js +1 -2
  116. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js.map +2 -2
  117. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js +1 -2
  118. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js.map +2 -2
  119. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js +1 -2
  120. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js.map +2 -2
  121. package/dist/modules/dictionaries/components/DictionaryTable.js +0 -2
  122. package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
  123. package/dist/modules/directory/backend/directory/organizations/page.js +2 -2
  124. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  125. package/dist/modules/directory/backend/directory/tenants/page.js +2 -2
  126. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  127. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +2 -2
  128. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  129. package/dist/modules/entities/components/SystemEntitiesTable.js +1 -1
  130. package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
  131. package/dist/modules/entities/components/UserEntitiesTable.js +2 -2
  132. package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
  133. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +3 -3
  134. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  135. package/dist/modules/feature_toggles/components/OverridesTable.js +1 -1
  136. package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
  137. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +2 -2
  138. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  139. package/dist/modules/query_index/cli.js +7 -63
  140. package/dist/modules/query_index/cli.js.map +2 -2
  141. package/dist/modules/query_index/components/QueryIndexesTable.js +1 -7
  142. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  143. package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
  144. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  145. package/dist/modules/resources/backend/resources/resources/page.js +2 -2
  146. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  147. package/dist/modules/sales/backend/sales/channels/offers/page.js +0 -2
  148. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  149. package/dist/modules/sales/backend/sales/channels/page.js +0 -2
  150. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  151. package/dist/modules/sales/commands/documents.js +0 -53
  152. package/dist/modules/sales/commands/documents.js.map +2 -2
  153. package/dist/modules/sales/commands/payments.js +0 -26
  154. package/dist/modules/sales/commands/payments.js.map +2 -2
  155. package/dist/modules/sales/components/AdjustmentKindSettings.js +2 -2
  156. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  157. package/dist/modules/sales/components/PaymentMethodsSettings.js +2 -2
  158. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  159. package/dist/modules/sales/components/ShippingMethodsSettings.js +2 -2
  160. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  161. package/dist/modules/sales/components/TaxRatesSettings.js +2 -2
  162. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  163. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +0 -2
  164. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  165. package/dist/modules/sales/components/documents/AdjustmentsSection.js +0 -2
  166. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  167. package/dist/modules/sales/components/documents/PaymentsSection.js +1 -2
  168. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  169. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +0 -2
  170. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  171. package/dist/modules/staff/backend/staff/team-members/page.js +1 -1
  172. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  173. package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
  174. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  175. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +2 -2
  176. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  177. package/dist/modules/staff/backend/staff/teams/page.js +2 -2
  178. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  179. package/dist/modules/staff/commands/leave-requests.js +0 -79
  180. package/dist/modules/staff/commands/leave-requests.js.map +2 -2
  181. package/dist/modules/workflows/backend/definitions/page.js +0 -5
  182. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  183. package/dist/modules/workflows/backend/instances/page.js +0 -3
  184. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  185. package/dist/modules/workflows/backend/tasks/page.js +0 -3
  186. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  187. package/dist/modules/workflows/cli.js +12 -12
  188. package/dist/modules/workflows/cli.js.map +2 -2
  189. package/dist/modules/workflows/lib/transition-handler.js +6 -14
  190. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  191. package/generated/entities.ids.generated.ts +1 -5
  192. package/generated/entity-fields-registry.ts +0 -2
  193. package/package.json +2 -2
  194. package/src/modules/api_docs/frontend/docs/api/page.tsx +2 -3
  195. package/src/modules/api_keys/backend/api-keys/page.tsx +1 -1
  196. package/src/modules/attachments/components/AttachmentLibrary.tsx +0 -4
  197. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +0 -2
  198. package/src/modules/auth/README.md +1 -1
  199. package/src/modules/auth/__tests__/cli-setup-acl.test.ts +1 -1
  200. package/src/modules/auth/api/__tests__/login.test.ts +0 -2
  201. package/src/modules/auth/api/admin/nav.ts +6 -10
  202. package/src/modules/auth/api/login.ts +7 -26
  203. package/src/modules/auth/api/reset/confirm.ts +2 -25
  204. package/src/modules/auth/api/reset.ts +0 -23
  205. package/src/modules/auth/api/sidebar/preferences/route.ts +12 -21
  206. package/src/modules/auth/api/users/route.ts +2 -5
  207. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +1 -4
  208. package/src/modules/auth/backend/roles/page.tsx +3 -3
  209. package/src/modules/auth/backend/users/[id]/edit/page.tsx +3 -22
  210. package/src/modules/auth/backend/users/create/page.tsx +2 -19
  211. package/src/modules/auth/backend/users/page.tsx +3 -3
  212. package/src/modules/auth/cli.ts +11 -38
  213. package/src/modules/auth/commands/users.ts +2 -73
  214. package/src/modules/auth/data/validators.ts +2 -6
  215. package/src/modules/auth/frontend/login.tsx +5 -134
  216. package/src/modules/auth/frontend/reset/[token]/page.tsx +11 -24
  217. package/src/modules/auth/i18n/de.json +1 -48
  218. package/src/modules/auth/i18n/en.json +1 -48
  219. package/src/modules/auth/i18n/es.json +1 -48
  220. package/src/modules/auth/i18n/pl.json +1 -48
  221. package/src/modules/auth/lib/setup-app.ts +9 -58
  222. package/src/modules/auth/services/authService.ts +4 -27
  223. package/src/modules/business_rules/api/execute/route.ts +1 -8
  224. package/src/modules/business_rules/backend/rules/page.tsx +0 -4
  225. package/src/modules/business_rules/backend/sets/page.tsx +0 -3
  226. package/src/modules/business_rules/cli.ts +1 -2
  227. package/src/modules/business_rules/i18n/en.json +1 -3
  228. package/src/modules/business_rules/lib/__tests__/rule-engine.test.ts +0 -51
  229. package/src/modules/business_rules/lib/rule-engine.ts +3 -57
  230. package/src/modules/catalog/components/PriceKindSettings.tsx +0 -2
  231. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -2
  232. package/src/modules/catalog/components/products/ProductsDataTable.tsx +0 -2
  233. package/src/modules/catalog/i18n/en.json +1 -3
  234. package/src/modules/configs/cli.ts +0 -6
  235. package/src/modules/configs/components/CachePanel.tsx +4 -4
  236. package/src/modules/configs/i18n/en.json +2 -12
  237. package/src/modules/configs/i18n/pl.json +2 -12
  238. package/src/modules/configs/lib/system-status.ts +1 -48
  239. package/src/modules/configs/lib/system-status.types.ts +0 -1
  240. package/src/modules/configs/lib/upgrade-actions.ts +0 -18
  241. package/src/modules/currencies/backend/currencies/page.tsx +0 -3
  242. package/src/modules/currencies/backend/exchange-rates/page.tsx +0 -2
  243. package/src/modules/customers/backend/customers/companies/page.tsx +0 -3
  244. package/src/modules/customers/backend/customers/deals/page.tsx +0 -3
  245. package/src/modules/customers/backend/customers/people/page.tsx +0 -3
  246. package/src/modules/customers/commands/deals.ts +0 -39
  247. package/src/modules/customers/components/CustomerTodosTable.tsx +0 -1
  248. package/src/modules/customers/i18n/en.json +1 -5
  249. package/src/modules/customers/widgets/dashboard/customer-todos/widget.ts +2 -2
  250. package/src/modules/customers/widgets/dashboard/new-customers/widget.ts +2 -2
  251. package/src/modules/customers/widgets/dashboard/new-deals/widget.ts +2 -2
  252. package/src/modules/customers/widgets/dashboard/next-interactions/widget.ts +2 -2
  253. package/src/modules/dashboards/cli.ts +5 -55
  254. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +11 -22
  255. package/src/modules/dashboards/services/widgetDataService.ts +4 -164
  256. package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.ts +2 -2
  257. package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.ts +2 -2
  258. package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.ts +2 -2
  259. package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.ts +2 -2
  260. package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
  261. package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.ts +2 -2
  262. package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.ts +2 -2
  263. package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.ts +2 -2
  264. package/src/modules/dashboards/widgets/dashboard/top-customers/widget.ts +2 -2
  265. package/src/modules/dashboards/widgets/dashboard/top-products/widget.ts +2 -2
  266. package/src/modules/dictionaries/components/DictionaryTable.tsx +0 -2
  267. package/src/modules/directory/backend/directory/organizations/page.tsx +2 -2
  268. package/src/modules/directory/backend/directory/tenants/page.tsx +2 -2
  269. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +2 -2
  270. package/src/modules/entities/components/SystemEntitiesTable.tsx +1 -1
  271. package/src/modules/entities/components/UserEntitiesTable.tsx +2 -2
  272. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +4 -3
  273. package/src/modules/feature_toggles/components/OverridesTable.tsx +1 -1
  274. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -2
  275. package/src/modules/query_index/cli.ts +13 -82
  276. package/src/modules/query_index/components/QueryIndexesTable.tsx +2 -8
  277. package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -2
  278. package/src/modules/resources/backend/resources/resources/page.tsx +2 -2
  279. package/src/modules/sales/backend/sales/channels/offers/page.tsx +0 -2
  280. package/src/modules/sales/backend/sales/channels/page.tsx +0 -2
  281. package/src/modules/sales/commands/documents.ts +0 -65
  282. package/src/modules/sales/commands/payments.ts +0 -33
  283. package/src/modules/sales/components/AdjustmentKindSettings.tsx +2 -2
  284. package/src/modules/sales/components/PaymentMethodsSettings.tsx +2 -2
  285. package/src/modules/sales/components/ShippingMethodsSettings.tsx +2 -2
  286. package/src/modules/sales/components/TaxRatesSettings.tsx +2 -2
  287. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +0 -2
  288. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +0 -2
  289. package/src/modules/sales/components/documents/PaymentsSection.tsx +1 -2
  290. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +0 -2
  291. package/src/modules/sales/i18n/de.json +0 -20
  292. package/src/modules/sales/i18n/en.json +1 -25
  293. package/src/modules/sales/i18n/es.json +0 -20
  294. package/src/modules/sales/i18n/pl.json +0 -20
  295. package/src/modules/staff/backend/staff/team-members/page.tsx +1 -1
  296. package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
  297. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +2 -2
  298. package/src/modules/staff/backend/staff/teams/page.tsx +2 -2
  299. package/src/modules/staff/commands/leave-requests.ts +0 -94
  300. package/src/modules/staff/i18n/de.json +0 -4
  301. package/src/modules/staff/i18n/en.json +1 -9
  302. package/src/modules/staff/i18n/es.json +0 -4
  303. package/src/modules/staff/i18n/pl.json +0 -4
  304. package/src/modules/workflows/backend/definitions/page.tsx +0 -5
  305. package/src/modules/workflows/backend/instances/page.tsx +1 -4
  306. package/src/modules/workflows/backend/tasks/page.tsx +1 -4
  307. package/src/modules/workflows/cli.ts +12 -12
  308. package/src/modules/workflows/i18n/en.json +1 -3
  309. package/src/modules/workflows/lib/transition-handler.ts +6 -18
  310. package/dist/generated/entities/notification/index.js +0 -57
  311. package/dist/generated/entities/notification/index.js.map +0 -7
  312. package/dist/modules/auth/api/profile/route.js +0 -157
  313. package/dist/modules/auth/api/profile/route.js.map +0 -7
  314. package/dist/modules/auth/backend/auth/profile/page.js +0 -141
  315. package/dist/modules/auth/backend/auth/profile/page.js.map +0 -7
  316. package/dist/modules/auth/backend/auth/profile/page.meta.js +0 -13
  317. package/dist/modules/auth/backend/auth/profile/page.meta.js.map +0 -7
  318. package/dist/modules/auth/notifications.js +0 -112
  319. package/dist/modules/auth/notifications.js.map +0 -7
  320. package/dist/modules/business_rules/notifications.js +0 -28
  321. package/dist/modules/business_rules/notifications.js.map +0 -7
  322. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +0 -37
  323. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +0 -7
  324. package/dist/modules/catalog/notifications.js +0 -28
  325. package/dist/modules/catalog/notifications.js.map +0 -7
  326. package/dist/modules/catalog/subscribers/low-stock-notification.js +0 -38
  327. package/dist/modules/catalog/subscribers/low-stock-notification.js.map +0 -7
  328. package/dist/modules/customers/notifications.js +0 -48
  329. package/dist/modules/customers/notifications.js.map +0 -7
  330. package/dist/modules/dashboards/lib/role-widgets.js +0 -58
  331. package/dist/modules/dashboards/lib/role-widgets.js.map +0 -7
  332. package/dist/modules/directory/api/get/tenants/lookup.js +0 -70
  333. package/dist/modules/directory/api/get/tenants/lookup.js.map +0 -7
  334. package/dist/modules/notifications/acl.js +0 -11
  335. package/dist/modules/notifications/acl.js.map +0 -7
  336. package/dist/modules/notifications/api/[id]/action/route.js +0 -74
  337. package/dist/modules/notifications/api/[id]/action/route.js.map +0 -7
  338. package/dist/modules/notifications/api/[id]/dismiss/route.js +0 -15
  339. package/dist/modules/notifications/api/[id]/dismiss/route.js.map +0 -7
  340. package/dist/modules/notifications/api/[id]/read/route.js +0 -15
  341. package/dist/modules/notifications/api/[id]/read/route.js.map +0 -7
  342. package/dist/modules/notifications/api/[id]/restore/route.js +0 -53
  343. package/dist/modules/notifications/api/[id]/restore/route.js.map +0 -7
  344. package/dist/modules/notifications/api/batch/route.js +0 -17
  345. package/dist/modules/notifications/api/batch/route.js.map +0 -7
  346. package/dist/modules/notifications/api/feature/route.js +0 -17
  347. package/dist/modules/notifications/api/feature/route.js.map +0 -7
  348. package/dist/modules/notifications/api/mark-all-read/route.js +0 -35
  349. package/dist/modules/notifications/api/mark-all-read/route.js.map +0 -7
  350. package/dist/modules/notifications/api/openapi.js +0 -76
  351. package/dist/modules/notifications/api/openapi.js.map +0 -7
  352. package/dist/modules/notifications/api/role/route.js +0 -17
  353. package/dist/modules/notifications/api/role/route.js.map +0 -7
  354. package/dist/modules/notifications/api/route.js +0 -85
  355. package/dist/modules/notifications/api/route.js.map +0 -7
  356. package/dist/modules/notifications/api/settings/route.js +0 -155
  357. package/dist/modules/notifications/api/settings/route.js.map +0 -7
  358. package/dist/modules/notifications/api/unread-count/route.js +0 -38
  359. package/dist/modules/notifications/api/unread-count/route.js.map +0 -7
  360. package/dist/modules/notifications/backend/config/notifications/page.js +0 -10
  361. package/dist/modules/notifications/backend/config/notifications/page.js.map +0 -7
  362. package/dist/modules/notifications/backend/config/notifications/page.meta.js +0 -24
  363. package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +0 -7
  364. package/dist/modules/notifications/cli.js +0 -16
  365. package/dist/modules/notifications/cli.js.map +0 -7
  366. package/dist/modules/notifications/data/entities.js +0 -112
  367. package/dist/modules/notifications/data/entities.js.map +0 -7
  368. package/dist/modules/notifications/data/validators.js +0 -98
  369. package/dist/modules/notifications/data/validators.js.map +0 -7
  370. package/dist/modules/notifications/di.js +0 -13
  371. package/dist/modules/notifications/di.js.map +0 -7
  372. package/dist/modules/notifications/emails/NotificationEmail.js +0 -58
  373. package/dist/modules/notifications/emails/NotificationEmail.js.map +0 -7
  374. package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +0 -44
  375. package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +0 -7
  376. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +0 -220
  377. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +0 -7
  378. package/dist/modules/notifications/index.js +0 -14
  379. package/dist/modules/notifications/index.js.map +0 -7
  380. package/dist/modules/notifications/lib/deliveryConfig.js +0 -107
  381. package/dist/modules/notifications/lib/deliveryConfig.js.map +0 -7
  382. package/dist/modules/notifications/lib/deliveryStrategies.js +0 -14
  383. package/dist/modules/notifications/lib/deliveryStrategies.js.map +0 -7
  384. package/dist/modules/notifications/lib/events.js +0 -12
  385. package/dist/modules/notifications/lib/events.js.map +0 -7
  386. package/dist/modules/notifications/lib/notificationBuilder.js +0 -66
  387. package/dist/modules/notifications/lib/notificationBuilder.js.map +0 -7
  388. package/dist/modules/notifications/lib/notificationFactory.js +0 -54
  389. package/dist/modules/notifications/lib/notificationFactory.js.map +0 -7
  390. package/dist/modules/notifications/lib/notificationMapper.js +0 -34
  391. package/dist/modules/notifications/lib/notificationMapper.js.map +0 -7
  392. package/dist/modules/notifications/lib/notificationRecipients.js +0 -35
  393. package/dist/modules/notifications/lib/notificationRecipients.js.map +0 -7
  394. package/dist/modules/notifications/lib/notificationService.js +0 -279
  395. package/dist/modules/notifications/lib/notificationService.js.map +0 -7
  396. package/dist/modules/notifications/lib/routeHelpers.js +0 -101
  397. package/dist/modules/notifications/lib/routeHelpers.js.map +0 -7
  398. package/dist/modules/notifications/lib/safeHref.js +0 -24
  399. package/dist/modules/notifications/lib/safeHref.js.map +0 -7
  400. package/dist/modules/notifications/migrations/Migration20260123000001.js +0 -70
  401. package/dist/modules/notifications/migrations/Migration20260123000001.js.map +0 -7
  402. package/dist/modules/notifications/migrations/Migration20260126150000.js +0 -37
  403. package/dist/modules/notifications/migrations/Migration20260126150000.js.map +0 -7
  404. package/dist/modules/notifications/migrations/Migration20260129082610.js +0 -13
  405. package/dist/modules/notifications/migrations/Migration20260129082610.js.map +0 -7
  406. package/dist/modules/notifications/subscribers/deliver-notification.js +0 -165
  407. package/dist/modules/notifications/subscribers/deliver-notification.js.map +0 -7
  408. package/dist/modules/notifications/workers/create-notification.worker.js +0 -70
  409. package/dist/modules/notifications/workers/create-notification.worker.js.map +0 -7
  410. package/dist/modules/sales/notifications.client.js +0 -51
  411. package/dist/modules/sales/notifications.client.js.map +0 -7
  412. package/dist/modules/sales/notifications.js +0 -88
  413. package/dist/modules/sales/notifications.js.map +0 -7
  414. package/dist/modules/sales/subscribers/quote-expiring-notification.js +0 -38
  415. package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +0 -7
  416. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +0 -137
  417. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +0 -7
  418. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +0 -137
  419. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +0 -7
  420. package/dist/modules/sales/widgets/notifications/index.js +0 -7
  421. package/dist/modules/sales/widgets/notifications/index.js.map +0 -7
  422. package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +0 -60
  423. package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +0 -7
  424. package/dist/modules/staff/notifications.js +0 -75
  425. package/dist/modules/staff/notifications.js.map +0 -7
  426. package/dist/modules/workflows/notifications.js +0 -28
  427. package/dist/modules/workflows/notifications.js.map +0 -7
  428. package/dist/modules/workflows/subscribers/task-assigned-notification.js +0 -38
  429. package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +0 -7
  430. package/generated/entities/notification/index.ts +0 -27
  431. package/src/modules/auth/api/profile/route.ts +0 -163
  432. package/src/modules/auth/backend/auth/profile/page.meta.ts +0 -9
  433. package/src/modules/auth/backend/auth/profile/page.tsx +0 -174
  434. package/src/modules/auth/notifications.ts +0 -109
  435. package/src/modules/business_rules/notifications.ts +0 -25
  436. package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +0 -50
  437. package/src/modules/catalog/notifications.ts +0 -25
  438. package/src/modules/catalog/subscribers/low-stock-notification.ts +0 -52
  439. package/src/modules/customers/notifications.ts +0 -44
  440. package/src/modules/dashboards/lib/role-widgets.ts +0 -80
  441. package/src/modules/directory/api/get/tenants/lookup.ts +0 -75
  442. package/src/modules/notifications/__tests__/deliver-notification.test.ts +0 -195
  443. package/src/modules/notifications/__tests__/deliveryStrategies.test.ts +0 -19
  444. package/src/modules/notifications/__tests__/notificationService.test.ts +0 -208
  445. package/src/modules/notifications/acl.ts +0 -7
  446. package/src/modules/notifications/api/[id]/action/route.ts +0 -75
  447. package/src/modules/notifications/api/[id]/dismiss/route.ts +0 -12
  448. package/src/modules/notifications/api/[id]/read/route.ts +0 -12
  449. package/src/modules/notifications/api/[id]/restore/route.ts +0 -53
  450. package/src/modules/notifications/api/batch/route.ts +0 -14
  451. package/src/modules/notifications/api/feature/route.ts +0 -14
  452. package/src/modules/notifications/api/mark-all-read/route.ts +0 -34
  453. package/src/modules/notifications/api/openapi.ts +0 -76
  454. package/src/modules/notifications/api/role/route.ts +0 -14
  455. package/src/modules/notifications/api/route.ts +0 -92
  456. package/src/modules/notifications/api/settings/route.ts +0 -157
  457. package/src/modules/notifications/api/unread-count/route.ts +0 -38
  458. package/src/modules/notifications/backend/config/notifications/page.meta.ts +0 -22
  459. package/src/modules/notifications/backend/config/notifications/page.tsx +0 -12
  460. package/src/modules/notifications/cli.ts +0 -18
  461. package/src/modules/notifications/data/entities.ts +0 -99
  462. package/src/modules/notifications/data/validators.ts +0 -115
  463. package/src/modules/notifications/di.ts +0 -11
  464. package/src/modules/notifications/emails/NotificationEmail.tsx +0 -98
  465. package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +0 -42
  466. package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +0 -233
  467. package/src/modules/notifications/i18n/de.json +0 -50
  468. package/src/modules/notifications/i18n/en.json +0 -50
  469. package/src/modules/notifications/i18n/es.json +0 -50
  470. package/src/modules/notifications/i18n/pl.json +0 -50
  471. package/src/modules/notifications/index.ts +0 -12
  472. package/src/modules/notifications/lib/deliveryConfig.ts +0 -153
  473. package/src/modules/notifications/lib/deliveryStrategies.ts +0 -50
  474. package/src/modules/notifications/lib/events.ts +0 -48
  475. package/src/modules/notifications/lib/notificationBuilder.ts +0 -121
  476. package/src/modules/notifications/lib/notificationFactory.ts +0 -76
  477. package/src/modules/notifications/lib/notificationMapper.ts +0 -33
  478. package/src/modules/notifications/lib/notificationRecipients.ts +0 -83
  479. package/src/modules/notifications/lib/notificationService.ts +0 -414
  480. package/src/modules/notifications/lib/routeHelpers.ts +0 -151
  481. package/src/modules/notifications/lib/safeHref.ts +0 -29
  482. package/src/modules/notifications/migrations/.snapshot-open-mercato.json +0 -336
  483. package/src/modules/notifications/migrations/Migration20260123000001.ts +0 -73
  484. package/src/modules/notifications/migrations/Migration20260126150000.ts +0 -39
  485. package/src/modules/notifications/migrations/Migration20260129082610.ts +0 -13
  486. package/src/modules/notifications/subscribers/deliver-notification.ts +0 -204
  487. package/src/modules/notifications/workers/create-notification.worker.ts +0 -122
  488. package/src/modules/sales/notifications.client.ts +0 -65
  489. package/src/modules/sales/notifications.ts +0 -82
  490. package/src/modules/sales/subscribers/quote-expiring-notification.ts +0 -53
  491. package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +0 -156
  492. package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +0 -156
  493. package/src/modules/sales/widgets/notifications/index.ts +0 -2
  494. package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +0 -81
  495. package/src/modules/staff/notifications.ts +0 -71
  496. package/src/modules/workflows/notifications.ts +0 -25
  497. package/src/modules/workflows/subscribers/task-assigned-notification.ts +0 -53
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/auth/frontend/login.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport { useCallback, useEffect, useState } from 'react'\nimport Image from 'next/image'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Card, CardContent, CardHeader, CardDescription } from '@open-mercato/ui/primitives/card'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { clearAllOperations } from '@open-mercato/ui/backend/operations/store'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { X } from 'lucide-react'\n\nconst loginTenantKey = 'om_login_tenant'\nconst loginTenantCookieMaxAge = 60 * 60 * 24 * 14\n\nfunction readTenantCookie() {\n if (typeof document === 'undefined') return null\n const entries = document.cookie.split(';')\n for (const entry of entries) {\n const [name, ...rest] = entry.trim().split('=')\n if (name === loginTenantKey) return decodeURIComponent(rest.join('='))\n }\n return null\n}\n\nfunction setTenantCookie(value: string) {\n if (typeof document === 'undefined') return\n document.cookie = `${loginTenantKey}=${encodeURIComponent(value)}; path=/; max-age=${loginTenantCookieMaxAge}; samesite=lax`\n}\n\nfunction clearTenantCookie() {\n if (typeof document === 'undefined') return\n document.cookie = `${loginTenantKey}=; path=/; max-age=0; samesite=lax`\n}\n\nfunction extractErrorMessage(payload: unknown): string | null {\n if (!payload) return null\n if (typeof payload === 'string') return payload\n if (Array.isArray(payload)) {\n for (const entry of payload) {\n const resolved = extractErrorMessage(entry)\n if (resolved) return resolved\n }\n return null\n }\n if (typeof payload === 'object') {\n const record = payload as Record<string, unknown>\n const candidates: unknown[] = [\n record.error,\n record.message,\n record.detail,\n record.details,\n record.description,\n ]\n for (const candidate of candidates) {\n const resolved = extractErrorMessage(candidate)\n if (resolved) return resolved\n }\n }\n return null\n}\n\nfunction looksLikeJsonString(value: string): boolean {\n const trimmed = value.trim()\n return trimmed.startsWith('{') || trimmed.startsWith('[')\n}\n\nexport default function LoginPage() {\n const t = useT()\n const translate = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>) =>\n translateWithFallback(t, key, fallback, params),\n [t],\n )\n const router = useRouter()\n const searchParams = useSearchParams()\n const requireRole = (searchParams.get('requireRole') || searchParams.get('role') || '').trim()\n const requireFeature = (searchParams.get('requireFeature') || '').trim()\n const requiredRoles = requireRole ? requireRole.split(',').map((value) => value.trim()).filter(Boolean) : []\n const requiredFeatures = requireFeature ? requireFeature.split(',').map((value) => value.trim()).filter(Boolean) : []\n const translatedRoles = requiredRoles.map((role) => translate(`auth.roles.${role}`, role))\n const translatedFeatures = requiredFeatures.map((feature) => translate(`features.${feature}`, feature))\n const [error, setError] = useState<string | null>(null)\n const [submitting, setSubmitting] = useState(false)\n const [tenantId, setTenantId] = useState<string | null>(null)\n const [tenantName, setTenantName] = useState<string | null>(null)\n const [tenantLoading, setTenantLoading] = useState(false)\n const [tenantInvalid, setTenantInvalid] = useState<string | null>(null)\n const showTenantInvalid = tenantId != null && tenantInvalid === tenantId\n\n useEffect(() => {\n const tenantParam = (searchParams.get('tenant') || '').trim()\n if (tenantParam) {\n setTenantId(tenantParam)\n window.localStorage.setItem(loginTenantKey, tenantParam)\n setTenantCookie(tenantParam)\n return\n }\n const storedTenant = window.localStorage.getItem(loginTenantKey) || readTenantCookie()\n if (storedTenant) {\n setTenantId(storedTenant)\n }\n }, [searchParams])\n\n useEffect(() => {\n if (!tenantId) {\n setTenantName(null)\n setTenantInvalid(null)\n return\n }\n if (tenantInvalid === tenantId) {\n setTenantName(null)\n setTenantLoading(false)\n return\n }\n let active = true\n setTenantLoading(true)\n setTenantInvalid(null)\n apiCall<{ ok: boolean; tenant?: { id: string; name: string }; error?: string }>(\n `/api/directory/tenants/lookup?tenantId=${encodeURIComponent(tenantId)}`,\n )\n .then(({ result }) => {\n if (!active) return\n if (result?.ok && result.tenant) {\n setTenantName(result.tenant.name)\n return\n }\n const message = translate('auth.login.errors.tenantInvalid', 'Tenant not found. Clear the tenant selection and try again.')\n setTenantName(null)\n setTenantInvalid(tenantId)\n setError(null)\n })\n .catch(() => {\n if (!active) return\n setTenantName(null)\n setTenantInvalid(tenantId)\n setError(null)\n })\n .finally(() => {\n if (active) setTenantLoading(false)\n })\n return () => {\n active = false\n }\n }, [tenantId, translate])\n\n function handleClearTenant() {\n window.localStorage.removeItem(loginTenantKey)\n clearTenantCookie()\n setTenantId(null)\n setTenantName(null)\n setTenantInvalid(null)\n const params = new URLSearchParams(searchParams)\n params.delete('tenant')\n setError(null)\n const query = params.toString()\n router.replace(query ? `/login?${query}` : '/login')\n }\n\n async function onSubmit(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault()\n setError(null)\n setSubmitting(true)\n try {\n const form = new FormData(e.currentTarget)\n if (requiredRoles.length) form.set('requireRole', requiredRoles.join(','))\n const res = await fetch('/api/auth/login', { method: 'POST', body: form })\n if (res.redirected) {\n clearAllOperations()\n // NextResponse.redirect from API\n router.replace(res.url)\n return\n }\n if (!res.ok) {\n const fallback = (() => {\n if (res.status === 403) {\n return translate(\n 'auth.login.errors.permissionDenied',\n 'You do not have permission to access this area. Please contact your administrator.',\n )\n }\n if (res.status === 401 || res.status === 400) {\n return translate('auth.login.errors.invalidCredentials', 'Invalid email or password')\n }\n return translate('auth.login.errors.generic', 'An error occurred. Please try again.')\n })()\n const cloned = res.clone()\n let errorMessage = ''\n const contentType = res.headers.get('content-type') || ''\n if (contentType.includes('application/json')) {\n try {\n const data = await res.json()\n errorMessage = extractErrorMessage(data) || ''\n } catch {\n try {\n const text = await cloned.text()\n const trimmed = text.trim()\n if (trimmed && !looksLikeJsonString(trimmed)) {\n errorMessage = trimmed\n }\n } catch {\n errorMessage = ''\n }\n }\n } else {\n try {\n const text = await res.text()\n const trimmed = text.trim()\n if (trimmed && !looksLikeJsonString(trimmed)) {\n errorMessage = trimmed\n }\n } catch {\n errorMessage = ''\n }\n }\n setError(errorMessage || fallback)\n return\n }\n // In case API returns 200 with JSON\n const data = await res.json().catch(() => null)\n clearAllOperations()\n if (data && data.redirect) {\n router.replace(data.redirect)\n }\n } catch (err: unknown) {\n // Handle any errors thrown (e.g., network errors or thrown exceptions)\n const message = err instanceof Error ? err.message : ''\n setError(message || translate('auth.login.errors.generic', 'An error occurred. Please try again.'))\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <div className=\"min-h-svh flex items-center justify-center p-4\">\n <Card className=\"w-full max-w-sm\">\n <CardHeader className=\"flex flex-col items-center gap-4 text-center p-10\">\n <Image alt={translate('auth.login.logoAlt', 'Open Mercato logo')} src=\"/open-mercato.svg\" width={150} height={150} priority />\n <h1 className=\"text-2xl font-semibold\">{translate('auth.login.brandName', 'Open Mercato')}</h1>\n <CardDescription>{translate('auth.login.subtitle', 'Access your workspace')}</CardDescription>\n </CardHeader>\n <CardContent>\n <form className=\"grid gap-3\" onSubmit={onSubmit} noValidate>\n {tenantId ? (\n <input type=\"hidden\" name=\"tenantId\" value={tenantId} />\n ) : null}\n {!!translatedRoles.length && (\n <div className=\"rounded-md border border-blue-200 bg-blue-50 px-3 py-2 text-center text-xs text-blue-900\">\n {translate(\n translatedRoles.length > 1 ? 'auth.login.requireRolesMessage' : 'auth.login.requireRoleMessage',\n translatedRoles.length > 1\n ? 'Access requires one of the following roles: {roles}'\n : 'Access requires role: {roles}',\n { roles: translatedRoles.join(', ') },\n )}\n </div>\n )}\n {!!translatedFeatures.length && (\n <div className=\"rounded-md border border-blue-200 bg-blue-50 px-3 py-2 text-center text-xs text-blue-900\">\n {translate('auth.login.featureDenied', \"You don't have access to this feature ({feature}). Please contact your administrator.\", {\n feature: translatedFeatures.join(', '),\n })}\n </div>\n )}\n {showTenantInvalid ? (\n <div className=\"rounded-md border border-red-200 bg-red-50 px-3 py-2 text-center text-xs text-red-700\">\n <div className=\"font-medium\">{translate('auth.login.errors.tenantInvalid', 'Tenant not found. Clear the tenant selection and try again.')}</div>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"mt-2 border-red-300 text-red-700\" onClick={handleClearTenant}>\n <X className=\"mr-2 size-4\" aria-hidden=\"true\" />\n {translate('auth.login.tenantClear', 'Clear')}\n </Button>\n </div>\n ) : tenantId ? (\n <div className=\"rounded-md border border-emerald-200 bg-emerald-50 px-3 py-2 text-center text-xs text-emerald-900\">\n <div className=\"font-medium\">\n {tenantLoading\n ? translate('auth.login.tenantLoading', 'Loading tenant details...')\n : translate('auth.login.tenantBanner', \"You're logging in to {tenant} tenant.\", {\n tenant: tenantName || tenantId,\n })}\n </div>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"mt-2 border-emerald-300 text-emerald-900\" onClick={handleClearTenant}>\n <X className=\"mr-2 size-4\" aria-hidden=\"true\" />\n {translate('auth.login.tenantClear', 'Clear')}\n </Button>\n </div>\n ) : null}\n {error && !showTenantInvalid && (\n <div className=\"rounded-md border border-red-200 bg-red-50 px-3 py-2 text-center text-sm text-red-700\" role=\"alert\" aria-live=\"polite\">\n {error}\n </div>\n )}\n <div className=\"grid gap-1\">\n <Label htmlFor=\"email\">{t('auth.email')}</Label>\n <Input id=\"email\" name=\"email\" type=\"email\" required aria-invalid={!!error} />\n </div>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"password\">{t('auth.password')}</Label>\n <Input id=\"password\" name=\"password\" type=\"password\" required aria-invalid={!!error} />\n </div>\n <label className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <input type=\"checkbox\" name=\"remember\" className=\"accent-foreground\" />\n <span>{translate('auth.login.rememberMe', 'Remember me')}</span>\n </label>\n <button disabled={submitting} className=\"h-10 rounded-md bg-foreground text-background mt-2 hover:opacity-90 transition disabled:opacity-60\">\n {submitting ? translate('auth.login.loading', 'Loading...') : translate('auth.signIn', 'Sign in')}\n </button>\n <div className=\"text-xs text-muted-foreground mt-2\">\n <Link className=\"underline\" href=\"/reset\">\n {translate('auth.login.forgotPassword', 'Forgot password?')}\n </Link>\n </div>\n </form>\n </CardContent>\n </Card>\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\nimport { useState } from 'react'\nimport Image from 'next/image'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@open-mercato/ui/primitives/card'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { clearAllOperations } from '@open-mercato/ui/backend/operations/store'\n\nfunction extractErrorMessage(payload: unknown): string | null {\n if (!payload) return null\n if (typeof payload === 'string') return payload\n if (Array.isArray(payload)) {\n for (const entry of payload) {\n const resolved = extractErrorMessage(entry)\n if (resolved) return resolved\n }\n return null\n }\n if (typeof payload === 'object') {\n const record = payload as Record<string, unknown>\n const candidates: unknown[] = [\n record.error,\n record.message,\n record.detail,\n record.details,\n record.description,\n ]\n for (const candidate of candidates) {\n const resolved = extractErrorMessage(candidate)\n if (resolved) return resolved\n }\n }\n return null\n}\n\nfunction looksLikeJsonString(value: string): boolean {\n const trimmed = value.trim()\n return trimmed.startsWith('{') || trimmed.startsWith('[')\n}\n\nexport default function LoginPage() {\n const t = useT()\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n translateWithFallback(t, key, fallback, params)\n const router = useRouter()\n const searchParams = useSearchParams()\n const requireRole = (searchParams.get('requireRole') || searchParams.get('role') || '').trim()\n const requireFeature = (searchParams.get('requireFeature') || '').trim()\n const requiredRoles = requireRole ? requireRole.split(',').map((value) => value.trim()).filter(Boolean) : []\n const requiredFeatures = requireFeature ? requireFeature.split(',').map((value) => value.trim()).filter(Boolean) : []\n const translatedRoles = requiredRoles.map((role) => translate(`auth.roles.${role}`, role))\n const translatedFeatures = requiredFeatures.map((feature) => translate(`features.${feature}`, feature))\n const [error, setError] = useState<string | null>(null)\n const [submitting, setSubmitting] = useState(false)\n\n async function onSubmit(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault()\n setError(null)\n setSubmitting(true)\n try {\n const form = new FormData(e.currentTarget)\n if (requiredRoles.length) form.set('requireRole', requiredRoles.join(','))\n const res = await fetch('/api/auth/login', { method: 'POST', body: form })\n if (res.redirected) {\n clearAllOperations()\n // NextResponse.redirect from API\n router.replace(res.url)\n return\n }\n if (!res.ok) {\n const fallback = (() => {\n if (res.status === 403) {\n return translate(\n 'auth.login.errors.permissionDenied',\n 'You do not have permission to access this area. Please contact your administrator.',\n )\n }\n if (res.status === 401 || res.status === 400) {\n return translate('auth.login.errors.invalidCredentials', 'Invalid email or password')\n }\n return translate('auth.login.errors.generic', 'An error occurred. Please try again.')\n })()\n const cloned = res.clone()\n let errorMessage = ''\n const contentType = res.headers.get('content-type') || ''\n if (contentType.includes('application/json')) {\n try {\n const data = await res.json()\n errorMessage = extractErrorMessage(data) || ''\n } catch {\n try {\n const text = await cloned.text()\n const trimmed = text.trim()\n if (trimmed && !looksLikeJsonString(trimmed)) {\n errorMessage = trimmed\n }\n } catch {\n errorMessage = ''\n }\n }\n } else {\n try {\n const text = await res.text()\n const trimmed = text.trim()\n if (trimmed && !looksLikeJsonString(trimmed)) {\n errorMessage = trimmed\n }\n } catch {\n errorMessage = ''\n }\n }\n setError(errorMessage || fallback)\n return\n }\n // In case API returns 200 with JSON\n const data = await res.json().catch(() => null)\n clearAllOperations()\n if (data && data.redirect) {\n router.replace(data.redirect)\n }\n } catch (err: unknown) {\n // Handle any errors thrown (e.g., network errors or thrown exceptions)\n const message = err instanceof Error ? err.message : ''\n setError(message || translate('auth.login.errors.generic', 'An error occurred. Please try again.'))\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <div className=\"min-h-svh flex items-center justify-center p-4\">\n <Card className=\"w-full max-w-sm\">\n <CardHeader className=\"flex flex-col items-center gap-4 text-center p-10\">\n <Image alt={translate('auth.login.logoAlt', 'Open Mercato logo')} src=\"/open-mercato.svg\" width={150} height={150} priority />\n <h1 className=\"text-2xl font-semibold\">{translate('auth.login.brandName', 'Open Mercato')}</h1>\n <CardDescription>{translate('auth.login.subtitle', 'Access your workspace')}</CardDescription>\n </CardHeader>\n <CardContent>\n <form className=\"grid gap-3\" onSubmit={onSubmit} noValidate>\n {!!translatedRoles.length && (\n <div className=\"rounded-md border border-blue-200 bg-blue-50 px-3 py-2 text-center text-xs text-blue-900\">\n {translate(\n translatedRoles.length > 1 ? 'auth.login.requireRolesMessage' : 'auth.login.requireRoleMessage',\n translatedRoles.length > 1\n ? 'Access requires one of the following roles: {roles}'\n : 'Access requires role: {roles}',\n { roles: translatedRoles.join(', ') },\n )}\n </div>\n )}\n {!!translatedFeatures.length && (\n <div className=\"rounded-md border border-blue-200 bg-blue-50 px-3 py-2 text-center text-xs text-blue-900\">\n {translate('auth.login.featureDenied', \"You don't have access to this feature ({feature}). Please contact your administrator.\", {\n feature: translatedFeatures.join(', '),\n })}\n </div>\n )}\n {error && (\n <div className=\"rounded-md border border-red-200 bg-red-50 px-3 py-2 text-center text-sm text-red-700\" role=\"alert\" aria-live=\"polite\">\n {error}\n </div>\n )}\n <div className=\"grid gap-1\">\n <Label htmlFor=\"email\">{t('auth.email')}</Label>\n <Input id=\"email\" name=\"email\" type=\"email\" required aria-invalid={!!error} />\n </div>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"password\">{t('auth.password')}</Label>\n <Input id=\"password\" name=\"password\" type=\"password\" required aria-invalid={!!error} />\n </div>\n <label className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <input type=\"checkbox\" name=\"remember\" className=\"accent-foreground\" />\n <span>{translate('auth.login.rememberMe', 'Remember me')}</span>\n </label>\n <button disabled={submitting} className=\"h-10 rounded-md bg-foreground text-background mt-2 hover:opacity-90 transition disabled:opacity-60\">\n {submitting ? translate('auth.login.loading', 'Loading...') : translate('auth.signIn', 'Sign in')}\n </button>\n <div className=\"text-xs text-muted-foreground mt-2\">\n <Link className=\"underline\" href=\"/reset\">\n {translate('auth.login.forgotPassword', 'Forgot password?')}\n </Link>\n </div>\n </form>\n </CardContent>\n </Card>\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["data"]
7
7
  }
@@ -5,17 +5,10 @@ import { Input } from "@open-mercato/ui/primitives/input";
5
5
  import { Label } from "@open-mercato/ui/primitives/label";
6
6
  import { useState } from "react";
7
7
  import { useRouter } from "next/navigation";
8
- import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
9
- import { useT } from "@open-mercato/shared/lib/i18n/context";
10
- import { formatPasswordRequirements, getPasswordPolicy } from "@open-mercato/shared/lib/auth/passwordPolicy";
11
8
  function ResetWithTokenPage({ params }) {
12
9
  const router = useRouter();
13
- const t = useT();
14
10
  const [error, setError] = useState(null);
15
11
  const [submitting, setSubmitting] = useState(false);
16
- const passwordPolicy = getPasswordPolicy();
17
- const passwordRequirements = formatPasswordRequirements(passwordPolicy, t);
18
- const passwordDescription = passwordRequirements ? t("auth.password.requirements.help", "Password requirements: {requirements}", { requirements: passwordRequirements }) : "";
19
12
  async function onSubmit(e) {
20
13
  e.preventDefault();
21
14
  setError(null);
@@ -23,32 +16,29 @@ function ResetWithTokenPage({ params }) {
23
16
  try {
24
17
  const form = new FormData(e.currentTarget);
25
18
  form.set("token", params.token);
26
- const { ok, result } = await apiCall(
27
- "/api/auth/reset/confirm",
28
- { method: "POST", body: form }
29
- );
30
- if (!ok || result?.ok === false) {
31
- setError(result?.error || t("auth.reset.errors.failed", "Unable to reset password"));
19
+ const res = await fetch("/api/auth/reset/confirm", { method: "POST", body: form });
20
+ const data = await res.json().catch(() => null);
21
+ if (!res.ok) {
22
+ setError(data?.error || "Unable to reset password");
32
23
  return;
33
24
  }
34
- router.replace(result?.redirect || "/login");
25
+ router.replace(data?.redirect || "/login");
35
26
  } finally {
36
27
  setSubmitting(false);
37
28
  }
38
29
  }
39
30
  return /* @__PURE__ */ jsx("div", { className: "min-h-svh flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs(Card, { className: "w-full max-w-sm", children: [
40
31
  /* @__PURE__ */ jsxs(CardHeader, { children: [
41
- /* @__PURE__ */ jsx(CardTitle, { children: t("auth.reset.title", "Set a new password") }),
42
- /* @__PURE__ */ jsx(CardDescription, { children: t("auth.reset.subtitle", "Choose a strong password for your account.") })
32
+ /* @__PURE__ */ jsx(CardTitle, { children: "Set a new password" }),
33
+ /* @__PURE__ */ jsx(CardDescription, { children: "Choose a strong password for your account." })
43
34
  ] }),
44
35
  /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs("form", { className: "grid gap-3", onSubmit, children: [
45
36
  error && /* @__PURE__ */ jsx("div", { className: "text-sm text-red-600", children: error }),
46
37
  /* @__PURE__ */ jsxs("div", { className: "grid gap-1", children: [
47
- /* @__PURE__ */ jsx(Label, { htmlFor: "password", children: t("auth.reset.form.password", "New password") }),
48
- /* @__PURE__ */ jsx(Input, { id: "password", name: "password", type: "password", required: true, minLength: passwordPolicy.minLength }),
49
- passwordDescription ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: passwordDescription }) : null
38
+ /* @__PURE__ */ jsx(Label, { htmlFor: "password", children: "New password" }),
39
+ /* @__PURE__ */ jsx(Input, { id: "password", name: "password", type: "password", required: true, minLength: 6 })
50
40
  ] }),
51
- /* @__PURE__ */ jsx("button", { disabled: submitting, className: "h-10 rounded-md bg-foreground text-background mt-2 hover:opacity-90 transition disabled:opacity-60", children: submitting ? t("auth.reset.form.loading", "...") : t("auth.reset.form.submit", "Update password") })
41
+ /* @__PURE__ */ jsx("button", { disabled: submitting, className: "h-10 rounded-md bg-foreground text-background mt-2 hover:opacity-90 transition disabled:opacity-60", children: submitting ? "..." : "Update password" })
52
42
  ] }) })
53
43
  ] }) });
54
44
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/auth/frontend/reset/%5Btoken%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@open-mercato/ui/primitives/card'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { useState } from 'react'\nimport { useRouter } from 'next/navigation'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { formatPasswordRequirements, getPasswordPolicy } from '@open-mercato/shared/lib/auth/passwordPolicy'\n\nexport default function ResetWithTokenPage({ params }: { params: { token: string } }) {\n const router = useRouter()\n const t = useT()\n const [error, setError] = useState<string | null>(null)\n const [submitting, setSubmitting] = useState(false)\n const passwordPolicy = getPasswordPolicy()\n const passwordRequirements = formatPasswordRequirements(passwordPolicy, t)\n const passwordDescription = passwordRequirements\n ? t('auth.password.requirements.help', 'Password requirements: {requirements}', { requirements: passwordRequirements })\n : ''\n\n async function onSubmit(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault()\n setError(null)\n setSubmitting(true)\n try {\n const form = new FormData(e.currentTarget)\n form.set('token', params.token)\n const { ok, result } = await apiCall<{ ok?: boolean; error?: string; redirect?: string }>(\n '/api/auth/reset/confirm',\n { method: 'POST', body: form },\n )\n if (!ok || result?.ok === false) {\n setError(result?.error || t('auth.reset.errors.failed', 'Unable to reset password'))\n return\n }\n router.replace(result?.redirect || '/login')\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <div className=\"min-h-svh flex items-center justify-center p-4\">\n <Card className=\"w-full max-w-sm\">\n <CardHeader>\n <CardTitle>{t('auth.reset.title', 'Set a new password')}</CardTitle>\n <CardDescription>{t('auth.reset.subtitle', 'Choose a strong password for your account.')}</CardDescription>\n </CardHeader>\n <CardContent>\n <form className=\"grid gap-3\" onSubmit={onSubmit}>\n {error && <div className=\"text-sm text-red-600\">{error}</div>}\n <div className=\"grid gap-1\">\n <Label htmlFor=\"password\">{t('auth.reset.form.password', 'New password')}</Label>\n <Input id=\"password\" name=\"password\" type=\"password\" required minLength={passwordPolicy.minLength} />\n {passwordDescription ? (\n <p className=\"text-xs text-muted-foreground\">{passwordDescription}</p>\n ) : null}\n </div>\n <button disabled={submitting} className=\"h-10 rounded-md bg-foreground text-background mt-2 hover:opacity-90 transition disabled:opacity-60\">\n {submitting ? t('auth.reset.form.loading', '...') : t('auth.reset.form.submit', 'Update password')}\n </button>\n </form>\n </CardContent>\n </Card>\n </div>\n )\n}\n"],
5
- "mappings": ";AA6CQ,SACE,KADF;AA5CR,SAAS,MAAM,aAAa,YAAY,WAAW,uBAAuB;AAC1E,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,4BAA4B,yBAAyB;AAE/C,SAAR,mBAAoC,EAAE,OAAO,GAAkC;AACpF,QAAM,SAAS,UAAU;AACzB,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,iBAAiB,kBAAkB;AACzC,QAAM,uBAAuB,2BAA2B,gBAAgB,CAAC;AACzE,QAAM,sBAAsB,uBACxB,EAAE,mCAAmC,yCAAyC,EAAE,cAAc,qBAAqB,CAAC,IACpH;AAEJ,iBAAe,SAAS,GAAqC;AAC3D,MAAE,eAAe;AACjB,aAAS,IAAI;AACb,kBAAc,IAAI;AAClB,QAAI;AACF,YAAM,OAAO,IAAI,SAAS,EAAE,aAAa;AACzC,WAAK,IAAI,SAAS,OAAO,KAAK;AAC9B,YAAM,EAAE,IAAI,OAAO,IAAI,MAAM;AAAA,QAC3B;AAAA,QACA,EAAE,QAAQ,QAAQ,MAAM,KAAK;AAAA,MAC/B;AACA,UAAI,CAAC,MAAM,QAAQ,OAAO,OAAO;AAC/B,iBAAS,QAAQ,SAAS,EAAE,4BAA4B,0BAA0B,CAAC;AACnF;AAAA,MACF;AACA,aAAO,QAAQ,QAAQ,YAAY,QAAQ;AAAA,IAC7C,UAAE;AACA,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF;AAEA,SACE,oBAAC,SAAI,WAAU,kDACb,+BAAC,QAAK,WAAU,mBACd;AAAA,yBAAC,cACC;AAAA,0BAAC,aAAW,YAAE,oBAAoB,oBAAoB,GAAE;AAAA,MACxD,oBAAC,mBAAiB,YAAE,uBAAuB,4CAA4C,GAAE;AAAA,OAC3F;AAAA,IACA,oBAAC,eACC,+BAAC,UAAK,WAAU,cAAa,UAC1B;AAAA,eAAS,oBAAC,SAAI,WAAU,wBAAwB,iBAAM;AAAA,MACvD,qBAAC,SAAI,WAAU,cACb;AAAA,4BAAC,SAAM,SAAQ,YAAY,YAAE,4BAA4B,cAAc,GAAE;AAAA,QACzE,oBAAC,SAAM,IAAG,YAAW,MAAK,YAAW,MAAK,YAAW,UAAQ,MAAC,WAAW,eAAe,WAAW;AAAA,QAClG,sBACC,oBAAC,OAAE,WAAU,iCAAiC,+BAAoB,IAChE;AAAA,SACN;AAAA,MACA,oBAAC,YAAO,UAAU,YAAY,WAAU,sGACrC,uBAAa,EAAE,2BAA2B,KAAK,IAAI,EAAE,0BAA0B,iBAAiB,GACnG;AAAA,OACF,GACF;AAAA,KACF,GACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\"\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@open-mercato/ui/primitives/card'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { useState } from 'react'\nimport { useRouter } from 'next/navigation'\n\nexport default function ResetWithTokenPage({ params }: { params: { token: string } }) {\n const router = useRouter()\n const [error, setError] = useState<string | null>(null)\n const [submitting, setSubmitting] = useState(false)\n\n async function onSubmit(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault()\n setError(null)\n setSubmitting(true)\n try {\n const form = new FormData(e.currentTarget)\n form.set('token', params.token)\n const res = await fetch('/api/auth/reset/confirm', { method: 'POST', body: form })\n const data = await res.json().catch(() => null)\n if (!res.ok) {\n setError(data?.error || 'Unable to reset password')\n return\n }\n router.replace(data?.redirect || '/login')\n } finally {\n setSubmitting(false)\n }\n }\n\n return (\n <div className=\"min-h-svh flex items-center justify-center p-4\">\n <Card className=\"w-full max-w-sm\">\n <CardHeader>\n <CardTitle>Set a new password</CardTitle>\n <CardDescription>Choose a strong password for your account.</CardDescription>\n </CardHeader>\n <CardContent>\n <form className=\"grid gap-3\" onSubmit={onSubmit}>\n {error && <div className=\"text-sm text-red-600\">{error}</div>}\n <div className=\"grid gap-1\">\n <Label htmlFor=\"password\">New password</Label>\n <Input id=\"password\" name=\"password\" type=\"password\" required minLength={6} />\n </div>\n <button disabled={submitting} className=\"h-10 rounded-md bg-foreground text-background mt-2 hover:opacity-90 transition disabled:opacity-60\">\n {submitting ? '...' : 'Update password'}\n </button>\n </form>\n </CardContent>\n </Card>\n </div>\n )\n}\n\n"],
5
+ "mappings": ";AAkCQ,SACE,KADF;AAjCR,SAAS,MAAM,aAAa,YAAY,WAAW,uBAAuB;AAC1E,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAEX,SAAR,mBAAoC,EAAE,OAAO,GAAkC;AACpF,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAElD,iBAAe,SAAS,GAAqC;AAC3D,MAAE,eAAe;AACjB,aAAS,IAAI;AACb,kBAAc,IAAI;AAClB,QAAI;AACF,YAAM,OAAO,IAAI,SAAS,EAAE,aAAa;AACzC,WAAK,IAAI,SAAS,OAAO,KAAK;AAC9B,YAAM,MAAM,MAAM,MAAM,2BAA2B,EAAE,QAAQ,QAAQ,MAAM,KAAK,CAAC;AACjF,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI;AAC9C,UAAI,CAAC,IAAI,IAAI;AACX,iBAAS,MAAM,SAAS,0BAA0B;AAClD;AAAA,MACF;AACA,aAAO,QAAQ,MAAM,YAAY,QAAQ;AAAA,IAC3C,UAAE;AACA,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF;AAEA,SACE,oBAAC,SAAI,WAAU,kDACb,+BAAC,QAAK,WAAU,mBACd;AAAA,yBAAC,cACC;AAAA,0BAAC,aAAU,gCAAkB;AAAA,MAC7B,oBAAC,mBAAgB,wDAA0C;AAAA,OAC7D;AAAA,IACA,oBAAC,eACC,+BAAC,UAAK,WAAU,cAAa,UAC1B;AAAA,eAAS,oBAAC,SAAI,WAAU,wBAAwB,iBAAM;AAAA,MACvD,qBAAC,SAAI,WAAU,cACb;AAAA,4BAAC,SAAM,SAAQ,YAAW,0BAAY;AAAA,QACtC,oBAAC,SAAM,IAAG,YAAW,MAAK,YAAW,MAAK,YAAW,UAAQ,MAAC,WAAW,GAAG;AAAA,SAC9E;AAAA,MACA,oBAAC,YAAO,UAAU,YAAY,WAAU,sGACrC,uBAAa,QAAQ,mBACxB;AAAA,OACF,GACF;AAAA,KACF,GACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -15,7 +15,6 @@ import { DEFAULT_ENCRYPTION_MAPS } from "@open-mercato/core/modules/entities/lib
15
15
  import { createKmsService } from "@open-mercato/shared/lib/encryption/kms";
16
16
  import { TenantDataEncryptionService } from "@open-mercato/shared/lib/encryption/tenantDataEncryptionService";
17
17
  import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
18
- import { parseBooleanToken } from "@open-mercato/shared/lib/boolean";
19
18
  const DEFAULT_ROLE_NAMES = ["employee", "admin", "superadmin"];
20
19
  const DEMO_SUPERADMIN_EMAIL = "superadmin@acme.com";
21
20
  async function ensureRolesInContext(em, roleNames, tenantId) {
@@ -54,10 +53,6 @@ async function findRoleByNameOrFail(em, name, tenantId) {
54
53
  if (!role) throw new Error(`ROLE_NOT_FOUND:${name}`);
55
54
  return role;
56
55
  }
57
- const DERIVED_EMAIL_ENV = {
58
- admin: "OM_INIT_ADMIN_EMAIL",
59
- employee: "OM_INIT_EMPLOYEE_EMAIL"
60
- };
61
56
  async function setupInitialTenant(em, options) {
62
57
  const {
63
58
  primaryUser,
@@ -115,17 +110,12 @@ async function setupInitialTenant(em, options) {
115
110
  { email: primaryUser.email, roles: primaryRoles, name: resolvePrimaryName(primaryUser) }
116
111
  ];
117
112
  if (includeDerivedUsers) {
118
- const [, domain] = String(primaryUser.email).split("@");
119
- const adminOverride = readEnvValue(DERIVED_EMAIL_ENV.admin);
120
- const employeeOverride = readEnvValue(DERIVED_EMAIL_ENV.employee);
121
- const adminEmail = adminOverride ?? (domain ? `admin@${domain}` : "");
122
- const employeeEmail = employeeOverride ?? (domain ? `employee@${domain}` : "");
123
- const adminPassword = readEnvValue("OM_INIT_ADMIN_PASSWORD");
124
- const employeePassword = readEnvValue("OM_INIT_EMPLOYEE_PASSWORD");
125
- const adminPasswordHash = adminPassword ? await resolvePasswordHash({ email: adminEmail, password: adminPassword }) : null;
126
- const employeePasswordHash = employeePassword ? await resolvePasswordHash({ email: employeeEmail, password: employeePassword }) : null;
127
- addUniqueBaseUser(baseUsers, { email: adminEmail, roles: ["admin"], passwordHash: adminPasswordHash });
128
- addUniqueBaseUser(baseUsers, { email: employeeEmail, roles: ["employee"], passwordHash: employeePasswordHash });
113
+ const [local, domain] = String(primaryUser.email).split("@");
114
+ const isSuperadminLocal = (local || "").toLowerCase() === "superadmin" && !!domain;
115
+ if (isSuperadminLocal) {
116
+ baseUsers.push({ email: `admin@${domain}`, roles: ["admin"] });
117
+ baseUsers.push({ email: `employee@${domain}`, roles: ["employee"] });
118
+ }
129
119
  }
130
120
  const passwordHash = await resolvePasswordHash(primaryUser);
131
121
  await em.transactional(async (tem) => {
@@ -207,12 +197,11 @@ async function setupInitialTenant(em, options) {
207
197
  await encryptionService.invalidateMap("auth:user", String(tenantId), null);
208
198
  }
209
199
  for (const base of baseUsers) {
210
- const resolvedPasswordHash = base.passwordHash ?? passwordHash;
211
200
  let user = await tem.findOne(User, { email: base.email });
212
201
  const confirm = primaryUser.confirm ?? true;
213
202
  const encryptedPayload = encryptionService ? await encryptionService.encryptEntityPayload("auth:user", { email: base.email }, tenantId, organizationId) : { email: base.email, emailHash: computeEmailHash(base.email) };
214
203
  if (user) {
215
- user.passwordHash = resolvedPasswordHash;
204
+ user.passwordHash = passwordHash;
216
205
  user.organizationId = organizationId;
217
206
  user.tenantId = tenantId;
218
207
  if (isTenantDataEncryptionEnabled()) {
@@ -227,7 +216,7 @@ async function setupInitialTenant(em, options) {
227
216
  user = tem.create(User, {
228
217
  email: encryptedPayload.email ?? base.email,
229
218
  emailHash: isTenantDataEncryptionEnabled() ? encryptedPayload.emailHash ?? computeEmailHash(base.email) : void 0,
230
- passwordHash: resolvedPasswordHash,
219
+ passwordHash,
231
220
  organizationId,
232
221
  tenantId,
233
222
  name: base.name ?? void 0,
@@ -269,27 +258,6 @@ function resolvePrimaryName(input) {
269
258
  if (parts.length) return parts.join(" ");
270
259
  return null;
271
260
  }
272
- function readEnvValue(key) {
273
- const value = process.env[key];
274
- if (typeof value !== "string") return void 0;
275
- const trimmed = value.trim();
276
- return trimmed.length > 0 ? trimmed : void 0;
277
- }
278
- function addUniqueBaseUser(baseUsers, entry) {
279
- if (!entry.email) return;
280
- const normalized = entry.email.toLowerCase();
281
- if (baseUsers.some((user) => user.email.toLowerCase() === normalized)) return;
282
- baseUsers.push(entry);
283
- }
284
- function isDemoModeEnabled() {
285
- const parsed = parseBooleanToken(process.env.DEMO_MODE ?? "");
286
- return parsed === false ? false : true;
287
- }
288
- function shouldKeepDemoSuperadminDuringInit() {
289
- if (process.env.OM_INIT_FLOW !== "true") return false;
290
- if (!readEnvValue("OM_INIT_SUPERADMIN_EMAIL")) return false;
291
- return isDemoModeEnabled();
292
- }
293
261
  async function resolvePasswordHash(input) {
294
262
  if (typeof input.hashedPassword === "string") return input.hashedPassword;
295
263
  if (input.password) return hash(input.password, 10);
@@ -340,7 +308,6 @@ async function ensureDefaultRoleAcls(em, tenantId, options = {}) {
340
308
  "dashboards.admin.assign-widgets",
341
309
  "analytics.view",
342
310
  "api_keys.*",
343
- "notifications.manage",
344
311
  "perspectives.use",
345
312
  "perspectives.role_defaults",
346
313
  "business_rules.*",
@@ -419,7 +386,6 @@ async function ensureRoleAclFor(em, role, tenantId, features, options = {}) {
419
386
  }
420
387
  async function deactivateDemoSuperAdminIfSelfOnboardingEnabled(em) {
421
388
  if (process.env.SELF_SERVICE_ONBOARDING_ENABLED !== "true") return;
422
- if (shouldKeepDemoSuperadminDuringInit()) return;
423
389
  try {
424
390
  const user = await em.findOne(User, { email: DEMO_SUPERADMIN_EMAIL });
425
391
  if (!user) return;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/auth/lib/setup-app.ts"],
4
- "sourcesContent": ["import { hash } from 'bcryptjs'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { Role, RoleAcl, User, UserRole } from '@open-mercato/core/modules/auth/data/entities'\nimport { Tenant, Organization } from '@open-mercato/core/modules/directory/data/entities'\nimport { rebuildHierarchyForTenant } from '@open-mercato/core/modules/directory/lib/hierarchy'\nimport { normalizeTenantId } from './tenantAccess'\nimport { SalesSettings, SalesDocumentSequence } from '@open-mercato/core/modules/sales/data/entities'\nimport {\n DEFAULT_ORDER_NUMBER_FORMAT,\n DEFAULT_QUOTE_NUMBER_FORMAT,\n} from '@open-mercato/core/modules/sales/lib/documentNumberTokens'\nimport { computeEmailHash } from '@open-mercato/core/modules/auth/lib/emailHash'\nimport { isEncryptionDebugEnabled, isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'\nimport { EncryptionMap } from '@open-mercato/core/modules/entities/data/entities'\nimport { DEFAULT_ENCRYPTION_MAPS } from '@open-mercato/core/modules/entities/lib/encryptionDefaults'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\nconst DEFAULT_ROLE_NAMES = ['employee', 'admin', 'superadmin'] as const\nconst DEMO_SUPERADMIN_EMAIL = 'superadmin@acme.com'\n\nexport type EnsureRolesOptions = {\n roleNames?: string[]\n tenantId?: string | null\n}\n\nasync function ensureRolesInContext(\n em: EntityManager,\n roleNames: string[],\n tenantId: string | null,\n) {\n for (const name of roleNames) {\n const existing = await em.findOne(Role, { name, tenantId })\n if (existing) continue\n if (tenantId !== null) {\n const globalRole = await em.findOne(Role, { name, tenantId: null })\n if (globalRole) {\n globalRole.tenantId = tenantId\n em.persist(globalRole)\n continue\n }\n }\n em.persist(em.create(Role, { name, tenantId, createdAt: new Date() }))\n }\n}\n\nexport async function ensureRoles(em: EntityManager, options: EnsureRolesOptions = {}) {\n const roleNames = options.roleNames ?? [...DEFAULT_ROLE_NAMES]\n const tenantId = normalizeTenantId(options.tenantId ?? null) ?? null\n await em.transactional(async (tem) => {\n await ensureRolesInContext(tem, roleNames, tenantId)\n await tem.flush()\n })\n}\n\nasync function findRoleByName(\n em: EntityManager,\n name: string,\n tenantId: string | null,\n): Promise<Role | null> {\n const normalizedTenant = normalizeTenantId(tenantId ?? null) ?? null\n let role = await em.findOne(Role, { name, tenantId: normalizedTenant })\n if (!role && normalizedTenant !== null) {\n role = await em.findOne(Role, { name, tenantId: null })\n }\n return role\n}\n\nasync function findRoleByNameOrFail(\n em: EntityManager,\n name: string,\n tenantId: string | null,\n): Promise<Role> {\n const role = await findRoleByName(em, name, tenantId)\n if (!role) throw new Error(`ROLE_NOT_FOUND:${name}`)\n return role\n}\n\ntype PrimaryUserInput = {\n email: string\n password?: string\n hashedPassword?: string | null\n firstName?: string | null\n lastName?: string | null\n displayName?: string | null\n confirm?: boolean\n}\n\nconst DERIVED_EMAIL_ENV = {\n admin: 'OM_INIT_ADMIN_EMAIL',\n employee: 'OM_INIT_EMPLOYEE_EMAIL',\n} as const\n\nexport type SetupInitialTenantOptions = {\n orgName: string\n primaryUser: PrimaryUserInput\n roleNames?: string[]\n includeDerivedUsers?: boolean\n failIfUserExists?: boolean\n primaryUserRoles?: string[]\n includeSuperadminRole?: boolean\n}\n\nexport type SetupInitialTenantResult = {\n tenantId: string\n organizationId: string\n users: Array<{ user: User; roles: string[]; created: boolean }>\n reusedExistingUser: boolean\n}\n\nexport async function setupInitialTenant(\n em: EntityManager,\n options: SetupInitialTenantOptions,\n): Promise<SetupInitialTenantResult> {\n const {\n primaryUser,\n includeDerivedUsers = true,\n failIfUserExists = false,\n primaryUserRoles,\n includeSuperadminRole = true,\n } = options\n const primaryRolesInput = primaryUserRoles && primaryUserRoles.length ? primaryUserRoles : ['superadmin']\n const primaryRoles = includeSuperadminRole\n ? primaryRolesInput\n : primaryRolesInput.filter((role) => role !== 'superadmin')\n if (primaryRoles.length === 0) {\n throw new Error('PRIMARY_ROLES_REQUIRED')\n }\n const defaultRoleNames = options.roleNames ?? [...DEFAULT_ROLE_NAMES]\n const resolvedRoleNames = includeSuperadminRole\n ? defaultRoleNames\n : defaultRoleNames.filter((role) => role !== 'superadmin')\n const roleNames = Array.from(new Set([...resolvedRoleNames, ...primaryRoles]))\n\n const mainEmail = primaryUser.email\n const existingUser = await em.findOne(User, { email: mainEmail })\n if (existingUser && failIfUserExists) {\n throw new Error('USER_EXISTS')\n }\n\n let tenantId: string | undefined\n let organizationId: string | undefined\n let reusedExistingUser = false\n const userSnapshots: Array<{ user: User; roles: string[]; created: boolean }> = []\n\n await em.transactional(async (tem) => {\n if (!existingUser) return\n reusedExistingUser = true\n tenantId = existingUser.tenantId ? String(existingUser.tenantId) : undefined\n organizationId = existingUser.organizationId ? String(existingUser.organizationId) : undefined\n const roleTenantId = normalizeTenantId(existingUser.tenantId ?? null) ?? null\n\n await ensureRolesInContext(tem, roleNames, roleTenantId)\n await tem.flush()\n\n const requiredRoleSet = new Set([...roleNames, ...primaryRoles])\n const links = await findWithDecryption(\n tem,\n UserRole,\n { user: existingUser },\n { populate: ['role'] },\n { tenantId: roleTenantId, organizationId: null },\n )\n const currentRoles = new Set(links.map((link) => link.role.name))\n for (const roleName of requiredRoleSet) {\n if (!currentRoles.has(roleName)) {\n const role = await findRoleByNameOrFail(tem, roleName, roleTenantId)\n tem.persist(tem.create(UserRole, { user: existingUser, role, createdAt: new Date() }))\n }\n }\n await tem.flush()\n const roles = Array.from(new Set([...currentRoles, ...roleNames]))\n userSnapshots.push({ user: existingUser, roles, created: false })\n })\n\n if (!existingUser) {\n const baseUsers: Array<{\n email: string\n roles: string[]\n name?: string | null\n passwordHash?: string | null\n }> = [\n { email: primaryUser.email, roles: primaryRoles, name: resolvePrimaryName(primaryUser) },\n ]\n if (includeDerivedUsers) {\n const [, domain] = String(primaryUser.email).split('@')\n const adminOverride = readEnvValue(DERIVED_EMAIL_ENV.admin)\n const employeeOverride = readEnvValue(DERIVED_EMAIL_ENV.employee)\n const adminEmail = adminOverride ?? (domain ? `admin@${domain}` : '')\n const employeeEmail = employeeOverride ?? (domain ? `employee@${domain}` : '')\n const adminPassword = readEnvValue('OM_INIT_ADMIN_PASSWORD')\n const employeePassword = readEnvValue('OM_INIT_EMPLOYEE_PASSWORD')\n const adminPasswordHash = adminPassword ? await resolvePasswordHash({ email: adminEmail, password: adminPassword }) : null\n const employeePasswordHash = employeePassword\n ? await resolvePasswordHash({ email: employeeEmail, password: employeePassword })\n : null\n addUniqueBaseUser(baseUsers, { email: adminEmail, roles: ['admin'], passwordHash: adminPasswordHash })\n addUniqueBaseUser(baseUsers, { email: employeeEmail, roles: ['employee'], passwordHash: employeePasswordHash })\n }\n const passwordHash = await resolvePasswordHash(primaryUser)\n\n await em.transactional(async (tem) => {\n const tenant = tem.create(Tenant, {\n name: `${options.orgName} Tenant`,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n tem.persist(tenant)\n await tem.flush()\n\n const organization = tem.create(Organization, {\n name: options.orgName,\n tenant,\n isActive: true,\n depth: 0,\n ancestorIds: [],\n childIds: [],\n descendantIds: [],\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n tem.persist(organization)\n await tem.flush()\n\n tenantId = String(tenant.id)\n organizationId = String(organization.id)\n const roleTenantId = tenantId\n\n if (isTenantDataEncryptionEnabled()) {\n try {\n const kms = createKmsService()\n if (kms.isHealthy()) {\n if (isEncryptionDebugEnabled()) {\n console.info('\uD83D\uDD11 [encryption][setup] provisioning tenant DEK', { tenantId: String(tenant.id) })\n }\n await kms.createTenantDek(String(tenant.id))\n if (isEncryptionDebugEnabled()) {\n console.info('\uD83D\uDD11 [encryption][setup] created tenant DEK during setup', { tenantId: String(tenant.id) })\n }\n } else {\n if (isEncryptionDebugEnabled()) {\n console.warn('\u26A0\uFE0F [encryption][setup] KMS not healthy, skipping tenant DEK creation', { tenantId: String(tenant.id) })\n }\n }\n } catch (err) {\n if (isEncryptionDebugEnabled()) {\n console.warn('\u26A0\uFE0F [encryption][setup] Failed to create tenant DEK', err)\n }\n }\n }\n\n await ensureRolesInContext(tem, roleNames, roleTenantId)\n await tem.flush()\n\n if (isTenantDataEncryptionEnabled()) {\n for (const spec of DEFAULT_ENCRYPTION_MAPS) {\n const existing = await tem.findOne(EncryptionMap, { entityId: spec.entityId, tenantId: tenant.id, organizationId: organization.id, deletedAt: null })\n if (!existing) {\n tem.persist(tem.create(EncryptionMap, {\n entityId: spec.entityId,\n tenantId: tenant.id,\n organizationId: organization.id,\n fieldsJson: spec.fields,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n }))\n } else {\n existing.fieldsJson = spec.fields\n existing.isActive = true\n }\n }\n await tem.flush()\n }\n })\n\n await em.transactional(async (tem) => {\n if (!tenantId || !organizationId) return\n const roleTenantId = tenantId\n const encryptionService = isTenantDataEncryptionEnabled()\n ? new TenantDataEncryptionService(tem as any, { kms: createKmsService() })\n : null\n if (encryptionService) {\n await encryptionService.invalidateMap('auth:user', String(tenantId), String(organizationId))\n await encryptionService.invalidateMap('auth:user', String(tenantId), null)\n }\n\n for (const base of baseUsers) {\n const resolvedPasswordHash = base.passwordHash ?? passwordHash\n let user = await tem.findOne(User, { email: base.email })\n const confirm = primaryUser.confirm ?? true\n const encryptedPayload = encryptionService\n ? await encryptionService.encryptEntityPayload('auth:user', { email: base.email }, tenantId, organizationId)\n : { email: base.email, emailHash: computeEmailHash(base.email) }\n if (user) {\n user.passwordHash = resolvedPasswordHash\n user.organizationId = organizationId\n user.tenantId = tenantId\n if (isTenantDataEncryptionEnabled()) {\n user.email = encryptedPayload.email as any\n user.emailHash = (encryptedPayload as any).emailHash ?? computeEmailHash(base.email)\n }\n if (base.name) user.name = base.name\n if (confirm) user.isConfirmed = true\n tem.persist(user)\n userSnapshots.push({ user, roles: base.roles, created: false })\n } else {\n user = tem.create(User, {\n email: (encryptedPayload as any).email ?? base.email,\n emailHash: isTenantDataEncryptionEnabled() ? (encryptedPayload as any).emailHash ?? computeEmailHash(base.email) : undefined,\n passwordHash: resolvedPasswordHash,\n organizationId,\n tenantId,\n name: base.name ?? undefined,\n isConfirmed: confirm,\n createdAt: new Date(),\n })\n tem.persist(user)\n userSnapshots.push({ user, roles: base.roles, created: true })\n }\n await tem.flush()\n for (const roleName of base.roles) {\n const role = await findRoleByNameOrFail(tem, roleName, roleTenantId)\n const existingLink = await tem.findOne(UserRole, { user, role })\n if (!existingLink) tem.persist(tem.create(UserRole, { user, role, createdAt: new Date() }))\n }\n await tem.flush()\n }\n })\n }\n\n if (!tenantId || !organizationId) {\n throw new Error('SETUP_FAILED')\n }\n\n if (!reusedExistingUser) {\n await rebuildHierarchyForTenant(em, tenantId)\n }\n\n await ensureDefaultRoleAcls(em, tenantId, { includeSuperadminRole })\n await deactivateDemoSuperAdminIfSelfOnboardingEnabled(em)\n await ensureSalesNumberingDefaults(em, { tenantId, organizationId })\n\n return {\n tenantId,\n organizationId,\n users: userSnapshots,\n reusedExistingUser,\n }\n}\n\nfunction resolvePrimaryName(input: PrimaryUserInput): string | null {\n if (input.displayName && input.displayName.trim()) return input.displayName.trim()\n const parts = [input.firstName, input.lastName].map((value) => value?.trim()).filter(Boolean)\n if (parts.length) return parts.join(' ')\n return null\n}\n\nfunction readEnvValue(key: string): string | undefined {\n const value = process.env[key]\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\nfunction addUniqueBaseUser(\n baseUsers: Array<{ email: string; roles: string[]; name?: string | null; passwordHash?: string | null }>,\n entry: { email: string; roles: string[]; name?: string | null; passwordHash?: string | null },\n) {\n if (!entry.email) return\n const normalized = entry.email.toLowerCase()\n if (baseUsers.some((user) => user.email.toLowerCase() === normalized)) return\n baseUsers.push(entry)\n}\n\nfunction isDemoModeEnabled(): boolean {\n const parsed = parseBooleanToken(process.env.DEMO_MODE ?? '')\n return parsed === false ? false : true\n}\n\nfunction shouldKeepDemoSuperadminDuringInit(): boolean {\n if (process.env.OM_INIT_FLOW !== 'true') return false\n if (!readEnvValue('OM_INIT_SUPERADMIN_EMAIL')) return false\n return isDemoModeEnabled()\n}\n\nasync function resolvePasswordHash(input: PrimaryUserInput): Promise<string | null> {\n if (typeof input.hashedPassword === 'string') return input.hashedPassword\n if (input.password) return hash(input.password, 10)\n return null\n}\n\nasync function ensureDefaultRoleAcls(\n em: EntityManager,\n tenantId: string,\n options: { includeSuperadminRole?: boolean } = {},\n) {\n const includeSuperadminRole = options.includeSuperadminRole ?? true\n const roleTenantId = normalizeTenantId(tenantId) ?? null\n const superadminRole = includeSuperadminRole ? await findRoleByName(em, 'superadmin', roleTenantId) : null\n const adminRole = await findRoleByName(em, 'admin', roleTenantId)\n const employeeRole = await findRoleByName(em, 'employee', roleTenantId)\n\n if (includeSuperadminRole && superadminRole) {\n await ensureRoleAclFor(em, superadminRole, tenantId, ['directory.tenants.*'], { isSuperAdmin: true })\n }\n if (adminRole) {\n const adminFeatures = [\n 'auth.*',\n 'entities.*',\n 'attachments.*',\n 'attachments.view',\n 'attachments.manage',\n 'query_index.*',\n 'search.*',\n 'vector.*',\n 'feature_toggles.*',\n 'configs.system_status.view',\n 'configs.cache.view',\n 'configs.cache.manage',\n 'configs.manage',\n 'catalog.*',\n 'catalog.variants.manage',\n 'catalog.pricing.manage',\n 'sales.*',\n 'audit_logs.*',\n 'directory.organizations.view',\n 'directory.organizations.manage',\n 'customers.*',\n 'customers.people.view',\n 'customers.people.manage',\n 'customers.companies.view',\n 'customers.companies.manage',\n 'customers.deals.view',\n 'customers.deals.manage',\n 'dictionaries.view',\n 'dictionaries.manage',\n 'example.*',\n 'dashboards.*',\n 'dashboards.admin.assign-widgets',\n 'analytics.view',\n 'api_keys.*',\n 'notifications.manage',\n 'perspectives.use',\n 'perspectives.role_defaults',\n 'business_rules.*',\n 'workflows.*',\n 'currencies.*',\n 'staff.*',\n 'staff.leave_requests.manage',\n 'resources.*',\n 'planner.*',\n ]\n await ensureRoleAclFor(em, adminRole, tenantId, adminFeatures, { remove: ['directory.organizations.*', 'directory.tenants.*'] })\n }\n if (employeeRole) {\n await ensureRoleAclFor(em, employeeRole, tenantId, [\n 'customers.*',\n 'customers.people.view',\n 'customers.people.manage',\n 'customers.companies.view',\n 'customers.companies.manage',\n 'vector.*',\n 'catalog.*',\n 'catalog.variants.manage',\n 'catalog.pricing.manage',\n 'sales.*',\n 'dictionaries.view',\n 'example.*',\n 'example.widgets.*',\n 'dashboards.view',\n 'dashboards.configure',\n 'analytics.view',\n 'audit_logs.undo_self',\n 'perspectives.use',\n 'staff.leave_requests.send',\n 'staff.my_availability.view',\n 'staff.my_availability.manage',\n 'staff.my_leave_requests.view',\n 'staff.my_leave_requests.send',\n 'planner.view',\n ])\n }\n}\n\nasync function ensureRoleAclFor(\n em: EntityManager,\n role: Role,\n tenantId: string,\n features: string[],\n options: { isSuperAdmin?: boolean; remove?: string[] } = {},\n) {\n const existing = await em.findOne(RoleAcl, { role, tenantId })\n if (!existing) {\n const acl = em.create(RoleAcl, {\n role,\n tenantId,\n featuresJson: features,\n isSuperAdmin: !!options.isSuperAdmin,\n createdAt: new Date(),\n })\n await em.persistAndFlush(acl)\n return\n }\n const currentFeatures = Array.isArray(existing.featuresJson) ? existing.featuresJson : []\n const merged = Array.from(new Set([...currentFeatures, ...features]))\n const removeSet = new Set(options.remove ?? [])\n const sanitized =\n removeSet.size\n ? merged.filter((value) => {\n if (removeSet.has(value)) return false\n for (const entry of removeSet) {\n if (entry.endsWith('.*')) {\n const prefix = entry.slice(0, -1) // keep trailing dot\n if (value === entry || value.startsWith(prefix)) return false\n }\n }\n return true\n })\n : merged\n const changed =\n sanitized.length !== currentFeatures.length ||\n sanitized.some((value, index) => value !== currentFeatures[index])\n if (changed) existing.featuresJson = sanitized\n if (options.isSuperAdmin && !existing.isSuperAdmin) {\n existing.isSuperAdmin = true\n }\n if (changed || options.isSuperAdmin) {\n await em.persistAndFlush(existing)\n }\n}\n\nasync function deactivateDemoSuperAdminIfSelfOnboardingEnabled(em: EntityManager) {\n if (process.env.SELF_SERVICE_ONBOARDING_ENABLED !== 'true') return\n if (shouldKeepDemoSuperadminDuringInit()) return\n try {\n const user = await em.findOne(User, { email: DEMO_SUPERADMIN_EMAIL })\n if (!user) return\n let dirty = false\n if (user.passwordHash) {\n user.passwordHash = null\n dirty = true\n }\n if (user.isConfirmed !== false) {\n user.isConfirmed = false\n dirty = true\n }\n if (dirty) {\n await em.persistAndFlush(user)\n }\n } catch (error) {\n console.error('[auth.setup] failed to deactivate demo superadmin user', error)\n }\n}\n\nasync function ensureSalesNumberingDefaults(\n em: EntityManager,\n scope: { tenantId: string; organizationId: string },\n) {\n const repo = (em as any).getRepository?.(SalesSettings)\n const findSettings = async () =>\n repo?.findOne({\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n }) ??\n (em as any).findOne?.(SalesSettings, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n\n const exists = await findSettings()\n if (!exists) {\n const settings =\n repo?.create?.({\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n orderNumberFormat: DEFAULT_ORDER_NUMBER_FORMAT,\n quoteNumberFormat: DEFAULT_QUOTE_NUMBER_FORMAT,\n createdAt: new Date(),\n updatedAt: new Date(),\n }) ??\n (em as any).create?.(SalesSettings, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n orderNumberFormat: DEFAULT_ORDER_NUMBER_FORMAT,\n quoteNumberFormat: DEFAULT_QUOTE_NUMBER_FORMAT,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n if (settings && (em as any).persist) {\n em.persist(settings)\n }\n }\n\n const sequenceRepo = (em as any).getRepository?.(SalesDocumentSequence)\n const kinds: Array<'order' | 'quote'> = ['order', 'quote']\n for (const kind of kinds) {\n const seq =\n sequenceRepo?.findOne({\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n documentKind: kind,\n }) ??\n (em as any).findOne?.(SalesDocumentSequence, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n documentKind: kind,\n })\n if (!seq) {\n const entry =\n sequenceRepo?.create?.({\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n documentKind: kind,\n currentValue: 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n }) ??\n (em as any).create?.(SalesDocumentSequence, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n documentKind: kind,\n currentValue: 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n if (entry && (em as any).persist) {\n em.persist(entry)\n }\n }\n }\n\n if ((em as any).flush) {\n await em.flush()\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { hash } from 'bcryptjs'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { Role, RoleAcl, User, UserRole } from '@open-mercato/core/modules/auth/data/entities'\nimport { Tenant, Organization } from '@open-mercato/core/modules/directory/data/entities'\nimport { rebuildHierarchyForTenant } from '@open-mercato/core/modules/directory/lib/hierarchy'\nimport { normalizeTenantId } from './tenantAccess'\nimport { SalesSettings, SalesDocumentSequence } from '@open-mercato/core/modules/sales/data/entities'\nimport {\n DEFAULT_ORDER_NUMBER_FORMAT,\n DEFAULT_QUOTE_NUMBER_FORMAT,\n} from '@open-mercato/core/modules/sales/lib/documentNumberTokens'\nimport { computeEmailHash } from '@open-mercato/core/modules/auth/lib/emailHash'\nimport { isEncryptionDebugEnabled, isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'\nimport { EncryptionMap } from '@open-mercato/core/modules/entities/data/entities'\nimport { DEFAULT_ENCRYPTION_MAPS } from '@open-mercato/core/modules/entities/lib/encryptionDefaults'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\nconst DEFAULT_ROLE_NAMES = ['employee', 'admin', 'superadmin'] as const\nconst DEMO_SUPERADMIN_EMAIL = 'superadmin@acme.com'\n\nexport type EnsureRolesOptions = {\n roleNames?: string[]\n tenantId?: string | null\n}\n\nasync function ensureRolesInContext(\n em: EntityManager,\n roleNames: string[],\n tenantId: string | null,\n) {\n for (const name of roleNames) {\n const existing = await em.findOne(Role, { name, tenantId })\n if (existing) continue\n if (tenantId !== null) {\n const globalRole = await em.findOne(Role, { name, tenantId: null })\n if (globalRole) {\n globalRole.tenantId = tenantId\n em.persist(globalRole)\n continue\n }\n }\n em.persist(em.create(Role, { name, tenantId, createdAt: new Date() }))\n }\n}\n\nexport async function ensureRoles(em: EntityManager, options: EnsureRolesOptions = {}) {\n const roleNames = options.roleNames ?? [...DEFAULT_ROLE_NAMES]\n const tenantId = normalizeTenantId(options.tenantId ?? null) ?? null\n await em.transactional(async (tem) => {\n await ensureRolesInContext(tem, roleNames, tenantId)\n await tem.flush()\n })\n}\n\nasync function findRoleByName(\n em: EntityManager,\n name: string,\n tenantId: string | null,\n): Promise<Role | null> {\n const normalizedTenant = normalizeTenantId(tenantId ?? null) ?? null\n let role = await em.findOne(Role, { name, tenantId: normalizedTenant })\n if (!role && normalizedTenant !== null) {\n role = await em.findOne(Role, { name, tenantId: null })\n }\n return role\n}\n\nasync function findRoleByNameOrFail(\n em: EntityManager,\n name: string,\n tenantId: string | null,\n): Promise<Role> {\n const role = await findRoleByName(em, name, tenantId)\n if (!role) throw new Error(`ROLE_NOT_FOUND:${name}`)\n return role\n}\n\ntype PrimaryUserInput = {\n email: string\n password?: string\n hashedPassword?: string | null\n firstName?: string | null\n lastName?: string | null\n displayName?: string | null\n confirm?: boolean\n}\n\nexport type SetupInitialTenantOptions = {\n orgName: string\n primaryUser: PrimaryUserInput\n roleNames?: string[]\n includeDerivedUsers?: boolean\n failIfUserExists?: boolean\n primaryUserRoles?: string[]\n includeSuperadminRole?: boolean\n}\n\nexport type SetupInitialTenantResult = {\n tenantId: string\n organizationId: string\n users: Array<{ user: User; roles: string[]; created: boolean }>\n reusedExistingUser: boolean\n}\n\nexport async function setupInitialTenant(\n em: EntityManager,\n options: SetupInitialTenantOptions,\n): Promise<SetupInitialTenantResult> {\n const {\n primaryUser,\n includeDerivedUsers = true,\n failIfUserExists = false,\n primaryUserRoles,\n includeSuperadminRole = true,\n } = options\n const primaryRolesInput = primaryUserRoles && primaryUserRoles.length ? primaryUserRoles : ['superadmin']\n const primaryRoles = includeSuperadminRole\n ? primaryRolesInput\n : primaryRolesInput.filter((role) => role !== 'superadmin')\n if (primaryRoles.length === 0) {\n throw new Error('PRIMARY_ROLES_REQUIRED')\n }\n const defaultRoleNames = options.roleNames ?? [...DEFAULT_ROLE_NAMES]\n const resolvedRoleNames = includeSuperadminRole\n ? defaultRoleNames\n : defaultRoleNames.filter((role) => role !== 'superadmin')\n const roleNames = Array.from(new Set([...resolvedRoleNames, ...primaryRoles]))\n\n const mainEmail = primaryUser.email\n const existingUser = await em.findOne(User, { email: mainEmail })\n if (existingUser && failIfUserExists) {\n throw new Error('USER_EXISTS')\n }\n\n let tenantId: string | undefined\n let organizationId: string | undefined\n let reusedExistingUser = false\n const userSnapshots: Array<{ user: User; roles: string[]; created: boolean }> = []\n\n await em.transactional(async (tem) => {\n if (!existingUser) return\n reusedExistingUser = true\n tenantId = existingUser.tenantId ? String(existingUser.tenantId) : undefined\n organizationId = existingUser.organizationId ? String(existingUser.organizationId) : undefined\n const roleTenantId = normalizeTenantId(existingUser.tenantId ?? null) ?? null\n\n await ensureRolesInContext(tem, roleNames, roleTenantId)\n await tem.flush()\n\n const requiredRoleSet = new Set([...roleNames, ...primaryRoles])\n const links = await findWithDecryption(\n tem,\n UserRole,\n { user: existingUser },\n { populate: ['role'] },\n { tenantId: roleTenantId, organizationId: null },\n )\n const currentRoles = new Set(links.map((link) => link.role.name))\n for (const roleName of requiredRoleSet) {\n if (!currentRoles.has(roleName)) {\n const role = await findRoleByNameOrFail(tem, roleName, roleTenantId)\n tem.persist(tem.create(UserRole, { user: existingUser, role, createdAt: new Date() }))\n }\n }\n await tem.flush()\n const roles = Array.from(new Set([...currentRoles, ...roleNames]))\n userSnapshots.push({ user: existingUser, roles, created: false })\n })\n\n if (!existingUser) {\n const baseUsers: Array<{ email: string; roles: string[]; name?: string | null }> = [\n { email: primaryUser.email, roles: primaryRoles, name: resolvePrimaryName(primaryUser) },\n ]\n if (includeDerivedUsers) {\n const [local, domain] = String(primaryUser.email).split('@')\n const isSuperadminLocal = (local || '').toLowerCase() === 'superadmin' && !!domain\n if (isSuperadminLocal) {\n baseUsers.push({ email: `admin@${domain}`, roles: ['admin'] })\n baseUsers.push({ email: `employee@${domain}`, roles: ['employee'] })\n }\n }\n const passwordHash = await resolvePasswordHash(primaryUser)\n\n await em.transactional(async (tem) => {\n const tenant = tem.create(Tenant, {\n name: `${options.orgName} Tenant`,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n tem.persist(tenant)\n await tem.flush()\n\n const organization = tem.create(Organization, {\n name: options.orgName,\n tenant,\n isActive: true,\n depth: 0,\n ancestorIds: [],\n childIds: [],\n descendantIds: [],\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n tem.persist(organization)\n await tem.flush()\n\n tenantId = String(tenant.id)\n organizationId = String(organization.id)\n const roleTenantId = tenantId\n\n if (isTenantDataEncryptionEnabled()) {\n try {\n const kms = createKmsService()\n if (kms.isHealthy()) {\n if (isEncryptionDebugEnabled()) {\n console.info('\uD83D\uDD11 [encryption][setup] provisioning tenant DEK', { tenantId: String(tenant.id) })\n }\n await kms.createTenantDek(String(tenant.id))\n if (isEncryptionDebugEnabled()) {\n console.info('\uD83D\uDD11 [encryption][setup] created tenant DEK during setup', { tenantId: String(tenant.id) })\n }\n } else {\n if (isEncryptionDebugEnabled()) {\n console.warn('\u26A0\uFE0F [encryption][setup] KMS not healthy, skipping tenant DEK creation', { tenantId: String(tenant.id) })\n }\n }\n } catch (err) {\n if (isEncryptionDebugEnabled()) {\n console.warn('\u26A0\uFE0F [encryption][setup] Failed to create tenant DEK', err)\n }\n }\n }\n\n await ensureRolesInContext(tem, roleNames, roleTenantId)\n await tem.flush()\n\n if (isTenantDataEncryptionEnabled()) {\n for (const spec of DEFAULT_ENCRYPTION_MAPS) {\n const existing = await tem.findOne(EncryptionMap, { entityId: spec.entityId, tenantId: tenant.id, organizationId: organization.id, deletedAt: null })\n if (!existing) {\n tem.persist(tem.create(EncryptionMap, {\n entityId: spec.entityId,\n tenantId: tenant.id,\n organizationId: organization.id,\n fieldsJson: spec.fields,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n }))\n } else {\n existing.fieldsJson = spec.fields\n existing.isActive = true\n }\n }\n await tem.flush()\n }\n })\n\n await em.transactional(async (tem) => {\n if (!tenantId || !organizationId) return\n const roleTenantId = tenantId\n const encryptionService = isTenantDataEncryptionEnabled()\n ? new TenantDataEncryptionService(tem as any, { kms: createKmsService() })\n : null\n if (encryptionService) {\n await encryptionService.invalidateMap('auth:user', String(tenantId), String(organizationId))\n await encryptionService.invalidateMap('auth:user', String(tenantId), null)\n }\n\n for (const base of baseUsers) {\n let user = await tem.findOne(User, { email: base.email })\n const confirm = primaryUser.confirm ?? true\n const encryptedPayload = encryptionService\n ? await encryptionService.encryptEntityPayload('auth:user', { email: base.email }, tenantId, organizationId)\n : { email: base.email, emailHash: computeEmailHash(base.email) }\n if (user) {\n user.passwordHash = passwordHash\n user.organizationId = organizationId\n user.tenantId = tenantId\n if (isTenantDataEncryptionEnabled()) {\n user.email = encryptedPayload.email as any\n user.emailHash = (encryptedPayload as any).emailHash ?? computeEmailHash(base.email)\n }\n if (base.name) user.name = base.name\n if (confirm) user.isConfirmed = true\n tem.persist(user)\n userSnapshots.push({ user, roles: base.roles, created: false })\n } else {\n user = tem.create(User, {\n email: (encryptedPayload as any).email ?? base.email,\n emailHash: isTenantDataEncryptionEnabled() ? (encryptedPayload as any).emailHash ?? computeEmailHash(base.email) : undefined,\n passwordHash,\n organizationId,\n tenantId,\n name: base.name ?? undefined,\n isConfirmed: confirm,\n createdAt: new Date(),\n })\n tem.persist(user)\n userSnapshots.push({ user, roles: base.roles, created: true })\n }\n await tem.flush()\n for (const roleName of base.roles) {\n const role = await findRoleByNameOrFail(tem, roleName, roleTenantId)\n const existingLink = await tem.findOne(UserRole, { user, role })\n if (!existingLink) tem.persist(tem.create(UserRole, { user, role, createdAt: new Date() }))\n }\n await tem.flush()\n }\n })\n }\n\n if (!tenantId || !organizationId) {\n throw new Error('SETUP_FAILED')\n }\n\n if (!reusedExistingUser) {\n await rebuildHierarchyForTenant(em, tenantId)\n }\n\n await ensureDefaultRoleAcls(em, tenantId, { includeSuperadminRole })\n await deactivateDemoSuperAdminIfSelfOnboardingEnabled(em)\n await ensureSalesNumberingDefaults(em, { tenantId, organizationId })\n\n return {\n tenantId,\n organizationId,\n users: userSnapshots,\n reusedExistingUser,\n }\n}\n\nfunction resolvePrimaryName(input: PrimaryUserInput): string | null {\n if (input.displayName && input.displayName.trim()) return input.displayName.trim()\n const parts = [input.firstName, input.lastName].map((value) => value?.trim()).filter(Boolean)\n if (parts.length) return parts.join(' ')\n return null\n}\n\nasync function resolvePasswordHash(input: PrimaryUserInput): Promise<string | null> {\n if (typeof input.hashedPassword === 'string') return input.hashedPassword\n if (input.password) return hash(input.password, 10)\n return null\n}\n\nasync function ensureDefaultRoleAcls(\n em: EntityManager,\n tenantId: string,\n options: { includeSuperadminRole?: boolean } = {},\n) {\n const includeSuperadminRole = options.includeSuperadminRole ?? true\n const roleTenantId = normalizeTenantId(tenantId) ?? null\n const superadminRole = includeSuperadminRole ? await findRoleByName(em, 'superadmin', roleTenantId) : null\n const adminRole = await findRoleByName(em, 'admin', roleTenantId)\n const employeeRole = await findRoleByName(em, 'employee', roleTenantId)\n\n if (includeSuperadminRole && superadminRole) {\n await ensureRoleAclFor(em, superadminRole, tenantId, ['directory.tenants.*'], { isSuperAdmin: true })\n }\n if (adminRole) {\n const adminFeatures = [\n 'auth.*',\n 'entities.*',\n 'attachments.*',\n 'attachments.view',\n 'attachments.manage',\n 'query_index.*',\n 'search.*',\n 'vector.*',\n 'feature_toggles.*',\n 'configs.system_status.view',\n 'configs.cache.view',\n 'configs.cache.manage',\n 'configs.manage',\n 'catalog.*',\n 'catalog.variants.manage',\n 'catalog.pricing.manage',\n 'sales.*',\n 'audit_logs.*',\n 'directory.organizations.view',\n 'directory.organizations.manage',\n 'customers.*',\n 'customers.people.view',\n 'customers.people.manage',\n 'customers.companies.view',\n 'customers.companies.manage',\n 'customers.deals.view',\n 'customers.deals.manage',\n 'dictionaries.view',\n 'dictionaries.manage',\n 'example.*',\n 'dashboards.*',\n 'dashboards.admin.assign-widgets',\n 'analytics.view',\n 'api_keys.*',\n 'perspectives.use',\n 'perspectives.role_defaults',\n 'business_rules.*',\n 'workflows.*',\n 'currencies.*',\n 'staff.*',\n 'staff.leave_requests.manage',\n 'resources.*',\n 'planner.*',\n ]\n await ensureRoleAclFor(em, adminRole, tenantId, adminFeatures, { remove: ['directory.organizations.*', 'directory.tenants.*'] })\n }\n if (employeeRole) {\n await ensureRoleAclFor(em, employeeRole, tenantId, [\n 'customers.*',\n 'customers.people.view',\n 'customers.people.manage',\n 'customers.companies.view',\n 'customers.companies.manage',\n 'vector.*',\n 'catalog.*',\n 'catalog.variants.manage',\n 'catalog.pricing.manage',\n 'sales.*',\n 'dictionaries.view',\n 'example.*',\n 'example.widgets.*',\n 'dashboards.view',\n 'dashboards.configure',\n 'analytics.view',\n 'audit_logs.undo_self',\n 'perspectives.use',\n 'staff.leave_requests.send',\n 'staff.my_availability.view',\n 'staff.my_availability.manage',\n 'staff.my_leave_requests.view',\n 'staff.my_leave_requests.send',\n 'planner.view',\n ])\n }\n}\n\nasync function ensureRoleAclFor(\n em: EntityManager,\n role: Role,\n tenantId: string,\n features: string[],\n options: { isSuperAdmin?: boolean; remove?: string[] } = {},\n) {\n const existing = await em.findOne(RoleAcl, { role, tenantId })\n if (!existing) {\n const acl = em.create(RoleAcl, {\n role,\n tenantId,\n featuresJson: features,\n isSuperAdmin: !!options.isSuperAdmin,\n createdAt: new Date(),\n })\n await em.persistAndFlush(acl)\n return\n }\n const currentFeatures = Array.isArray(existing.featuresJson) ? existing.featuresJson : []\n const merged = Array.from(new Set([...currentFeatures, ...features]))\n const removeSet = new Set(options.remove ?? [])\n const sanitized =\n removeSet.size\n ? merged.filter((value) => {\n if (removeSet.has(value)) return false\n for (const entry of removeSet) {\n if (entry.endsWith('.*')) {\n const prefix = entry.slice(0, -1) // keep trailing dot\n if (value === entry || value.startsWith(prefix)) return false\n }\n }\n return true\n })\n : merged\n const changed =\n sanitized.length !== currentFeatures.length ||\n sanitized.some((value, index) => value !== currentFeatures[index])\n if (changed) existing.featuresJson = sanitized\n if (options.isSuperAdmin && !existing.isSuperAdmin) {\n existing.isSuperAdmin = true\n }\n if (changed || options.isSuperAdmin) {\n await em.persistAndFlush(existing)\n }\n}\n\nasync function deactivateDemoSuperAdminIfSelfOnboardingEnabled(em: EntityManager) {\n if (process.env.SELF_SERVICE_ONBOARDING_ENABLED !== 'true') return\n try {\n const user = await em.findOne(User, { email: DEMO_SUPERADMIN_EMAIL })\n if (!user) return\n let dirty = false\n if (user.passwordHash) {\n user.passwordHash = null\n dirty = true\n }\n if (user.isConfirmed !== false) {\n user.isConfirmed = false\n dirty = true\n }\n if (dirty) {\n await em.persistAndFlush(user)\n }\n } catch (error) {\n console.error('[auth.setup] failed to deactivate demo superadmin user', error)\n }\n}\n\nasync function ensureSalesNumberingDefaults(\n em: EntityManager,\n scope: { tenantId: string; organizationId: string },\n) {\n const repo = (em as any).getRepository?.(SalesSettings)\n const findSettings = async () =>\n repo?.findOne({\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n }) ??\n (em as any).findOne?.(SalesSettings, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n\n const exists = await findSettings()\n if (!exists) {\n const settings =\n repo?.create?.({\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n orderNumberFormat: DEFAULT_ORDER_NUMBER_FORMAT,\n quoteNumberFormat: DEFAULT_QUOTE_NUMBER_FORMAT,\n createdAt: new Date(),\n updatedAt: new Date(),\n }) ??\n (em as any).create?.(SalesSettings, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n orderNumberFormat: DEFAULT_ORDER_NUMBER_FORMAT,\n quoteNumberFormat: DEFAULT_QUOTE_NUMBER_FORMAT,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n if (settings && (em as any).persist) {\n em.persist(settings)\n }\n }\n\n const sequenceRepo = (em as any).getRepository?.(SalesDocumentSequence)\n const kinds: Array<'order' | 'quote'> = ['order', 'quote']\n for (const kind of kinds) {\n const seq =\n sequenceRepo?.findOne({\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n documentKind: kind,\n }) ??\n (em as any).findOne?.(SalesDocumentSequence, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n documentKind: kind,\n })\n if (!seq) {\n const entry =\n sequenceRepo?.create?.({\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n documentKind: kind,\n currentValue: 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n }) ??\n (em as any).create?.(SalesDocumentSequence, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n documentKind: kind,\n currentValue: 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n if (entry && (em as any).persist) {\n em.persist(entry)\n }\n }\n }\n\n if ((em as any).flush) {\n await em.flush()\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -16,27 +16,6 @@ class AuthService {
16
16
  ]
17
17
  });
18
18
  }
19
- async findUsersByEmail(email) {
20
- const emailHash = computeEmailHash(email);
21
- return this.em.find(User, {
22
- deletedAt: null,
23
- $or: [
24
- { email },
25
- { emailHash }
26
- ]
27
- });
28
- }
29
- async findUserByEmailAndTenant(email, tenantId) {
30
- const emailHash = computeEmailHash(email);
31
- return this.em.findOne(User, {
32
- tenantId,
33
- deletedAt: null,
34
- $or: [
35
- { email },
36
- { emailHash }
37
- ]
38
- });
39
- }
40
19
  async verifyPassword(user, password) {
41
20
  if (!user.passwordHash) return false;
42
21
  return compare(password, user.passwordHash);
@@ -88,13 +67,13 @@ class AuthService {
88
67
  async confirmPasswordReset(token, newPassword) {
89
68
  const now = /* @__PURE__ */ new Date();
90
69
  const row = await this.em.findOne(PasswordReset, { token });
91
- if (!row || row.usedAt && row.usedAt <= now || row.expiresAt <= now) return null;
70
+ if (!row || row.usedAt && row.usedAt <= now || row.expiresAt <= now) return false;
92
71
  const user = await this.em.findOne(User, { id: row.user.id });
93
- if (!user) return null;
72
+ if (!user) return false;
94
73
  user.passwordHash = await hash(newPassword, 10);
95
74
  row.usedAt = /* @__PURE__ */ new Date();
96
75
  await this.em.flush();
97
- return user;
76
+ return true;
98
77
  }
99
78
  }
100
79
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/auth/services/authService.ts"],
4
- "sourcesContent": ["import { EntityManager } from '@mikro-orm/postgresql'\nimport { compare, hash } from 'bcryptjs'\nimport { User, Role, UserRole, Session, PasswordReset } from '@open-mercato/core/modules/auth/data/entities'\nimport crypto from 'node:crypto'\nimport { computeEmailHash } from '@open-mercato/core/modules/auth/lib/emailHash'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\nexport class AuthService {\n constructor(private em: EntityManager) {}\n\n async findUserByEmail(email: string) {\n const emailHash = computeEmailHash(email)\n return this.em.findOne(User, {\n $or: [\n { email },\n { emailHash },\n ],\n } as any)\n }\n\n async findUsersByEmail(email: string) {\n const emailHash = computeEmailHash(email)\n return this.em.find(User, {\n deletedAt: null,\n $or: [\n { email },\n { emailHash },\n ],\n } as any)\n }\n\n async findUserByEmailAndTenant(email: string, tenantId: string) {\n const emailHash = computeEmailHash(email)\n return this.em.findOne(User, {\n tenantId,\n deletedAt: null,\n $or: [\n { email },\n { emailHash },\n ],\n } as any)\n }\n\n async verifyPassword(user: User, password: string) {\n if (!user.passwordHash) return false\n return compare(password, user.passwordHash)\n }\n\n async updateLastLoginAt(user: User) {\n const now = new Date()\n // Use native update to avoid flushing unrelated entities that might be pending in this EM\n await this.em.nativeUpdate(User, { id: user.id }, { lastLoginAt: now })\n user.lastLoginAt = now\n }\n\n async getUserRoles(user: User, tenantId?: string | null): Promise<string[]> {\n const resolvedTenantId = tenantId ?? user.tenantId ?? null\n if (!resolvedTenantId) return []\n const links = await findWithDecryption(\n this.em,\n UserRole,\n { user, role: { tenantId: resolvedTenantId } as any },\n { populate: ['role'] },\n { tenantId: resolvedTenantId, organizationId: user.organizationId ?? null },\n )\n return links.map((l) => l.role.name)\n }\n\n\n async createSession(user: User, expiresAt: Date): Promise<Session> {\n const token = crypto.randomBytes(32).toString('hex')\n const sess = this.em.create(Session as any, { user, token, expiresAt, createdAt: new Date() } as any)\n await this.em.persistAndFlush(sess)\n return sess as Session\n }\n\n async deleteSessionByToken(token: string) {\n await this.em.nativeDelete(Session, { token })\n }\n\n async refreshFromSessionToken(token: string) {\n const now = new Date()\n const sess = await this.em.findOne(Session, { token })\n if (!sess || sess.expiresAt <= now) return null\n const user = await this.em.findOne(User, { id: sess.user.id })\n if (!user) return null\n const roles = await this.getUserRoles(user, user.tenantId ?? null)\n return { user, roles }\n }\n\n async requestPasswordReset(email: string) {\n const user = await this.findUserByEmail(email)\n if (!user) return null\n const token = crypto.randomBytes(32).toString('hex')\n const expiresAt = new Date(Date.now() + 60 * 60 * 1000)\n const row = this.em.create(PasswordReset as any, { user, token, expiresAt, createdAt: new Date() } as any)\n await this.em.persistAndFlush(row)\n return { user, token }\n }\n\n async confirmPasswordReset(token: string, newPassword: string): Promise<User | null> {\n const now = new Date()\n const row = await this.em.findOne(PasswordReset, { token })\n if (!row || (row.usedAt && row.usedAt <= now) || row.expiresAt <= now) return null\n const user = await this.em.findOne(User, { id: row.user.id })\n if (!user) return null\n user.passwordHash = await hash(newPassword, 10)\n row.usedAt = new Date()\n await this.em.flush()\n return user\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { EntityManager } from '@mikro-orm/postgresql'\nimport { compare, hash } from 'bcryptjs'\nimport { User, Role, UserRole, Session, PasswordReset } from '@open-mercato/core/modules/auth/data/entities'\nimport crypto from 'node:crypto'\nimport { computeEmailHash } from '@open-mercato/core/modules/auth/lib/emailHash'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\nexport class AuthService {\n constructor(private em: EntityManager) {}\n\n async findUserByEmail(email: string) {\n const emailHash = computeEmailHash(email)\n return this.em.findOne(User, {\n $or: [\n { email },\n { emailHash },\n ],\n } as any)\n }\n\n async verifyPassword(user: User, password: string) {\n if (!user.passwordHash) return false\n return compare(password, user.passwordHash)\n }\n\n async updateLastLoginAt(user: User) {\n const now = new Date()\n // Use native update to avoid flushing unrelated entities that might be pending in this EM\n await this.em.nativeUpdate(User, { id: user.id }, { lastLoginAt: now })\n user.lastLoginAt = now\n }\n\n async getUserRoles(user: User, tenantId?: string | null): Promise<string[]> {\n const resolvedTenantId = tenantId ?? user.tenantId ?? null\n if (!resolvedTenantId) return []\n const links = await findWithDecryption(\n this.em,\n UserRole,\n { user, role: { tenantId: resolvedTenantId } as any },\n { populate: ['role'] },\n { tenantId: resolvedTenantId, organizationId: user.organizationId ?? null },\n )\n return links.map((l) => l.role.name)\n }\n\n\n async createSession(user: User, expiresAt: Date): Promise<Session> {\n const token = crypto.randomBytes(32).toString('hex')\n const sess = this.em.create(Session as any, { user, token, expiresAt, createdAt: new Date() } as any)\n await this.em.persistAndFlush(sess)\n return sess as Session\n }\n\n async deleteSessionByToken(token: string) {\n await this.em.nativeDelete(Session, { token })\n }\n\n async refreshFromSessionToken(token: string) {\n const now = new Date()\n const sess = await this.em.findOne(Session, { token })\n if (!sess || sess.expiresAt <= now) return null\n const user = await this.em.findOne(User, { id: sess.user.id })\n if (!user) return null\n const roles = await this.getUserRoles(user, user.tenantId ?? null)\n return { user, roles }\n }\n\n async requestPasswordReset(email: string) {\n const user = await this.findUserByEmail(email)\n if (!user) return null\n const token = crypto.randomBytes(32).toString('hex')\n const expiresAt = new Date(Date.now() + 60 * 60 * 1000)\n const row = this.em.create(PasswordReset as any, { user, token, expiresAt, createdAt: new Date() } as any)\n await this.em.persistAndFlush(row)\n return { user, token }\n }\n\n async confirmPasswordReset(token: string, newPassword: string) {\n const now = new Date()\n const row = await this.em.findOne(PasswordReset, { token })\n if (!row || (row.usedAt && row.usedAt <= now) || row.expiresAt <= now) return false\n const user = await this.em.findOne(User, { id: row.user.id })\n if (!user) return false\n user.passwordHash = await hash(newPassword, 10)\n row.usedAt = new Date()\n await this.em.flush()\n return true\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -37,12 +37,6 @@ async function POST(req) {
37
37
  }
38
38
  const container = await createRequestContainer();
39
39
  const em = container.resolve("em");
40
- let eventBus = null;
41
- try {
42
- eventBus = container.resolve("eventBus");
43
- } catch {
44
- eventBus = null;
45
- }
46
40
  let body;
47
41
  try {
48
42
  body = await req.json();
@@ -76,7 +70,7 @@ async function POST(req) {
76
70
  return NextResponse.json({ error: `Invalid execution context: ${errors.join(", ")}` }, { status: 400 });
77
71
  }
78
72
  try {
79
- const result = await ruleEngine.executeRules(em, context, { eventBus });
73
+ const result = await ruleEngine.executeRules(em, context);
80
74
  const response = {
81
75
  allowed: result.allowed,
82
76
  executedRules: result.executedRules.map((r) => ({