@hed-hog/core 0.0.386 → 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 (556) 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 +26 -10
  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 +35 -9
  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 +27 -0
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +31 -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 +12 -2
  146. package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
  147. package/dist/integration-profile/integration-profile.service.d.ts +28 -2
  148. package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
  149. package/dist/integration-profile/integration-profile.service.js +105 -31
  150. package/dist/integration-profile/integration-profile.service.js.map +1 -1
  151. package/dist/integration-profile/integration-profile.utils.d.ts +31 -1
  152. package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
  153. package/dist/integration-profile/integration-profile.utils.js +35 -4
  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 +24 -17
  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 +34 -21
  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/webhook-integration/webhook-integration.controller.d.ts +5 -8
  361. package/dist/webhook-integration/webhook-integration.controller.d.ts.map +1 -1
  362. package/dist/webhook-integration/webhook-integration.controller.js +31 -8
  363. package/dist/webhook-integration/webhook-integration.controller.js.map +1 -1
  364. package/dist/webhook-integration/webhook-integration.module.d.ts.map +1 -1
  365. package/dist/webhook-integration/webhook-integration.module.js +5 -0
  366. package/dist/webhook-integration/webhook-integration.module.js.map +1 -1
  367. package/dist/webhook-integration/webhook-integration.service.d.ts +33 -1
  368. package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -1
  369. package/dist/webhook-integration/webhook-integration.service.js +109 -4
  370. package/dist/webhook-integration/webhook-integration.service.js.map +1 -1
  371. package/dist/webhook-integration/webhook-protocol.registry.d.ts +63 -0
  372. package/dist/webhook-integration/webhook-protocol.registry.d.ts.map +1 -0
  373. package/dist/webhook-integration/webhook-protocol.registry.js +51 -0
  374. package/dist/webhook-integration/webhook-protocol.registry.js.map +1 -0
  375. package/dist/whatsapp-sender/whatsapp-sender.module.d.ts +3 -0
  376. package/dist/whatsapp-sender/whatsapp-sender.module.d.ts.map +1 -0
  377. package/dist/whatsapp-sender/whatsapp-sender.module.js +23 -0
  378. package/dist/whatsapp-sender/whatsapp-sender.module.js.map +1 -0
  379. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +50 -0
  380. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -0
  381. package/dist/whatsapp-sender/whatsapp-sender.service.js +224 -0
  382. package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -0
  383. package/hedhog/data/integration_provider.yaml +16 -0
  384. package/hedhog/data/mail.yaml +88 -61
  385. package/hedhog/data/mail_layout.yaml +188 -0
  386. package/hedhog/data/menu.yaml +67 -3
  387. package/hedhog/data/route.yaml +135 -0
  388. package/hedhog/data/setting_group.yaml +139 -1
  389. package/hedhog/frontend/app/account/components/mfa-setup-dialog.tsx.ejs +36 -0
  390. package/hedhog/frontend/app/account/components/two-factor-auth.tsx.ejs +2 -0
  391. package/hedhog/frontend/app/account/hooks/use-mfa-setup.ts.ejs +10 -7
  392. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +7 -4
  393. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +580 -0
  394. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-preview.tsx.ejs +150 -0
  395. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +199 -0
  396. package/hedhog/frontend/app/ai_instruction/_components/prompt-diff.tsx.ejs +63 -0
  397. package/hedhog/frontend/app/ai_instruction/_lib/line-diff.spec.ts.ejs +59 -0
  398. package/hedhog/frontend/app/ai_instruction/_lib/line-diff.ts.ejs +72 -0
  399. package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.spec.ts.ejs +170 -0
  400. package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.ts.ejs +167 -0
  401. package/hedhog/frontend/app/ai_instruction/_lib/types.ts.ejs +99 -0
  402. package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +422 -0
  403. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +51 -4
  404. package/hedhog/frontend/app/incidents/page.tsx.ejs +400 -0
  405. package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +169 -92
  406. package/hedhog/frontend/app/mail/layout/page.tsx.ejs +344 -0
  407. package/hedhog/frontend/app/mail/template/page.tsx.ejs +155 -121
  408. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +129 -17
  409. package/hedhog/frontend/app/pages/_components/page-delete-dialog.tsx.ejs +343 -0
  410. package/hedhog/frontend/app/pages/_components/page-detail-sheet.tsx.ejs +438 -0
  411. package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1009 -0
  412. package/hedhog/frontend/app/pages/_components/system-page-types.ts.ejs +56 -0
  413. package/hedhog/frontend/app/pages/_components/use-system-pages.ts.ejs +171 -0
  414. package/hedhog/frontend/app/pages/page.tsx.ejs +514 -0
  415. package/hedhog/frontend/app/users/page.tsx.ejs +119 -13
  416. package/hedhog/frontend/app/users/user-activity-timeline.tsx.ejs +231 -0
  417. package/hedhog/frontend/app/users/user-mails.tsx.ejs +399 -0
  418. package/hedhog/frontend/app/users/user-sheet.tsx.ejs +60 -75
  419. package/hedhog/frontend/messages/en.json +521 -3
  420. package/hedhog/frontend/messages/pt.json +521 -3
  421. package/hedhog/table/ai_agent.yaml +1 -0
  422. package/hedhog/table/ai_instruction.yaml +15 -0
  423. package/hedhog/table/leaked_password.yaml +18 -0
  424. package/hedhog/table/mail_layout.yaml +35 -0
  425. package/hedhog/table/mail_var.yaml +4 -0
  426. package/hedhog/table/setting.yaml +1 -0
  427. package/hedhog/table/system_incident.yaml +59 -0
  428. package/hedhog/table/user_presence.yaml +36 -0
  429. package/hedhog/table/webhook_integration.yaml +64 -43
  430. package/package.json +8 -4
  431. package/src/access-log/access-log.interceptor.ts +4 -2
  432. package/src/ai/ai-attachment.fragments.spec.ts +319 -0
  433. package/src/ai/ai-attachment.fragments.ts +35 -0
  434. package/src/ai/ai.prompts.ts +38 -0
  435. package/src/ai/ai.service.spec.ts +280 -0
  436. package/src/ai/ai.service.ts +338 -82
  437. package/src/ai/dto/chat.dto.ts +33 -3
  438. package/src/ai/dto/create-agent.dto.ts +2 -2
  439. package/src/ai/dto/update-agent.dto.ts +2 -2
  440. package/src/ai-instruction/ai-instruction.controller.ts +40 -9
  441. package/src/ai-instruction/ai-instruction.module.ts +13 -2
  442. package/src/ai-instruction/ai-instruction.service.spec.ts +658 -0
  443. package/src/ai-instruction/ai-instruction.service.ts +661 -62
  444. package/src/ai-instruction/ai-prompt-builder.service.ts +10 -1
  445. package/src/ai-instruction/ai-prompt-registry.ts +87 -0
  446. package/src/ai-instruction/ai-prompt-resolver.service.spec.ts +375 -0
  447. package/src/ai-instruction/ai-prompt-resolver.service.ts +295 -0
  448. package/src/ai-instruction/ai-prompt-template.util.spec.ts +162 -0
  449. package/src/ai-instruction/ai-prompt-template.util.ts +199 -0
  450. package/src/ai-instruction/dto/create-ai-instruction.dto.ts +39 -3
  451. package/src/ai-instruction/dto/preview-ai-instruction.dto.ts +26 -0
  452. package/src/ai-instruction/dto/update-ai-instruction.dto.ts +42 -1
  453. package/src/ai-instruction/types/ai-instruction.types.ts +24 -1
  454. package/src/auth/auth.controller.ts +33 -6
  455. package/src/auth/auth.service.spec.ts +3 -1
  456. package/src/auth/auth.service.ts +103 -37
  457. package/src/captcha/captcha.module.ts +10 -0
  458. package/src/captcha/captcha.service.spec.ts +210 -0
  459. package/src/captcha/captcha.service.ts +191 -0
  460. package/src/challenge/challenge.service.spec.ts +39 -4
  461. package/src/challenge/challenge.service.ts +72 -17
  462. package/src/core.module.ts +27 -1
  463. package/src/file/file.service.spec.ts +105 -0
  464. package/src/file/file.service.ts +60 -3
  465. package/src/incident/incident-notifier.service.spec.ts +205 -0
  466. package/src/incident/incident-notifier.service.ts +241 -0
  467. package/src/incident/incident.controller.ts +38 -0
  468. package/src/incident/incident.module.ts +19 -0
  469. package/src/incident/incident.service.spec.ts +150 -0
  470. package/src/incident/incident.service.ts +209 -0
  471. package/src/index.ts +38 -0
  472. package/src/integration-profile/dto/test.dto.ts +19 -0
  473. package/src/integration-profile/integration-profile.controller.ts +10 -1
  474. package/src/integration-profile/integration-profile.module.spec.ts +51 -0
  475. package/src/integration-profile/integration-profile.module.ts +23 -4
  476. package/src/integration-profile/integration-profile.secrets.ts +12 -2
  477. package/src/integration-profile/integration-profile.service.spec.ts +279 -0
  478. package/src/integration-profile/integration-profile.service.ts +132 -29
  479. package/src/integration-profile/integration-profile.utils.spec.ts +97 -0
  480. package/src/integration-profile/integration-profile.utils.ts +79 -3
  481. package/src/integration-profile/testers/ai.testers.ts +165 -0
  482. package/src/integration-profile/testers/captcha.testers.spec.ts +92 -0
  483. package/src/integration-profile/testers/captcha.testers.ts +139 -0
  484. package/src/integration-profile/testers/email.testers.ts +161 -0
  485. package/src/integration-profile/testers/http-probe.spec.ts +153 -0
  486. package/src/integration-profile/testers/http-probe.ts +171 -0
  487. package/src/integration-profile/testers/index.ts +30 -0
  488. package/src/integration-profile/testers/infrastructure.testers.ts +122 -0
  489. package/src/integration-profile/testers/integration-tester.registry.spec.ts +75 -0
  490. package/src/integration-profile/testers/integration-tester.registry.ts +43 -0
  491. package/src/integration-profile/testers/integration-tester.types.ts +61 -0
  492. package/src/integration-profile/testers/messaging.testers.ts +102 -0
  493. package/src/integration-profile/testers/oauth.testers.spec.ts +220 -0
  494. package/src/integration-profile/testers/oauth.testers.ts +305 -0
  495. package/src/integration-profile/testers/payment.testers.ts +185 -0
  496. package/src/integration-profile/testers/remaining.testers.spec.ts +401 -0
  497. package/src/integration-profile/testers/storage.testers.spec.ts +185 -0
  498. package/src/integration-profile/testers/storage.testers.ts +226 -0
  499. package/src/integration-profile/testers/tester-coverage.spec.ts +58 -0
  500. package/src/language/en.json +4 -2
  501. package/src/language/pt.json +4 -2
  502. package/src/leaked-password/README.md +83 -0
  503. package/src/leaked-password/leaked-password.controller.ts +52 -0
  504. package/src/leaked-password/leaked-password.module.ts +18 -0
  505. package/src/leaked-password/leaked-password.service.ts +242 -0
  506. package/src/leaked-password/seed/build-seed-sql.mjs +180 -0
  507. package/src/leaked-password/seed/common-passwords.txt +335 -0
  508. package/src/mail/dto/preview.dto.ts +50 -0
  509. package/src/mail/dto/send.dto.ts +14 -1
  510. package/src/mail/mail-template.spec.ts +197 -0
  511. package/src/mail/mail.controller.ts +9 -2
  512. package/src/mail/mail.service.spec.ts +116 -1
  513. package/src/mail/mail.service.ts +118 -12
  514. package/src/mail-layout/dto/update.dto.ts +19 -0
  515. package/src/mail-layout/mail-layout.controller.ts +47 -0
  516. package/src/mail-layout/mail-layout.module.ts +22 -0
  517. package/src/mail-layout/mail-layout.service.ts +94 -0
  518. package/src/mcp-chat/mcp-chat.service.spec.ts +236 -0
  519. package/src/mcp-chat/mcp-chat.service.ts +122 -26
  520. package/src/oauth/oauth-token-broker.service.spec.ts +172 -0
  521. package/src/oauth/oauth-token-broker.service.ts +363 -0
  522. package/src/oauth/oauth.module.ts +3 -1
  523. package/src/oauth/oauth.service.ts +8 -2
  524. package/src/pdf/pdf.service.ts +75 -0
  525. package/src/presence/presence.controller.ts +29 -0
  526. package/src/presence/presence.listener.ts +53 -0
  527. package/src/presence/presence.module.ts +19 -0
  528. package/src/presence/presence.service.spec.ts +97 -0
  529. package/src/presence/presence.service.ts +160 -0
  530. package/src/profile/dto/delete-account.dto.ts +11 -0
  531. package/src/profile/events/profile-account-deleted.event.ts +13 -0
  532. package/src/profile/profile.controller.ts +52 -36
  533. package/src/profile/profile.service.ts +143 -41
  534. package/src/realtime/realtime.gateway.ts +138 -0
  535. package/src/realtime/realtime.module.ts +16 -0
  536. package/src/realtime/realtime.service.spec.ts +50 -0
  537. package/src/realtime/realtime.service.ts +187 -0
  538. package/src/redis/redis-pubsub.ts +179 -0
  539. package/src/setting/dto/create.dto.ts +13 -2
  540. package/src/setting/setting.service.spec.ts +56 -0
  541. package/src/setting/setting.service.ts +29 -1
  542. package/src/user/dto/create-with-email-and-password.dto.ts +6 -1
  543. package/src/user/dto/query-user-mail-list.dto.ts +10 -0
  544. package/src/user/user-credential.util.ts +35 -0
  545. package/src/user/user.controller.ts +17 -2
  546. package/src/user/user.service.spec.ts +153 -0
  547. package/src/user/user.service.ts +255 -12
  548. package/src/validators/is-strong-password-with-settings.validator.ts +12 -0
  549. package/src/validators/service-locator.ts +15 -0
  550. package/src/webhook-integration/webhook-integration.controller.ts +40 -2
  551. package/src/webhook-integration/webhook-integration.module.ts +5 -0
  552. package/src/webhook-integration/webhook-integration.service.ts +133 -0
  553. package/src/webhook-integration/webhook-protocol.registry.spec.ts +70 -0
  554. package/src/webhook-integration/webhook-protocol.registry.ts +93 -0
  555. package/src/whatsapp-sender/whatsapp-sender.module.ts +10 -0
  556. 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
  }
@@ -15,6 +15,7 @@ import {
15
15
  Res,
16
16
  } from '@nestjs/common';
17
17
  import { Request, Response } from 'express';
18
+ import { WebhookProtocolResponse } from './webhook-protocol.registry';
18
19
  import { WebhookIntegrationService } from './webhook-integration.service';
19
20
  import {
20
21
  CreateWebhookActionDTO,
@@ -145,12 +146,24 @@ export class PublicWebhookController {
145
146
  constructor(private readonly service: WebhookIntegrationService) {}
146
147
 
147
148
  @Post(':uuid')
148
- execute(
149
+ async execute(
149
150
  @Param('uuid') uuid: string,
150
151
  @Body() body: any,
152
+ @Query() query: any,
151
153
  @Headers() headers: any,
152
154
  @Req() req: Request,
155
+ @Res({ passthrough: true }) res: Response,
153
156
  ) {
157
+ const handled = await this.service.executeProtocol(
158
+ uuid,
159
+ 'POST',
160
+ body,
161
+ query,
162
+ headers,
163
+ req,
164
+ );
165
+ if (handled) return sendProtocolResponse(res, handled);
166
+
154
167
  return this.service.executePublic(uuid, body, headers, req);
155
168
  }
156
169
 
@@ -158,15 +171,40 @@ export class PublicWebhookController {
158
171
  * GET variant so a webhook can be triggered by a plain clickable link (e.g.
159
172
  * approve/reject links sent by email/WhatsApp). Query params are used as the
160
173
  * payload for action templates (`{{body.decision}}` ← `?decision=approve`).
174
+ *
175
+ * Webhooks with a protocol take a different path: for them a GET is the
176
+ * provider's verification handshake, not a trigger — it must not run actions.
161
177
  */
162
178
  @Get(':uuid')
163
- executeGet(
179
+ async executeGet(
164
180
  @Param('uuid') uuid: string,
165
181
  @Query() query: any,
166
182
  @Headers() headers: any,
167
183
  @Req() req: Request,
184
+ @Res({ passthrough: true }) res: Response,
168
185
  ) {
186
+ const handled = await this.service.executeProtocol(
187
+ uuid,
188
+ 'GET',
189
+ query ?? {},
190
+ query,
191
+ headers,
192
+ req,
193
+ );
194
+ if (handled) return sendProtocolResponse(res, handled);
195
+
169
196
  return this.service.executePublic(uuid, query ?? {}, headers, req);
170
197
  }
171
198
  }
172
199
 
200
+ /**
201
+ * Aplica status/content-type que o adaptador pediu. Devolver a string crua importa:
202
+ * provedores como a Meta comparam o corpo da resposta literalmente, então um
203
+ * envelope JSON reprovaria a verificação.
204
+ */
205
+ function sendProtocolResponse(res: Response, result: WebhookProtocolResponse) {
206
+ res.status(result.status);
207
+ if (result.contentType) res.type(result.contentType);
208
+ return result.body;
209
+ }
210
+
@@ -16,6 +16,7 @@ import {
16
16
  WebhookIntegrationController,
17
17
  } from './webhook-integration.controller';
18
18
  import { WebhookIntegrationService } from './webhook-integration.service';
19
+ import { WebhookProtocolRegistry } from './webhook-protocol.registry';
19
20
 
20
21
  @Module({
21
22
  imports: [
@@ -38,12 +39,16 @@ import { WebhookIntegrationService } from './webhook-integration.service';
38
39
  IntegrationEventCatalogService,
39
40
  WebhookIntegrationService,
40
41
  EventWebhookService,
42
+ WebhookProtocolRegistry,
41
43
  ],
42
44
  exports: [
43
45
  IntegrationEventCatalogService,
44
46
  AppCommandModule,
45
47
  WebhookIntegrationService,
46
48
  EventWebhookService,
49
+ // Exportado para que outros módulos registrem protocolos de entrada
50
+ // (ex.: a library whatsapp registra o protocolo da Meta).
51
+ WebhookProtocolRegistry,
47
52
  ],
48
53
  })
49
54
  export class WebhookIntegrationModule {}