@hed-hog/core 0.0.387 → 0.0.390

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 (535) hide show
  1. package/README.md +12 -11
  2. package/dist/access-log/access-log.interceptor.d.ts.map +1 -1
  3. package/dist/access-log/access-log.interceptor.js +4 -2
  4. package/dist/access-log/access-log.interceptor.js.map +1 -1
  5. package/dist/ai/ai-attachment.fragments.d.ts +23 -0
  6. package/dist/ai/ai-attachment.fragments.d.ts.map +1 -0
  7. package/dist/ai/ai-attachment.fragments.js +34 -0
  8. package/dist/ai/ai-attachment.fragments.js.map +1 -0
  9. package/dist/ai/ai.controller.d.ts +7 -16
  10. package/dist/ai/ai.controller.d.ts.map +1 -1
  11. package/dist/ai/ai.prompts.d.ts +16 -0
  12. package/dist/ai/ai.prompts.d.ts.map +1 -0
  13. package/dist/ai/ai.prompts.js +37 -0
  14. package/dist/ai/ai.prompts.js.map +1 -0
  15. package/dist/ai/ai.service.d.ts +63 -12
  16. package/dist/ai/ai.service.d.ts.map +1 -1
  17. package/dist/ai/ai.service.js +215 -88
  18. package/dist/ai/ai.service.js.map +1 -1
  19. package/dist/ai/dto/chat.dto.d.ts +4 -1
  20. package/dist/ai/dto/chat.dto.d.ts.map +1 -1
  21. package/dist/ai/dto/chat.dto.js +23 -1
  22. package/dist/ai/dto/chat.dto.js.map +1 -1
  23. package/dist/ai/dto/create-agent.dto.d.ts +1 -1
  24. package/dist/ai/dto/create-agent.dto.d.ts.map +1 -1
  25. package/dist/ai/dto/create-agent.dto.js +1 -1
  26. package/dist/ai/dto/create-agent.dto.js.map +1 -1
  27. package/dist/ai/dto/update-agent.dto.d.ts +1 -1
  28. package/dist/ai/dto/update-agent.dto.d.ts.map +1 -1
  29. package/dist/ai/dto/update-agent.dto.js +1 -1
  30. package/dist/ai/dto/update-agent.dto.js.map +1 -1
  31. package/dist/ai-instruction/ai-instruction.controller.d.ts +61 -7
  32. package/dist/ai-instruction/ai-instruction.controller.d.ts.map +1 -1
  33. package/dist/ai-instruction/ai-instruction.controller.js +63 -20
  34. package/dist/ai-instruction/ai-instruction.controller.js.map +1 -1
  35. package/dist/ai-instruction/ai-instruction.module.d.ts.map +1 -1
  36. package/dist/ai-instruction/ai-instruction.module.js +13 -2
  37. package/dist/ai-instruction/ai-instruction.module.js.map +1 -1
  38. package/dist/ai-instruction/ai-instruction.service.d.ts +131 -6
  39. package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
  40. package/dist/ai-instruction/ai-instruction.service.js +533 -60
  41. package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
  42. package/dist/ai-instruction/ai-prompt-builder.service.d.ts +8 -0
  43. package/dist/ai-instruction/ai-prompt-builder.service.d.ts.map +1 -1
  44. package/dist/ai-instruction/ai-prompt-builder.service.js +10 -1
  45. package/dist/ai-instruction/ai-prompt-builder.service.js.map +1 -1
  46. package/dist/ai-instruction/ai-prompt-registry.d.ts +45 -0
  47. package/dist/ai-instruction/ai-prompt-registry.d.ts.map +1 -0
  48. package/dist/ai-instruction/ai-prompt-registry.js +49 -0
  49. package/dist/ai-instruction/ai-prompt-registry.js.map +1 -0
  50. package/dist/ai-instruction/ai-prompt-resolver.service.d.ts +89 -0
  51. package/dist/ai-instruction/ai-prompt-resolver.service.d.ts.map +1 -0
  52. package/dist/ai-instruction/ai-prompt-resolver.service.js +222 -0
  53. package/dist/ai-instruction/ai-prompt-resolver.service.js.map +1 -0
  54. package/dist/ai-instruction/ai-prompt-template.util.d.ts +70 -0
  55. package/dist/ai-instruction/ai-prompt-template.util.d.ts.map +1 -0
  56. package/dist/ai-instruction/ai-prompt-template.util.js +154 -0
  57. package/dist/ai-instruction/ai-prompt-template.util.js.map +1 -0
  58. package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts +5 -0
  59. package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts.map +1 -1
  60. package/dist/ai-instruction/dto/create-ai-instruction.dto.js +27 -1
  61. package/dist/ai-instruction/dto/create-ai-instruction.dto.js.map +1 -1
  62. package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts +14 -0
  63. package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts.map +1 -0
  64. package/dist/ai-instruction/dto/preview-ai-instruction.dto.js +42 -0
  65. package/dist/ai-instruction/dto/preview-ai-instruction.dto.js.map +1 -0
  66. package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts +11 -0
  67. package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts.map +1 -1
  68. package/dist/ai-instruction/dto/update-ai-instruction.dto.js +34 -0
  69. package/dist/ai-instruction/dto/update-ai-instruction.dto.js.map +1 -1
  70. package/dist/ai-instruction/types/ai-instruction.types.d.ts +13 -1
  71. package/dist/ai-instruction/types/ai-instruction.types.d.ts.map +1 -1
  72. package/dist/ai-instruction/types/ai-instruction.types.js +10 -0
  73. package/dist/ai-instruction/types/ai-instruction.types.js.map +1 -1
  74. package/dist/auth/auth.controller.d.ts +24 -9
  75. package/dist/auth/auth.controller.d.ts.map +1 -1
  76. package/dist/auth/auth.controller.js +49 -21
  77. package/dist/auth/auth.controller.js.map +1 -1
  78. package/dist/auth/auth.service.d.ts +33 -8
  79. package/dist/auth/auth.service.d.ts.map +1 -1
  80. package/dist/auth/auth.service.js +78 -29
  81. package/dist/auth/auth.service.js.map +1 -1
  82. package/dist/captcha/captcha.module.d.ts +3 -0
  83. package/dist/captcha/captcha.module.d.ts.map +1 -0
  84. package/dist/captcha/captcha.module.js +23 -0
  85. package/dist/captcha/captcha.module.js.map +1 -0
  86. package/dist/captcha/captcha.service.d.ts +38 -0
  87. package/dist/captcha/captcha.service.d.ts.map +1 -0
  88. package/dist/captcha/captcha.service.js +144 -0
  89. package/dist/captcha/captcha.service.js.map +1 -0
  90. package/dist/challenge/challenge.service.d.ts +16 -7
  91. package/dist/challenge/challenge.service.d.ts.map +1 -1
  92. package/dist/challenge/challenge.service.js +64 -16
  93. package/dist/challenge/challenge.service.js.map +1 -1
  94. package/dist/core.module.d.ts +3 -1
  95. package/dist/core.module.d.ts.map +1 -1
  96. package/dist/core.module.js +29 -2
  97. package/dist/core.module.js.map +1 -1
  98. package/dist/dashboard/dashboard/dashboard.controller.d.ts +15 -15
  99. package/dist/dashboard/dashboard/dashboard.service.d.ts +15 -15
  100. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +6 -6
  101. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +6 -6
  102. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +20 -20
  103. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +20 -20
  104. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +1 -1
  105. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +1 -1
  106. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +13 -13
  107. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +13 -13
  108. package/dist/file/file.service.d.ts +6 -0
  109. package/dist/file/file.service.d.ts.map +1 -1
  110. package/dist/file/file.service.js +44 -4
  111. package/dist/file/file.service.js.map +1 -1
  112. package/dist/incident/incident-notifier.service.d.ts +36 -0
  113. package/dist/incident/incident-notifier.service.d.ts.map +1 -0
  114. package/dist/incident/incident-notifier.service.js +208 -0
  115. package/dist/incident/incident-notifier.service.js.map +1 -0
  116. package/dist/incident/incident.controller.d.ts +23 -0
  117. package/dist/incident/incident.controller.d.ts.map +1 -0
  118. package/dist/incident/incident.controller.js +75 -0
  119. package/dist/incident/incident.controller.js.map +1 -0
  120. package/dist/incident/incident.module.d.ts +7 -0
  121. package/dist/incident/incident.module.d.ts.map +1 -0
  122. package/dist/incident/incident.module.js +32 -0
  123. package/dist/incident/incident.module.js.map +1 -0
  124. package/dist/incident/incident.service.d.ts +72 -0
  125. package/dist/incident/incident.service.d.ts.map +1 -0
  126. package/dist/incident/incident.service.js +184 -0
  127. package/dist/incident/incident.service.js.map +1 -0
  128. package/dist/index.d.ts +26 -0
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +30 -0
  131. package/dist/index.js.map +1 -1
  132. package/dist/integration-profile/dto/test.dto.d.ts +13 -0
  133. package/dist/integration-profile/dto/test.dto.d.ts.map +1 -0
  134. package/dist/integration-profile/dto/test.dto.js +26 -0
  135. package/dist/integration-profile/dto/test.dto.js.map +1 -0
  136. package/dist/integration-profile/integration-profile.controller.d.ts +12 -1
  137. package/dist/integration-profile/integration-profile.controller.d.ts.map +1 -1
  138. package/dist/integration-profile/integration-profile.controller.js +9 -1
  139. package/dist/integration-profile/integration-profile.controller.js.map +1 -1
  140. package/dist/integration-profile/integration-profile.module.d.ts +6 -1
  141. package/dist/integration-profile/integration-profile.module.d.ts.map +1 -1
  142. package/dist/integration-profile/integration-profile.module.js +26 -3
  143. package/dist/integration-profile/integration-profile.module.js.map +1 -1
  144. package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
  145. package/dist/integration-profile/integration-profile.secrets.js +9 -1
  146. package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
  147. package/dist/integration-profile/integration-profile.service.d.ts +26 -7
  148. package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
  149. package/dist/integration-profile/integration-profile.service.js +94 -91
  150. package/dist/integration-profile/integration-profile.service.js.map +1 -1
  151. package/dist/integration-profile/integration-profile.utils.d.ts +13 -1
  152. package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
  153. package/dist/integration-profile/integration-profile.utils.js +20 -5
  154. package/dist/integration-profile/integration-profile.utils.js.map +1 -1
  155. package/dist/integration-profile/testers/ai.testers.d.ts +3 -0
  156. package/dist/integration-profile/testers/ai.testers.d.ts.map +1 -0
  157. package/dist/integration-profile/testers/ai.testers.js +125 -0
  158. package/dist/integration-profile/testers/ai.testers.js.map +1 -0
  159. package/dist/integration-profile/testers/captcha.testers.d.ts +3 -0
  160. package/dist/integration-profile/testers/captcha.testers.d.ts.map +1 -0
  161. package/dist/integration-profile/testers/captcha.testers.js +121 -0
  162. package/dist/integration-profile/testers/captcha.testers.js.map +1 -0
  163. package/dist/integration-profile/testers/email.testers.d.ts +3 -0
  164. package/dist/integration-profile/testers/email.testers.d.ts.map +1 -0
  165. package/dist/integration-profile/testers/email.testers.js +128 -0
  166. package/dist/integration-profile/testers/email.testers.js.map +1 -0
  167. package/dist/integration-profile/testers/http-probe.d.ts +57 -0
  168. package/dist/integration-profile/testers/http-probe.d.ts.map +1 -0
  169. package/dist/integration-profile/testers/http-probe.js +140 -0
  170. package/dist/integration-profile/testers/http-probe.js.map +1 -0
  171. package/dist/integration-profile/testers/index.d.ts +12 -0
  172. package/dist/integration-profile/testers/index.d.ts.map +1 -0
  173. package/dist/integration-profile/testers/index.js +45 -0
  174. package/dist/integration-profile/testers/index.js.map +1 -0
  175. package/dist/integration-profile/testers/infrastructure.testers.d.ts +3 -0
  176. package/dist/integration-profile/testers/infrastructure.testers.d.ts.map +1 -0
  177. package/dist/integration-profile/testers/infrastructure.testers.js +105 -0
  178. package/dist/integration-profile/testers/infrastructure.testers.js.map +1 -0
  179. package/dist/integration-profile/testers/integration-tester.registry.d.ts +17 -0
  180. package/dist/integration-profile/testers/integration-tester.registry.d.ts.map +1 -0
  181. package/dist/integration-profile/testers/integration-tester.registry.js +52 -0
  182. package/dist/integration-profile/testers/integration-tester.registry.js.map +1 -0
  183. package/dist/integration-profile/testers/integration-tester.types.d.ts +55 -0
  184. package/dist/integration-profile/testers/integration-tester.types.d.ts.map +1 -0
  185. package/dist/integration-profile/testers/integration-tester.types.js +16 -0
  186. package/dist/integration-profile/testers/integration-tester.types.js.map +1 -0
  187. package/dist/integration-profile/testers/messaging.testers.d.ts +3 -0
  188. package/dist/integration-profile/testers/messaging.testers.d.ts.map +1 -0
  189. package/dist/integration-profile/testers/messaging.testers.js +70 -0
  190. package/dist/integration-profile/testers/messaging.testers.js.map +1 -0
  191. package/dist/integration-profile/testers/oauth.testers.d.ts +3 -0
  192. package/dist/integration-profile/testers/oauth.testers.d.ts.map +1 -0
  193. package/dist/integration-profile/testers/oauth.testers.js +285 -0
  194. package/dist/integration-profile/testers/oauth.testers.js.map +1 -0
  195. package/dist/integration-profile/testers/payment.testers.d.ts +3 -0
  196. package/dist/integration-profile/testers/payment.testers.d.ts.map +1 -0
  197. package/dist/integration-profile/testers/payment.testers.js +169 -0
  198. package/dist/integration-profile/testers/payment.testers.js.map +1 -0
  199. package/dist/integration-profile/testers/storage.testers.d.ts +3 -0
  200. package/dist/integration-profile/testers/storage.testers.d.ts.map +1 -0
  201. package/dist/integration-profile/testers/storage.testers.js +208 -0
  202. package/dist/integration-profile/testers/storage.testers.js.map +1 -0
  203. package/dist/language/en.json +4 -2
  204. package/dist/language/pt.json +4 -2
  205. package/dist/leaked-password/leaked-password.controller.d.ts +24 -0
  206. package/dist/leaked-password/leaked-password.controller.d.ts.map +1 -0
  207. package/dist/leaked-password/leaked-password.controller.js +78 -0
  208. package/dist/leaked-password/leaked-password.controller.js.map +1 -0
  209. package/dist/leaked-password/leaked-password.module.d.ts +8 -0
  210. package/dist/leaked-password/leaked-password.module.d.ts.map +1 -0
  211. package/dist/leaked-password/leaked-password.module.js +31 -0
  212. package/dist/leaked-password/leaked-password.module.js.map +1 -0
  213. package/dist/leaked-password/leaked-password.service.d.ts +64 -0
  214. package/dist/leaked-password/leaked-password.service.d.ts.map +1 -0
  215. package/dist/leaked-password/leaked-password.service.js +218 -0
  216. package/dist/leaked-password/leaked-password.service.js.map +1 -0
  217. package/dist/locale/locale.controller.d.ts +1 -1
  218. package/dist/locale/locale.service.d.ts +1 -1
  219. package/dist/mail/dto/preview.dto.d.ts +18 -0
  220. package/dist/mail/dto/preview.dto.d.ts.map +1 -0
  221. package/dist/mail/dto/preview.dto.js +66 -0
  222. package/dist/mail/dto/preview.dto.js.map +1 -0
  223. package/dist/mail/dto/send.dto.d.ts +7 -0
  224. package/dist/mail/dto/send.dto.d.ts.map +1 -1
  225. package/dist/mail/dto/send.dto.js +10 -0
  226. package/dist/mail/dto/send.dto.js.map +1 -1
  227. package/dist/mail/mail.controller.d.ts +4 -0
  228. package/dist/mail/mail.controller.d.ts.map +1 -1
  229. package/dist/mail/mail.controller.js +16 -2
  230. package/dist/mail/mail.controller.js.map +1 -1
  231. package/dist/mail/mail.service.d.ts +23 -2
  232. package/dist/mail/mail.service.d.ts.map +1 -1
  233. package/dist/mail/mail.service.js +102 -13
  234. package/dist/mail/mail.service.js.map +1 -1
  235. package/dist/mail-layout/dto/update.dto.d.ts +17 -0
  236. package/dist/mail-layout/dto/update.dto.d.ts.map +1 -0
  237. package/dist/mail-layout/dto/update.dto.js +27 -0
  238. package/dist/mail-layout/dto/update.dto.js.map +1 -0
  239. package/dist/mail-layout/mail-layout.controller.d.ts +15 -0
  240. package/dist/mail-layout/mail-layout.controller.d.ts.map +1 -0
  241. package/dist/mail-layout/mail-layout.controller.js +71 -0
  242. package/dist/mail-layout/mail-layout.controller.js.map +1 -0
  243. package/dist/mail-layout/mail-layout.module.d.ts +3 -0
  244. package/dist/mail-layout/mail-layout.module.d.ts.map +1 -0
  245. package/dist/mail-layout/mail-layout.module.js +35 -0
  246. package/dist/mail-layout/mail-layout.module.js.map +1 -0
  247. package/dist/mail-layout/mail-layout.service.d.ts +27 -0
  248. package/dist/mail-layout/mail-layout.service.d.ts.map +1 -0
  249. package/dist/mail-layout/mail-layout.service.js +80 -0
  250. package/dist/mail-layout/mail-layout.service.js.map +1 -0
  251. package/dist/mcp-chat/mcp-chat.controller.d.ts +2 -2
  252. package/dist/mcp-chat/mcp-chat.service.d.ts +24 -2
  253. package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
  254. package/dist/mcp-chat/mcp-chat.service.js +80 -24
  255. package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
  256. package/dist/menu/menu.controller.d.ts +3 -3
  257. package/dist/menu/menu.service.d.ts +3 -3
  258. package/dist/notification/notification.controller.d.ts +12 -12
  259. package/dist/notification/notification.service.d.ts +12 -12
  260. package/dist/oauth/oauth-token-broker.service.d.ts +72 -0
  261. package/dist/oauth/oauth-token-broker.service.d.ts.map +1 -0
  262. package/dist/oauth/oauth-token-broker.service.js +258 -0
  263. package/dist/oauth/oauth-token-broker.service.js.map +1 -0
  264. package/dist/oauth/oauth.module.d.ts.map +1 -1
  265. package/dist/oauth/oauth.module.js +3 -1
  266. package/dist/oauth/oauth.module.js.map +1 -1
  267. package/dist/oauth/oauth.service.d.ts +2 -0
  268. package/dist/oauth/oauth.service.d.ts.map +1 -1
  269. package/dist/oauth/oauth.service.js +6 -3
  270. package/dist/oauth/oauth.service.js.map +1 -1
  271. package/dist/pdf/pdf.service.d.ts +8 -0
  272. package/dist/pdf/pdf.service.d.ts.map +1 -1
  273. package/dist/pdf/pdf.service.js +52 -0
  274. package/dist/pdf/pdf.service.js.map +1 -1
  275. package/dist/presence/presence.controller.d.ts +16 -0
  276. package/dist/presence/presence.controller.d.ts.map +1 -0
  277. package/dist/presence/presence.controller.js +60 -0
  278. package/dist/presence/presence.controller.js.map +1 -0
  279. package/dist/presence/presence.listener.d.ts +29 -0
  280. package/dist/presence/presence.listener.d.ts.map +1 -0
  281. package/dist/presence/presence.listener.js +82 -0
  282. package/dist/presence/presence.listener.js.map +1 -0
  283. package/dist/presence/presence.module.d.ts +3 -0
  284. package/dist/presence/presence.module.d.ts.map +1 -0
  285. package/dist/presence/presence.module.js +32 -0
  286. package/dist/presence/presence.module.js.map +1 -0
  287. package/dist/presence/presence.service.d.ts +42 -0
  288. package/dist/presence/presence.service.d.ts.map +1 -0
  289. package/dist/presence/presence.service.js +147 -0
  290. package/dist/presence/presence.service.js.map +1 -0
  291. package/dist/profile/dto/delete-account.dto.d.ts +8 -0
  292. package/dist/profile/dto/delete-account.dto.d.ts.map +1 -0
  293. package/dist/profile/dto/delete-account.dto.js +22 -0
  294. package/dist/profile/dto/delete-account.dto.js.map +1 -0
  295. package/dist/profile/events/profile-account-deleted.event.d.ts +12 -0
  296. package/dist/profile/events/profile-account-deleted.event.d.ts.map +1 -0
  297. package/dist/profile/events/profile-account-deleted.event.js +17 -0
  298. package/dist/profile/events/profile-account-deleted.event.js.map +1 -0
  299. package/dist/profile/profile.controller.d.ts +21 -15
  300. package/dist/profile/profile.controller.d.ts.map +1 -1
  301. package/dist/profile/profile.controller.js +75 -46
  302. package/dist/profile/profile.controller.js.map +1 -1
  303. package/dist/profile/profile.service.d.ts +30 -18
  304. package/dist/profile/profile.service.d.ts.map +1 -1
  305. package/dist/profile/profile.service.js +113 -37
  306. package/dist/profile/profile.service.js.map +1 -1
  307. package/dist/realtime/realtime.gateway.d.ts +48 -0
  308. package/dist/realtime/realtime.gateway.d.ts.map +1 -0
  309. package/dist/realtime/realtime.gateway.js +156 -0
  310. package/dist/realtime/realtime.gateway.js.map +1 -0
  311. package/dist/realtime/realtime.module.d.ts +8 -0
  312. package/dist/realtime/realtime.module.d.ts.map +1 -0
  313. package/dist/realtime/realtime.module.js +29 -0
  314. package/dist/realtime/realtime.module.js.map +1 -0
  315. package/dist/realtime/realtime.service.d.ts +51 -0
  316. package/dist/realtime/realtime.service.d.ts.map +1 -0
  317. package/dist/realtime/realtime.service.js +177 -0
  318. package/dist/realtime/realtime.service.js.map +1 -0
  319. package/dist/redis/redis-pubsub.d.ts +27 -0
  320. package/dist/redis/redis-pubsub.d.ts.map +1 -0
  321. package/dist/redis/redis-pubsub.js +140 -0
  322. package/dist/redis/redis-pubsub.js.map +1 -0
  323. package/dist/role/role.controller.d.ts +3 -3
  324. package/dist/role/role.service.d.ts +3 -3
  325. package/dist/setting/dto/create.dto.d.ts.map +1 -1
  326. package/dist/setting/dto/create.dto.js +9 -2
  327. package/dist/setting/dto/create.dto.js.map +1 -1
  328. package/dist/setting/setting.controller.d.ts +5 -5
  329. package/dist/setting/setting.service.d.ts +8 -5
  330. package/dist/setting/setting.service.d.ts.map +1 -1
  331. package/dist/setting/setting.service.js +25 -1
  332. package/dist/setting/setting.service.js.map +1 -1
  333. package/dist/user/dto/create-with-email-and-password.dto.d.ts +2 -0
  334. package/dist/user/dto/create-with-email-and-password.dto.d.ts.map +1 -1
  335. package/dist/user/dto/create-with-email-and-password.dto.js +5 -0
  336. package/dist/user/dto/create-with-email-and-password.dto.js.map +1 -1
  337. package/dist/user/dto/query-user-mail-list.dto.d.ts +5 -0
  338. package/dist/user/dto/query-user-mail-list.dto.d.ts.map +1 -0
  339. package/dist/user/dto/query-user-mail-list.dto.js +25 -0
  340. package/dist/user/dto/query-user-mail-list.dto.js.map +1 -0
  341. package/dist/user/user-credential.util.d.ts +19 -0
  342. package/dist/user/user-credential.util.d.ts.map +1 -0
  343. package/dist/user/user-credential.util.js +32 -0
  344. package/dist/user/user-credential.util.js.map +1 -0
  345. package/dist/user/user.controller.d.ts +17 -5
  346. package/dist/user/user.controller.d.ts.map +1 -1
  347. package/dist/user/user.controller.js +18 -3
  348. package/dist/user/user.controller.js.map +1 -1
  349. package/dist/user/user.service.d.ts +28 -6
  350. package/dist/user/user.service.d.ts.map +1 -1
  351. package/dist/user/user.service.js +204 -13
  352. package/dist/user/user.service.js.map +1 -1
  353. package/dist/validators/is-strong-password-with-settings.validator.d.ts.map +1 -1
  354. package/dist/validators/is-strong-password-with-settings.validator.js +11 -0
  355. package/dist/validators/is-strong-password-with-settings.validator.js.map +1 -1
  356. package/dist/validators/service-locator.d.ts +9 -0
  357. package/dist/validators/service-locator.d.ts.map +1 -1
  358. package/dist/validators/service-locator.js +12 -0
  359. package/dist/validators/service-locator.js.map +1 -1
  360. package/dist/whatsapp-sender/whatsapp-sender.module.d.ts +3 -0
  361. package/dist/whatsapp-sender/whatsapp-sender.module.d.ts.map +1 -0
  362. package/dist/whatsapp-sender/whatsapp-sender.module.js +23 -0
  363. package/dist/whatsapp-sender/whatsapp-sender.module.js.map +1 -0
  364. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +50 -0
  365. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -0
  366. package/dist/whatsapp-sender/whatsapp-sender.service.js +224 -0
  367. package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -0
  368. package/hedhog/data/integration_provider.yaml +16 -0
  369. package/hedhog/data/mail.yaml +88 -61
  370. package/hedhog/data/mail_layout.yaml +188 -0
  371. package/hedhog/data/menu.yaml +67 -3
  372. package/hedhog/data/route.yaml +135 -0
  373. package/hedhog/data/setting_group.yaml +139 -1
  374. package/hedhog/frontend/app/account/components/mfa-setup-dialog.tsx.ejs +36 -0
  375. package/hedhog/frontend/app/account/components/two-factor-auth.tsx.ejs +2 -0
  376. package/hedhog/frontend/app/account/hooks/use-mfa-setup.ts.ejs +10 -7
  377. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +7 -4
  378. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +580 -0
  379. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-preview.tsx.ejs +150 -0
  380. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +199 -0
  381. package/hedhog/frontend/app/ai_instruction/_components/prompt-diff.tsx.ejs +63 -0
  382. package/hedhog/frontend/app/ai_instruction/_lib/line-diff.spec.ts.ejs +59 -0
  383. package/hedhog/frontend/app/ai_instruction/_lib/line-diff.ts.ejs +72 -0
  384. package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.spec.ts.ejs +170 -0
  385. package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.ts.ejs +167 -0
  386. package/hedhog/frontend/app/ai_instruction/_lib/types.ts.ejs +99 -0
  387. package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +422 -0
  388. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +51 -4
  389. package/hedhog/frontend/app/incidents/page.tsx.ejs +400 -0
  390. package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +153 -84
  391. package/hedhog/frontend/app/mail/layout/page.tsx.ejs +344 -0
  392. package/hedhog/frontend/app/mail/template/page.tsx.ejs +155 -121
  393. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +129 -17
  394. package/hedhog/frontend/app/pages/_components/page-delete-dialog.tsx.ejs +343 -0
  395. package/hedhog/frontend/app/pages/_components/page-detail-sheet.tsx.ejs +438 -0
  396. package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1009 -0
  397. package/hedhog/frontend/app/pages/_components/system-page-types.ts.ejs +56 -0
  398. package/hedhog/frontend/app/pages/_components/use-system-pages.ts.ejs +171 -0
  399. package/hedhog/frontend/app/pages/page.tsx.ejs +514 -0
  400. package/hedhog/frontend/app/users/page.tsx.ejs +119 -13
  401. package/hedhog/frontend/app/users/user-activity-timeline.tsx.ejs +231 -0
  402. package/hedhog/frontend/app/users/user-mails.tsx.ejs +399 -0
  403. package/hedhog/frontend/app/users/user-sheet.tsx.ejs +60 -75
  404. package/hedhog/frontend/messages/en.json +499 -3
  405. package/hedhog/frontend/messages/pt.json +499 -3
  406. package/hedhog/table/ai_agent.yaml +1 -0
  407. package/hedhog/table/ai_instruction.yaml +15 -0
  408. package/hedhog/table/leaked_password.yaml +18 -0
  409. package/hedhog/table/mail_layout.yaml +35 -0
  410. package/hedhog/table/mail_var.yaml +4 -0
  411. package/hedhog/table/setting.yaml +1 -0
  412. package/hedhog/table/system_incident.yaml +59 -0
  413. package/hedhog/table/user_presence.yaml +36 -0
  414. package/package.json +8 -4
  415. package/src/access-log/access-log.interceptor.ts +4 -2
  416. package/src/ai/ai-attachment.fragments.spec.ts +319 -0
  417. package/src/ai/ai-attachment.fragments.ts +35 -0
  418. package/src/ai/ai.prompts.ts +38 -0
  419. package/src/ai/ai.service.spec.ts +280 -0
  420. package/src/ai/ai.service.ts +338 -82
  421. package/src/ai/dto/chat.dto.ts +33 -3
  422. package/src/ai/dto/create-agent.dto.ts +2 -2
  423. package/src/ai/dto/update-agent.dto.ts +2 -2
  424. package/src/ai-instruction/ai-instruction.controller.ts +40 -9
  425. package/src/ai-instruction/ai-instruction.module.ts +13 -2
  426. package/src/ai-instruction/ai-instruction.service.spec.ts +658 -0
  427. package/src/ai-instruction/ai-instruction.service.ts +661 -62
  428. package/src/ai-instruction/ai-prompt-builder.service.ts +10 -1
  429. package/src/ai-instruction/ai-prompt-registry.ts +87 -0
  430. package/src/ai-instruction/ai-prompt-resolver.service.spec.ts +375 -0
  431. package/src/ai-instruction/ai-prompt-resolver.service.ts +295 -0
  432. package/src/ai-instruction/ai-prompt-template.util.spec.ts +162 -0
  433. package/src/ai-instruction/ai-prompt-template.util.ts +199 -0
  434. package/src/ai-instruction/dto/create-ai-instruction.dto.ts +39 -3
  435. package/src/ai-instruction/dto/preview-ai-instruction.dto.ts +26 -0
  436. package/src/ai-instruction/dto/update-ai-instruction.dto.ts +42 -1
  437. package/src/ai-instruction/types/ai-instruction.types.ts +24 -1
  438. package/src/auth/auth.controller.ts +31 -5
  439. package/src/auth/auth.service.spec.ts +3 -1
  440. package/src/auth/auth.service.ts +101 -36
  441. package/src/captcha/captcha.module.ts +10 -0
  442. package/src/captcha/captcha.service.spec.ts +210 -0
  443. package/src/captcha/captcha.service.ts +191 -0
  444. package/src/challenge/challenge.service.spec.ts +39 -4
  445. package/src/challenge/challenge.service.ts +72 -17
  446. package/src/core.module.ts +27 -1
  447. package/src/file/file.service.spec.ts +105 -0
  448. package/src/file/file.service.ts +60 -3
  449. package/src/incident/incident-notifier.service.spec.ts +205 -0
  450. package/src/incident/incident-notifier.service.ts +241 -0
  451. package/src/incident/incident.controller.ts +38 -0
  452. package/src/incident/incident.module.ts +19 -0
  453. package/src/incident/incident.service.spec.ts +150 -0
  454. package/src/incident/incident.service.ts +209 -0
  455. package/src/index.ts +37 -0
  456. package/src/integration-profile/dto/test.dto.ts +19 -0
  457. package/src/integration-profile/integration-profile.controller.ts +10 -1
  458. package/src/integration-profile/integration-profile.module.spec.ts +51 -0
  459. package/src/integration-profile/integration-profile.module.ts +23 -4
  460. package/src/integration-profile/integration-profile.secrets.ts +9 -1
  461. package/src/integration-profile/integration-profile.service.spec.ts +279 -0
  462. package/src/integration-profile/integration-profile.service.ts +120 -124
  463. package/src/integration-profile/integration-profile.utils.spec.ts +22 -0
  464. package/src/integration-profile/integration-profile.utils.ts +40 -3
  465. package/src/integration-profile/testers/ai.testers.ts +165 -0
  466. package/src/integration-profile/testers/captcha.testers.spec.ts +92 -0
  467. package/src/integration-profile/testers/captcha.testers.ts +139 -0
  468. package/src/integration-profile/testers/email.testers.ts +161 -0
  469. package/src/integration-profile/testers/http-probe.spec.ts +153 -0
  470. package/src/integration-profile/testers/http-probe.ts +171 -0
  471. package/src/integration-profile/testers/index.ts +30 -0
  472. package/src/integration-profile/testers/infrastructure.testers.ts +122 -0
  473. package/src/integration-profile/testers/integration-tester.registry.spec.ts +75 -0
  474. package/src/integration-profile/testers/integration-tester.registry.ts +43 -0
  475. package/src/integration-profile/testers/integration-tester.types.ts +61 -0
  476. package/src/integration-profile/testers/messaging.testers.ts +102 -0
  477. package/src/integration-profile/testers/oauth.testers.spec.ts +220 -0
  478. package/src/integration-profile/testers/oauth.testers.ts +305 -0
  479. package/src/integration-profile/testers/payment.testers.ts +185 -0
  480. package/src/integration-profile/testers/remaining.testers.spec.ts +401 -0
  481. package/src/integration-profile/testers/storage.testers.spec.ts +185 -0
  482. package/src/integration-profile/testers/storage.testers.ts +226 -0
  483. package/src/integration-profile/testers/tester-coverage.spec.ts +58 -0
  484. package/src/language/en.json +4 -2
  485. package/src/language/pt.json +4 -2
  486. package/src/leaked-password/README.md +83 -0
  487. package/src/leaked-password/leaked-password.controller.ts +52 -0
  488. package/src/leaked-password/leaked-password.module.ts +18 -0
  489. package/src/leaked-password/leaked-password.service.ts +242 -0
  490. package/src/leaked-password/seed/build-seed-sql.mjs +180 -0
  491. package/src/leaked-password/seed/common-passwords.txt +335 -0
  492. package/src/mail/dto/preview.dto.ts +50 -0
  493. package/src/mail/dto/send.dto.ts +14 -1
  494. package/src/mail/mail-template.spec.ts +197 -0
  495. package/src/mail/mail.controller.ts +9 -2
  496. package/src/mail/mail.service.spec.ts +116 -1
  497. package/src/mail/mail.service.ts +118 -12
  498. package/src/mail-layout/dto/update.dto.ts +19 -0
  499. package/src/mail-layout/mail-layout.controller.ts +47 -0
  500. package/src/mail-layout/mail-layout.module.ts +22 -0
  501. package/src/mail-layout/mail-layout.service.ts +94 -0
  502. package/src/mcp-chat/mcp-chat.service.spec.ts +236 -0
  503. package/src/mcp-chat/mcp-chat.service.ts +122 -26
  504. package/src/oauth/oauth-token-broker.service.spec.ts +172 -0
  505. package/src/oauth/oauth-token-broker.service.ts +363 -0
  506. package/src/oauth/oauth.module.ts +3 -1
  507. package/src/oauth/oauth.service.ts +8 -2
  508. package/src/pdf/pdf.service.ts +75 -0
  509. package/src/presence/presence.controller.ts +29 -0
  510. package/src/presence/presence.listener.ts +53 -0
  511. package/src/presence/presence.module.ts +19 -0
  512. package/src/presence/presence.service.spec.ts +97 -0
  513. package/src/presence/presence.service.ts +160 -0
  514. package/src/profile/dto/delete-account.dto.ts +11 -0
  515. package/src/profile/events/profile-account-deleted.event.ts +13 -0
  516. package/src/profile/profile.controller.ts +46 -34
  517. package/src/profile/profile.service.ts +138 -38
  518. package/src/realtime/realtime.gateway.ts +138 -0
  519. package/src/realtime/realtime.module.ts +16 -0
  520. package/src/realtime/realtime.service.spec.ts +50 -0
  521. package/src/realtime/realtime.service.ts +187 -0
  522. package/src/redis/redis-pubsub.ts +179 -0
  523. package/src/setting/dto/create.dto.ts +13 -2
  524. package/src/setting/setting.service.spec.ts +56 -0
  525. package/src/setting/setting.service.ts +29 -1
  526. package/src/user/dto/create-with-email-and-password.dto.ts +6 -1
  527. package/src/user/dto/query-user-mail-list.dto.ts +10 -0
  528. package/src/user/user-credential.util.ts +35 -0
  529. package/src/user/user.controller.ts +17 -2
  530. package/src/user/user.service.spec.ts +153 -0
  531. package/src/user/user.service.ts +255 -12
  532. package/src/validators/is-strong-password-with-settings.validator.ts +12 -0
  533. package/src/validators/service-locator.ts +15 -0
  534. package/src/whatsapp-sender/whatsapp-sender.module.ts +10 -0
  535. package/src/whatsapp-sender/whatsapp-sender.service.ts +313 -0
@@ -10,6 +10,7 @@ const makeDeps = () => {
10
10
  findMany: jest.fn(),
11
11
  update: jest.fn(),
12
12
  deleteMany: jest.fn(),
13
+ count: jest.fn(),
13
14
  },
14
15
  role: { findUnique: jest.fn(), findMany: jest.fn() },
15
16
  role_user: { findFirst: jest.fn(), create: jest.fn(), delete: jest.fn(), findMany: jest.fn() },
@@ -237,6 +238,158 @@ describe('UserService', () => {
237
238
  });
238
239
  });
239
240
 
241
+ describe('list', () => {
242
+ const makeListService = () => {
243
+ const { service, deps } = makeService();
244
+ deps.prismaService.$transaction.mockResolvedValue([0, 0, 0]);
245
+ deps.paginationService.paginatePrismaModel.mockResolvedValue({
246
+ total: 0,
247
+ data: [],
248
+ });
249
+ return { service, deps };
250
+ };
251
+
252
+ const whereOf = (deps: ReturnType<typeof makeDeps>) =>
253
+ (deps.paginationService.paginatePrismaModel.mock.calls[0][1] as any).where;
254
+
255
+ it('não filtra quando o filtro é ausente ou desconhecido', async () => {
256
+ const { service, deps } = makeListService();
257
+ await service.list({});
258
+ expect(whereOf(deps)).toEqual({});
259
+
260
+ deps.paginationService.paginatePrismaModel.mockClear();
261
+ await service.list({}, 'inexistente');
262
+ expect(whereOf(deps)).toEqual({});
263
+ });
264
+
265
+ it('filtra bloqueados por suspended_until futuro', async () => {
266
+ const { service, deps } = makeListService();
267
+ await service.list({}, 'blocked');
268
+ expect(whereOf(deps).suspended_until.gt).toBeInstanceOf(Date);
269
+ });
270
+
271
+ it('filtra novos pelos últimos 7 dias', async () => {
272
+ const { service, deps } = makeListService();
273
+ await service.list({}, 'new');
274
+ const gte = whereOf(deps).created_at.gte as Date;
275
+ const diffInDays = (Date.now() - gte.getTime()) / (24 * 60 * 60 * 1000);
276
+ expect(Math.round(diffInDays)).toBe(7);
277
+ });
278
+
279
+ it('filtra por credencial de senha com reset pendente', async () => {
280
+ const { service, deps } = makeListService();
281
+ await service.list({}, 'password-reset');
282
+ expect(whereOf(deps)).toEqual({
283
+ user_credential: {
284
+ some: { type: 'password', requires_reset: true, revoked_at: null },
285
+ },
286
+ });
287
+ });
288
+
289
+ it('busca por nome e por qualquer identificador do usuário', async () => {
290
+ const { service, deps } = makeListService();
291
+ await service.list({ search: 'joao@hedhog.com' });
292
+
293
+ expect(whereOf(deps)).toEqual({
294
+ OR: [
295
+ { name: { contains: 'joao@hedhog.com', mode: 'insensitive' } },
296
+ {
297
+ user_identifier: {
298
+ some: {
299
+ value: { contains: 'joao@hedhog.com', mode: 'insensitive' },
300
+ },
301
+ },
302
+ },
303
+ ],
304
+ });
305
+ });
306
+
307
+ it('ignora busca vazia ou só com espaços', async () => {
308
+ const { service, deps } = makeListService();
309
+ await service.list({ search: ' ' });
310
+ expect(whereOf(deps)).toEqual({});
311
+
312
+ deps.paginationService.paginatePrismaModel.mockClear();
313
+ await service.list({ search: '' });
314
+ expect(whereOf(deps)).toEqual({});
315
+ });
316
+
317
+ it('combina busca e filtro com AND', async () => {
318
+ const { service, deps } = makeListService();
319
+ await service.list({ search: 'joao' }, 'blocked');
320
+
321
+ const where = whereOf(deps);
322
+ expect(where.OR).toBeUndefined();
323
+ expect(where.AND).toHaveLength(2);
324
+ expect(where.AND[0].suspended_until.gt).toBeInstanceOf(Date);
325
+ expect(where.AND[1].OR).toHaveLength(2);
326
+ });
327
+
328
+ it('não delega a busca ao searchFields da paginação', async () => {
329
+ const { service, deps } = makeListService();
330
+ await service.list({ search: 'joao' });
331
+
332
+ const options = deps.paginationService.paginatePrismaModel.mock
333
+ .calls[0][1] as any;
334
+ expect(options.searchFields).toBeUndefined();
335
+ });
336
+
337
+ it('deriva requires_password_reset e last_login_at', async () => {
338
+ const { service, deps } = makeListService();
339
+ const lastLogin = new Date('2026-07-01T10:00:00Z');
340
+ deps.paginationService.paginatePrismaModel.mockResolvedValue({
341
+ total: 3,
342
+ data: [
343
+ {
344
+ id: 1,
345
+ user_credential: [
346
+ { type: 'password', requires_reset: true, revoked_at: null },
347
+ ],
348
+ user_activity: [{ action: 'login', created_at: lastLogin }],
349
+ },
350
+ {
351
+ id: 2,
352
+ user_credential: [
353
+ { type: 'password', requires_reset: true, revoked_at: new Date() },
354
+ ],
355
+ user_activity: [],
356
+ },
357
+ { id: 3, user_credential: [], user_activity: [] },
358
+ ],
359
+ });
360
+
361
+ const { paginate } = await service.list({});
362
+
363
+ expect(paginate.total).toBe(3);
364
+ expect(paginate.data.map((u: any) => u.requires_password_reset)).toEqual([
365
+ true,
366
+ false,
367
+ false,
368
+ ]);
369
+ expect(paginate.data.map((u: any) => u.last_login_at)).toEqual([
370
+ lastLogin,
371
+ null,
372
+ null,
373
+ ]);
374
+ });
375
+
376
+ it('traz apenas o último login e credenciais sem hash', async () => {
377
+ const { service, deps } = makeListService();
378
+ await service.list({});
379
+ const { include } = deps.paginationService.paginatePrismaModel.mock
380
+ .calls[0][1] as any;
381
+
382
+ expect(include.user_activity).toEqual({
383
+ where: { action: 'login' },
384
+ orderBy: { created_at: 'desc' },
385
+ take: 1,
386
+ });
387
+ expect(include.user_credential.select.hash).toBeUndefined();
388
+ expect(include.user_credential.select.requires_reset).toBe(true);
389
+ expect(include.user_session.select.hash).toBeUndefined();
390
+ });
391
+ });
392
+
240
393
  describe('listUserActivities', () => {
241
394
  it('mapeia atividades com createdAt ISO', async () => {
242
395
  const { service, deps } = makeService();
@@ -6,6 +6,7 @@ import {
6
6
  BadRequestException,
7
7
  Inject,
8
8
  Injectable,
9
+ Logger,
9
10
  NotFoundException,
10
11
  forwardRef,
11
12
  } from '@nestjs/common';
@@ -20,6 +21,10 @@ import { USER_AVATAR_UPLOAD_DESTINATION } from './constants/user.constants';
20
21
  import { CreateWithEmailAndPasswordDTO } from './dto/create-with-email-and-password.dto';
21
22
  import { ResetPasswordDTO } from './dto/reset-password.dto';
22
23
  import { UpdateDTO } from './dto/update.dto';
24
+ import {
25
+ PENDING_PASSWORD_RESET_WHERE,
26
+ hasPendingPasswordReset,
27
+ } from './user-credential.util';
23
28
 
24
29
  // Constants
25
30
  const IDENTIFIER_TYPE = {
@@ -54,8 +59,6 @@ const USER_SORT_FIELDS = [
54
59
  'updated_at',
55
60
  ] as const;
56
61
 
57
- const USER_SEARCH_FIELDS = ['name'] as const;
58
-
59
62
  type UserChangeLog = user_change_log;
60
63
  type UserChangeLogActor = Prisma.userGetPayload<{
61
64
  select: {
@@ -70,6 +73,8 @@ type UserChangeLogActor = Prisma.userGetPayload<{
70
73
 
71
74
  @Injectable()
72
75
  export class UserService {
76
+ private readonly logger = new Logger(UserService.name);
77
+
73
78
  constructor(
74
79
  @Inject(forwardRef(() => PrismaService))
75
80
  private readonly prismaService: PrismaService,
@@ -154,20 +159,30 @@ export class UserService {
154
159
  // CRUD Operations
155
160
  // ==========================================
156
161
 
157
- async list(paginationParams) {
162
+ async list(paginationParams, filter?: string) {
158
163
  const paginate = await this.paginationService.paginatePrismaModel(
159
164
  this.prismaService.user,
160
165
  {
161
166
  ...paginationParams,
162
167
  validSortFields: USER_SORT_FIELDS,
163
- searchFields: USER_SEARCH_FIELDS,
168
+ where: this.buildUserListWhere(filter, paginationParams?.search),
164
169
  include: this.getUserIncludeClause(),
165
170
  }
166
171
  );
167
172
 
168
173
  const stats = await this.getUserStatistics();
169
174
 
170
- return { paginate, stats };
175
+ return {
176
+ paginate: {
177
+ ...paginate,
178
+ data: (paginate?.data ?? []).map((user: any) => ({
179
+ ...user,
180
+ requires_password_reset: hasPendingPasswordReset(user),
181
+ last_login_at: user?.user_activity?.[0]?.created_at ?? null,
182
+ })),
183
+ },
184
+ stats,
185
+ };
171
186
  }
172
187
 
173
188
  async get(locale: string, userId: number) {
@@ -176,7 +191,7 @@ export class UserService {
176
191
 
177
192
  async createWithEmailAndPassword(
178
193
  locale: string,
179
- { email, name, password }: CreateWithEmailAndPasswordDTO,
194
+ { email, name, password, app }: CreateWithEmailAndPasswordDTO,
180
195
  ) {
181
196
  await this.validateEmailAvailable(locale, email);
182
197
 
@@ -185,7 +200,7 @@ export class UserService {
185
200
  const user = await this.prismaService.$transaction(async (tx) => {
186
201
  const role = await this.getDefaultUserRole(locale, tx);
187
202
 
188
- const user = await tx.user.create({
203
+ const created = await tx.user.create({
189
204
  data: {
190
205
  name,
191
206
  user_identifier: {
@@ -209,10 +224,25 @@ export class UserService {
209
224
  },
210
225
  });
211
226
 
212
- return user;
227
+ return created;
228
+ }).catch((error: any) => {
229
+ if (error?.code === 'P2002') {
230
+ throw new BadRequestException(
231
+ getLocaleText('signup.emailExists', locale, 'Email already in use.')
232
+ );
233
+ }
234
+
235
+ throw error;
213
236
  });
214
237
 
215
- const challenge = await this.challenge.verifyEmail(locale, user.id, email);
238
+ try {
239
+ await this.challenge.verifyEmail(locale, user.id, email, app);
240
+ } catch (error: any) {
241
+ this.logger.warn(
242
+ `Signup confirmation email failed for user ${user.id}: ${error?.message ?? error}`
243
+ );
244
+ }
245
+
216
246
  await this.registerUserActivity(user.id, 'register');
217
247
 
218
248
  await this.integrationApi.publishEvent({
@@ -223,7 +253,7 @@ export class UserService {
223
253
  payload: { id: user.id, name: user.name, email },
224
254
  }).catch(() => null);
225
255
 
226
- return { user, challenge };
256
+ return { user, hasChallenge: true };
227
257
  }
228
258
 
229
259
  async update(
@@ -424,7 +454,10 @@ export class UserService {
424
454
  include: {
425
455
  user_identifier: true,
426
456
  user_credential: true,
427
- user_activity: true,
457
+ user_activity: {
458
+ orderBy: { created_at: 'desc' },
459
+ take: 20,
460
+ },
428
461
  user_session: true,
429
462
  user_account: true,
430
463
  role_user: {
@@ -749,6 +782,139 @@ export class UserService {
749
782
  };
750
783
  }
751
784
 
785
+ // ==========================================
786
+ // Sent Mails (delivery history per user)
787
+ // ==========================================
788
+
789
+ async listUserMails(
790
+ locale: string,
791
+ userId: number,
792
+ params: {
793
+ page?: number;
794
+ pageSize?: number;
795
+ search?: string;
796
+ sortField?: string;
797
+ sortOrder?: 'asc' | 'desc';
798
+ status?: 'all' | 'received' | 'read' | 'error';
799
+ },
800
+ ) {
801
+ await this.validateUserExists(locale, userId);
802
+
803
+ const identifiers = await this.prismaService.user_identifier.findMany({
804
+ where: { user_id: userId, type: IDENTIFIER_TYPE.EMAIL },
805
+ select: { value: true },
806
+ });
807
+
808
+ const emails = [
809
+ ...new Set(
810
+ identifiers
811
+ .map((identifier) => identifier.value?.trim().toLowerCase())
812
+ .filter((value): value is string => Boolean(value)),
813
+ ),
814
+ ];
815
+
816
+ // Tracked deliveries plus a fallback over the raw recipient fields, so
817
+ // mails sent before the tracking table existed still show up here.
818
+ const OR: any[] = [{ mail_sent_user: { some: { user_id: userId } } }];
819
+
820
+ for (const email of emails) {
821
+ OR.push({ to: { contains: email, mode: 'insensitive' } });
822
+ OR.push({ cc: { contains: email, mode: 'insensitive' } });
823
+ OR.push({ bcc: { contains: email, mode: 'insensitive' } });
824
+ }
825
+
826
+ const AND: any[] = [];
827
+
828
+ const status = params?.status;
829
+ if (status && status !== 'all') {
830
+ AND.push({ mail_sent_user: { some: { user_id: userId, status } } });
831
+ }
832
+
833
+ const search = params?.search?.trim();
834
+ if (search) {
835
+ AND.push({ subject: { contains: search, mode: 'insensitive' } });
836
+ }
837
+
838
+ const paginated = await this.paginationService.paginatePrismaModel(
839
+ this.prismaService.mail_sent,
840
+ {
841
+ page: params?.page,
842
+ pageSize: params?.pageSize,
843
+ sortField: params?.sortField || 'created_at',
844
+ sortOrder: params?.sortOrder || 'desc',
845
+ validSortFields: ['id', 'created_at', 'subject'],
846
+ where: {
847
+ OR,
848
+ ...(AND.length > 0 ? { AND } : {}),
849
+ },
850
+ include: {
851
+ mail: { select: { id: true, slug: true } },
852
+ mail_sent_user: {
853
+ where: { user_id: userId },
854
+ select: {
855
+ id: true,
856
+ recipient_email: true,
857
+ status: true,
858
+ read_at: true,
859
+ error_code: true,
860
+ error_message: true,
861
+ },
862
+ },
863
+ },
864
+ },
865
+ );
866
+
867
+ // `total` conta o mesmo universo da lista (rastreados + fallback), para o
868
+ // KPI não divergir da quantidade de itens exibidos. Os demais contadores só
869
+ // existem para envios rastreados.
870
+ const [totalMails, grouped] = await Promise.all([
871
+ this.prismaService.mail_sent.count({ where: { OR } }),
872
+ this.prismaService.mail_sent_user.groupBy({
873
+ by: ['status'],
874
+ where: { user_id: userId },
875
+ _count: { _all: true },
876
+ }),
877
+ ]);
878
+
879
+ const stats = grouped.reduce(
880
+ (acc, group) => {
881
+ const count = group._count?._all ?? 0;
882
+ if (group.status === 'received') acc.received += count;
883
+ if (group.status === 'read') acc.read += count;
884
+ if (group.status === 'error') acc.error += count;
885
+ return acc;
886
+ },
887
+ { total: totalMails, received: 0, read: 0, error: 0 },
888
+ );
889
+
890
+ return {
891
+ ...paginated,
892
+ stats,
893
+ data: (paginated.data || []).map((mailSent: any) => {
894
+ const tracking = mailSent.mail_sent_user?.[0] ?? null;
895
+
896
+ return {
897
+ id: mailSent.id,
898
+ mailId: mailSent.mail_id,
899
+ mailSlug: mailSent.mail?.slug ?? null,
900
+ subject: mailSent.subject,
901
+ from: mailSent.from,
902
+ to: mailSent.to,
903
+ cc: mailSent.cc,
904
+ bcc: mailSent.bcc,
905
+ body: mailSent.body,
906
+ createdAt: mailSent.created_at?.toISOString?.() || null,
907
+ tracked: Boolean(tracking),
908
+ recipientEmail: tracking?.recipient_email ?? null,
909
+ status: tracking?.status ?? null,
910
+ readAt: tracking?.read_at?.toISOString?.() || null,
911
+ errorCode: tracking?.error_code ?? null,
912
+ errorMessage: tracking?.error_message ?? null,
913
+ };
914
+ }),
915
+ };
916
+ }
917
+
752
918
  async listUserActivities(locale: string, userId: number, paginationParams) {
753
919
  await this.validateUserExists(locale, userId);
754
920
 
@@ -859,10 +1025,74 @@ export class UserService {
859
1025
  return passwordChars.slice(0, length).join('');
860
1026
  }
861
1027
 
1028
+ private buildUserFilterWhere(filter?: string) {
1029
+ switch (filter) {
1030
+ case 'new':
1031
+ return {
1032
+ created_at: {
1033
+ gte: new Date(Date.now() - NEW_USERS_PERIOD_DAYS * DAYS_IN_MS),
1034
+ },
1035
+ };
1036
+ case 'blocked':
1037
+ return { suspended_until: { gt: new Date() } };
1038
+ case 'password-reset':
1039
+ return { user_credential: PENDING_PASSWORD_RESET_WHERE };
1040
+ default:
1041
+ return {};
1042
+ }
1043
+ }
1044
+
1045
+ // O e-mail não é coluna de `user`: mora em `user_identifier`, junto de
1046
+ // username, telefone e cpf. Por isso a busca é montada aqui, e não via
1047
+ // `searchFields` da paginação, que só sabe filtrar colunas escalares.
1048
+ private buildUserSearchWhere(search?: string) {
1049
+ const term = typeof search === 'string' ? search.trim() : '';
1050
+
1051
+ if (!term) {
1052
+ return null;
1053
+ }
1054
+
1055
+ return {
1056
+ OR: [
1057
+ { name: { contains: term, mode: 'insensitive' as const } },
1058
+ {
1059
+ user_identifier: {
1060
+ some: { value: { contains: term, mode: 'insensitive' as const } },
1061
+ },
1062
+ },
1063
+ ],
1064
+ };
1065
+ }
1066
+
1067
+ private buildUserListWhere(filter?: string, search?: string) {
1068
+ const filterWhere = this.buildUserFilterWhere(filter);
1069
+ const searchWhere = this.buildUserSearchWhere(search);
1070
+
1071
+ if (!searchWhere) {
1072
+ return filterWhere;
1073
+ }
1074
+
1075
+ if (!Object.keys(filterWhere).length) {
1076
+ return searchWhere;
1077
+ }
1078
+
1079
+ return { AND: [filterWhere, searchWhere] };
1080
+ }
1081
+
862
1082
  private getUserIncludeClause() {
863
1083
  return {
864
1084
  user_account: true,
865
- user_credential: true,
1085
+ user_credential: {
1086
+ select: {
1087
+ id: true,
1088
+ type: true,
1089
+ requires_reset: true,
1090
+ revoked_at: true,
1091
+ expires_at: true,
1092
+ created_at: true,
1093
+ updated_at: true,
1094
+ },
1095
+ },
866
1096
  user_identifier: {
867
1097
  where: { enabled: true },
868
1098
  },
@@ -870,9 +1100,22 @@ export class UserService {
870
1100
  where: { verified_at: { not: null } },
871
1101
  },
872
1102
  user_activity: {
1103
+ where: { action: 'login' },
873
1104
  orderBy: { created_at: 'desc' },
1105
+ take: 1,
874
1106
  },
875
1107
  user_session: {
1108
+ select: {
1109
+ id: true,
1110
+ user_id: true,
1111
+ ip_address: true,
1112
+ user_agent: true,
1113
+ browser_id: true,
1114
+ revoked_at: true,
1115
+ expires_at: true,
1116
+ created_at: true,
1117
+ updated_at: true,
1118
+ },
876
1119
  where: {
877
1120
  revoked_at: null,
878
1121
  expires_at: { gt: new Date() },
@@ -68,6 +68,18 @@ export class IsStrongPasswordWithSettingsConstraint
68
68
  return false;
69
69
  }
70
70
 
71
+ // Senha vazada por ultimo: e a checagem mais cara (bate no banco) e nao faz
72
+ // sentido pagar por ela se a senha ja falhou na politica. Aqui a senha em
73
+ // claro passa pelo servidor de qualquer forma; a do cofre nunca passa, e por
74
+ // isso o cofre usa o bloom filter no cliente em vez deste caminho.
75
+ if (this.settings.setting['password-block-leaked'] !== false) {
76
+ const leakedService = ValidatorServiceLocator.getLeakedPasswordService();
77
+ if (leakedService && (await leakedService.isLeaked(password))) {
78
+ this.failedRule = 'password.leaked';
79
+ return false;
80
+ }
81
+ }
82
+
71
83
  return true;
72
84
  } catch (error) {
73
85
  console.warn('[IsStrongPasswordWithSettingsConstraint] Error getting SettingService:', error);
@@ -1,3 +1,4 @@
1
+ import { LeakedPasswordService } from '../leaked-password/leaked-password.service';
1
2
  import { SettingService } from '../setting/setting.service';
2
3
 
3
4
  /**
@@ -6,6 +7,7 @@ import { SettingService } from '../setting/setting.service';
6
7
  */
7
8
  export class ValidatorServiceLocator {
8
9
  private static settingService: SettingService;
10
+ private static leakedPasswordService: LeakedPasswordService;
9
11
 
10
12
  static setSettingService(service: SettingService): void {
11
13
  this.settingService = service;
@@ -17,4 +19,17 @@ export class ValidatorServiceLocator {
17
19
  }
18
20
  return this.settingService;
19
21
  }
22
+
23
+ static setLeakedPasswordService(service: LeakedPasswordService): void {
24
+ this.leakedPasswordService = service;
25
+ }
26
+
27
+ /**
28
+ * Diferente do SettingService, devolve null em vez de lançar: a checagem de
29
+ * senha vazada é uma camada extra, e um bootstrap sem ela deve deixar a
30
+ * validação de política seguir funcionando.
31
+ */
32
+ static getLeakedPasswordService(): LeakedPasswordService | null {
33
+ return this.leakedPasswordService ?? null;
34
+ }
20
35
  }
@@ -0,0 +1,10 @@
1
+ import { PrismaModule } from '@hed-hog/api-prisma';
2
+ import { forwardRef, Module } from '@nestjs/common';
3
+ import { WhatsappSenderService } from './whatsapp-sender.service';
4
+
5
+ @Module({
6
+ imports: [forwardRef(() => PrismaModule)],
7
+ providers: [WhatsappSenderService],
8
+ exports: [WhatsappSenderService],
9
+ })
10
+ export class WhatsappSenderModule {}