@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
@@ -1,10 +1,12 @@
1
1
  import { getLocaleText } from '@hed-hog/api-locale';
2
- import { PrismaService, user } from '@hed-hog/api-prisma';
2
+ import { PrismaService } from '@hed-hog/api-prisma';
3
3
  import { User } from '@hed-hog/api-types';
4
4
  import { BadRequestException, forwardRef, Inject, Injectable, NotFoundException } from '@nestjs/common';
5
5
  import { EventEmitter2 } from '@nestjs/event-emitter';
6
6
  import { JwtService } from '@nestjs/jwt';
7
7
  import type {
8
+ PublicKeyCredentialCreationOptionsJSON,
9
+ PublicKeyCredentialRequestOptionsJSON,
8
10
  VerifiedAuthenticationResponse,
9
11
  VerifiedRegistrationResponse,
10
12
  } from '@simplewebauthn/server';
@@ -25,10 +27,12 @@ import { UserService } from '../user/user.service';
25
27
  import { resolveWebAuthnOrigin } from '../utils/webauthn-origin';
26
28
  import { ChangeEmailDto } from './dto/change-email.dto';
27
29
  import { ChangePasswordDto } from './dto/change-password.dto';
30
+ import { DeleteAccountDto } from './dto/delete-account.dto';
28
31
  import { EmailVerificationDto } from './dto/email-verification-confirm.dto';
29
32
  import { SendEmailVerificationDto } from './dto/send-email-verification.dto';
30
33
  import { SetPreferencesDto } from './dto/set-preferences.dto';
31
34
  import { UpdateDto } from './dto/update.dto';
35
+ import { PROFILE_ACCOUNT_DELETED, ProfileAccountDeletedEvent } from './events/profile-account-deleted.event';
32
36
  import { PROFILE_AVATAR_UPDATED, ProfileAvatarUpdatedEvent } from './events/profile-avatar-updated.event';
33
37
  import { PROFILE_EMAIL_CHANGED, ProfileEmailChangedEvent } from './events/profile-email-changed.event';
34
38
  import { PROFILE_UPDATED, ProfileUpdatedEvent } from './events/profile-updated.event';
@@ -52,7 +56,7 @@ export class ProfileService {
52
56
  private readonly eventEmitter: EventEmitter2,
53
57
  ) {}
54
58
 
55
- async changeEmail(locale: string, userId: number, { email, password, pin }: ChangeEmailDto) {
59
+ async changeEmail(locale: string, userId: number, { email, password, pin }: ChangeEmailDto, origin?: string) {
56
60
 
57
61
  const checkAlreadyExists = await this.prisma.user_identifier.findFirst({
58
62
  where: { type: 'email', value: email, enabled: true, verified_at: { not: null } },
@@ -125,7 +129,7 @@ export class ProfileService {
125
129
  });
126
130
 
127
131
  // Create verification challenge for the new email
128
- await this.challenge.verifyEmail(locale, userId, email);
132
+ await this.challenge.verifyEmail(locale, userId, email, undefined, origin);
129
133
 
130
134
  });
131
135
 
@@ -148,7 +152,7 @@ export class ProfileService {
148
152
  return { success: true };
149
153
  }
150
154
 
151
- async confirmEmailVerificationMfa(locale: string, userId: number, { pin, challengeId, name }: EmailVerificationDto) {
155
+ async confirmEmailVerificationMfa(locale: string, userId: number, { pin, challengeId, name }: EmailVerificationDto, sessionId: number | null) {
152
156
 
153
157
  const user = await this.prisma.user.findUnique({
154
158
  where: { id: userId },
@@ -221,9 +225,8 @@ export class ProfileService {
221
225
 
222
226
  });
223
227
 
224
- const updatedUser = await this.prisma.user.findFirst({ where: { id: user.id }})
225
- const codes = await this.createMfaRecoveryCodes(user.id);
226
- const newToken = await this.getToken(updatedUser);
228
+ const codes = await this.createMfaRecoveryCodes(userId);
229
+ const newToken = await this.getToken(userId, sessionId);
227
230
  return { ...newToken, codes };
228
231
 
229
232
  }
@@ -300,16 +303,16 @@ export class ProfileService {
300
303
  return { success: true };
301
304
  }
302
305
 
303
- async sendEmailVerificationMfa(locale: string, userId: number, { email }: SendEmailVerificationDto) {
304
- return this.challenge.verifyMfaEmail(locale, userId, email);
306
+ async sendEmailVerificationMfa(locale: string, userId: number, { email }: SendEmailVerificationDto, origin?: string) {
307
+ return this.challenge.verifyMfaEmail(locale, userId, email, origin);
305
308
  }
306
309
 
307
- async sendEmailVerification(locale: string, userId: number, { email }: SendEmailVerificationDto) {
308
- return this.challenge.verifyEmail(locale, userId, email);
310
+ async sendEmailVerification(locale: string, userId: number, { email }: SendEmailVerificationDto, origin?: string) {
311
+ return this.challenge.verifyEmail(locale, userId, email, undefined, origin);
309
312
  }
310
313
 
311
- async sendCodeToRemove(locale, userId, email){
312
- return this.challenge.verifyEmail(locale, userId, email)
314
+ async sendCodeToRemove(locale, userId, email, origin?: string){
315
+ return this.challenge.verifyEmail(locale, userId, email, undefined, origin)
313
316
  }
314
317
 
315
318
  async getEmailIdentifier(userId: number) {
@@ -357,6 +360,84 @@ export class ProfileService {
357
360
  return result;
358
361
  }
359
362
 
363
+ /**
364
+ * Exclusão de conta pelo próprio usuário (exigida pelas lojas de aplicativos).
365
+ *
366
+ * Anonimiza em vez de apagar: os dados pessoais somem e o acesso é revogado
367
+ * em definitivo, mas as linhas continuam existindo para não quebrar registros
368
+ * fiscais e integridade referencial. Os identificadores (e-mail, CPF...) são
369
+ * embaralhados, o que libera o e-mail original para uma conta nova no futuro.
370
+ */
371
+ async deleteAccount(locale: string, userId: number, { password }: DeleteAccountDto) {
372
+ const user = await this.prisma.user.findUnique({ where: { id: userId } });
373
+
374
+ if (!user) {
375
+ throw new NotFoundException(getLocaleText('userNotFound', locale, 'User not found.'));
376
+ }
377
+
378
+ if (user.deactivated_at) {
379
+ throw new BadRequestException(getLocaleText('accessDenied', locale, 'Access denied.'));
380
+ }
381
+
382
+ const credentials = await this.prisma.user_credential.findMany({
383
+ where: { user_id: userId, type: 'password' },
384
+ });
385
+
386
+ // Conta com senha exige a senha; conta só de login social não tem o que pedir.
387
+ if (credentials.length > 0) {
388
+ if (!password || !(await this.security.validatePassword(locale, credentials, password))) {
389
+ throw new BadRequestException(getLocaleText('accessDenied', locale, 'Access denied.'));
390
+ }
391
+ }
392
+
393
+ const deletedAt = new Date();
394
+ const suffix = `${userId}-${deletedAt.getTime()}`;
395
+
396
+ await this.prisma.$transaction(async (tx) => {
397
+ // Identificadores primeiro: libera e-mail/CPF para reuso e impede o login,
398
+ // que resolve o usuário justamente por essa tabela.
399
+ const identifiers = await tx.user_identifier.findMany({
400
+ where: { user_id: userId },
401
+ select: { id: true, type: true },
402
+ });
403
+
404
+ for (const identifier of identifiers) {
405
+ await tx.user_identifier.update({
406
+ where: { id: identifier.id },
407
+ data: {
408
+ value: `deleted-${identifier.type}-${suffix}`,
409
+ enabled: false,
410
+ verified_at: null,
411
+ },
412
+ });
413
+ }
414
+
415
+ // Credenciais, sessões e segundos fatores: nada aqui pode sobreviver,
416
+ // ou restaria um caminho de acesso à conta anonimizada.
417
+ await tx.user_identifier_challenge.deleteMany({ where: { user_identifier: { user_id: userId } } });
418
+ await tx.user_credential.deleteMany({ where: { user_id: userId } });
419
+ await tx.user_session.deleteMany({ where: { user_id: userId } });
420
+ await tx.user_mfa_challenge.deleteMany({ where: { user_mfa: { user_id: userId } } });
421
+ await tx.user_mfa.deleteMany({ where: { user_id: userId } });
422
+ await tx.user_recovery_code.deleteMany({ where: { user_id: userId } });
423
+ await tx.user_account.deleteMany({ where: { user_id: userId } });
424
+
425
+ await tx.user.update({
426
+ where: { id: userId },
427
+ data: {
428
+ name: 'Usuário removido',
429
+ photo_id: null,
430
+ deactivated_at: deletedAt,
431
+ },
432
+ });
433
+ });
434
+
435
+ // Cada library cuida dos seus próprios dados (assinatura, progresso, mensagens).
436
+ this.eventEmitter.emit(PROFILE_ACCOUNT_DELETED, new ProfileAccountDeletedEvent(userId, deletedAt));
437
+
438
+ return { success: true };
439
+ }
440
+
360
441
  async updateAvatar(locale: string, userId: number, file: MulterFile) {
361
442
  const result = await this.user.changeAvatar(locale, userId, file);
362
443
  this.eventEmitter.emit(PROFILE_AVATAR_UPDATED, new ProfileAvatarUpdatedEvent(userId, result?.id ?? null));
@@ -364,7 +445,7 @@ export class ProfileService {
364
445
  return result;
365
446
  }
366
447
 
367
- async changePassword(locale:string, userId: number, {currentPassword, newPassword}: ChangePasswordDto, ipAddress?: string, userAgent?: string) {
448
+ async changePassword(locale:string, userId: number, {currentPassword, newPassword}: ChangePasswordDto, ipAddress?: string, userAgent?: string, origin?: string) {
368
449
  const credential = await this.prisma.user_credential.findFirst({
369
450
  where: { user_id: userId, type: 'password' },
370
451
  });
@@ -405,6 +486,7 @@ export class ProfileService {
405
486
  ipAddress: ipAddress || 'Unknown',
406
487
  location: 'Unknown',
407
488
  },
489
+ app: await this.challenge.resolveAppKeyFromOrigin(origin),
408
490
  }).catch(error => {
409
491
  console.error('Failed to send password change notification:', error);
410
492
  });
@@ -446,11 +528,11 @@ export class ProfileService {
446
528
  return codes;
447
529
  }
448
530
 
449
- async getToken(user: user) {
450
- return { token: this.jwt.sign(user) };
531
+ async getToken(userId: number, sessionId: number | null) {
532
+ return { token: await this.token.createAccessToken({ sub: userId, sessionId }) };
451
533
  }
452
534
 
453
- async verifyMfaTotp(locale: string, userId: number, token: string, secret: string, name?: string) {
535
+ async verifyMfaTotp(locale: string, userId: number, token: string, secret: string, name?: string, sessionId?: number | null) {
454
536
  const settings = await this.setting.getSettingValues([
455
537
  'mfa-issuer',
456
538
  'mfa-window',
@@ -512,9 +594,8 @@ export class ProfileService {
512
594
  });
513
595
  }
514
596
 
515
- const updatedUser = await this.prisma.user.findFirst({ where: { id: user.id }})
516
- const codes = await this.createMfaRecoveryCodes(updatedUser.id);
517
- const newToken = await this.getToken(updatedUser);
597
+ const codes = await this.createMfaRecoveryCodes(userId);
598
+ const newToken = await this.getToken(userId, sessionId ?? null);
518
599
  return { ...newToken, codes };
519
600
  }
520
601
 
@@ -567,7 +648,7 @@ export class ProfileService {
567
648
  return { otpauthUrl: secret.otpauth_url, qrCode, secret: encodedSecret };
568
649
  }
569
650
 
570
- async removeMfaTotp(locale: string, userId: number, mfaId: number, token: string) {
651
+ async removeMfaTotp(locale: string, userId: number, mfaId: number, token: string, sessionId: number | null) {
571
652
  try {
572
653
  const user = await this.prisma.user.findFirst({
573
654
  where: { id: userId },
@@ -604,26 +685,26 @@ export class ProfileService {
604
685
  });
605
686
  });
606
687
 
607
- return this.getUserToken(userId)
688
+ return this.getUserToken(userId, sessionId)
608
689
  } catch (error: any) {
609
690
  throw new BadRequestException(`Invalid code: ${error?.message}`);
610
691
  }
611
692
  }
612
693
 
613
- async removeMfaEmail(locale: string, userId: number, mfaId: number, token: string, providedHash: string) {
694
+ async removeMfaEmail(locale: string, userId: number, mfaId: number, token: string, providedHash: string, sessionId: number | null) {
614
695
  try {
615
696
  await this.challenge.verifyCode(locale, userId, token, providedHash)
616
697
  await this.prisma.user_mfa.deleteMany({
617
698
  where: { id: mfaId, user_id: userId, type: 'email' },
618
699
  });
619
700
 
620
- return this.getUserToken(userId)
701
+ return this.getUserToken(userId, sessionId)
621
702
  } catch (error: any) {
622
703
  throw new BadRequestException(`Invalid code: ${error?.message}`);
623
704
  }
624
705
  }
625
706
 
626
- async removeMfaWithRecoveryCode(locale: string, userId: number, mfaId: number, recoveryCode: string) {
707
+ async removeMfaWithRecoveryCode(locale: string, userId: number, mfaId: number, recoveryCode: string, sessionId: number | null) {
627
708
  try {
628
709
  const user = await this.prisma.user.findUnique({
629
710
  where: { id: userId },
@@ -657,13 +738,13 @@ export class ProfileService {
657
738
  where: { id: mfaId, user_id: userId },
658
739
  });
659
740
 
660
- return this.getUserToken(userId);
741
+ return this.getUserToken(userId, sessionId);
661
742
  } catch (error: any) {
662
743
  throw new BadRequestException(`Invalid code: ${error?.message}`);
663
744
  }
664
745
  }
665
746
 
666
- async removeMfa(locale: string, userId: number, mfaId: number, data: { token?: string; hash?: string; verificationType?: 'totp' | 'email' | 'recovery' | 'webauthn'; assertionResponse?: any }, requestOrigin?: string) {
747
+ async removeMfa(locale: string, userId: number, mfaId: number, data: { token?: string; hash?: string; verificationType?: 'totp' | 'email' | 'recovery' | 'webauthn'; assertionResponse?: any }, requestOrigin: string | undefined, sessionId: number | null) {
667
748
  try {
668
749
  const user = await this.prisma.user.findUnique({
669
750
  where: { id: userId },
@@ -784,13 +865,13 @@ export class ProfileService {
784
865
  where: { id: mfaId, user_id: userId },
785
866
  });
786
867
 
787
- return this.getUserToken(userId);
868
+ return this.getUserToken(userId, sessionId);
788
869
  } catch (error: any) {
789
870
  throw new BadRequestException(`Failed to remove MFA: ${error?.message}`);
790
871
  }
791
872
  }
792
873
 
793
- async checkMfaBeforeAdd(locale: string, userId: number) {
874
+ async checkMfaBeforeAdd(locale: string, userId: number, origin?: string) {
794
875
  try {
795
876
  const mfaMethods = await this.prisma.user_mfa.findMany({
796
877
  where: {
@@ -820,7 +901,7 @@ export class ProfileService {
820
901
 
821
902
  if (emailMfas.length > 0) {
822
903
  const emails = emailMfas.map(mfa => mfa.user_mfa_email[0].email);
823
- await this.challenge.sendMfaCodeToMultipleEmails(locale, userId, emails);
904
+ await this.challenge.sendMfaCodeToMultipleEmails(locale, userId, emails, origin);
824
905
  availableMethods.push('email');
825
906
  }
826
907
 
@@ -857,7 +938,7 @@ export class ProfileService {
857
938
  }
858
939
  }
859
940
 
860
- async checkMfaBeforeRemove(locale: string, userId: number) {
941
+ async checkMfaBeforeRemove(locale: string, userId: number, origin?: string) {
861
942
  try {
862
943
  const mfaMethods = await this.prisma.user_mfa.findMany({
863
944
  where: {
@@ -888,7 +969,7 @@ export class ProfileService {
888
969
 
889
970
  if (emailMfas.length > 0) {
890
971
  const emails = emailMfas.map(mfa => mfa.user_mfa_email[0].email);
891
- await this.challenge.sendMfaCodeToMultipleEmails(locale, userId, emails);
972
+ await this.challenge.sendMfaCodeToMultipleEmails(locale, userId, emails, origin);
892
973
  availableMethods.push('email');
893
974
  }
894
975
 
@@ -1029,7 +1110,7 @@ export class ProfileService {
1029
1110
  }
1030
1111
  }
1031
1112
 
1032
- async sendRecoveryCodesVerification(locale: string, userId: number) {
1113
+ async sendRecoveryCodesVerification(locale: string, userId: number, origin?: string) {
1033
1114
  try {
1034
1115
  const mfaMethods = await this.prisma.user_mfa.findMany({
1035
1116
  where: {
@@ -1058,7 +1139,7 @@ export class ProfileService {
1058
1139
 
1059
1140
  if (emailMfas.length > 0) {
1060
1141
  const emails = emailMfas.map(mfa => mfa.user_mfa_email[0].email);
1061
- await this.challenge.sendMfaCodeToMultipleEmails(locale, userId, emails);
1142
+ await this.challenge.sendMfaCodeToMultipleEmails(locale, userId, emails, origin);
1062
1143
  availableMethods.push('email');
1063
1144
  }
1064
1145
 
@@ -1221,7 +1302,7 @@ export class ProfileService {
1221
1302
  }
1222
1303
  }
1223
1304
 
1224
- async generateWebAuthnRegistrationOptions(locale: string, userId: number, name: string, requestOrigin?: string) {
1305
+ async generateWebAuthnRegistrationOptions(locale: string, userId: number, name: string, requestOrigin?: string): Promise<PublicKeyCredentialCreationOptionsJSON> {
1225
1306
  try {
1226
1307
  const user = await this.prisma.user.findFirst({
1227
1308
  where: { id: userId },
@@ -1367,7 +1448,7 @@ export class ProfileService {
1367
1448
  }
1368
1449
  }
1369
1450
 
1370
- async generateWebAuthnAuthenticationOptions(locale: string, userId: number, requestOrigin?: string) {
1451
+ async generateWebAuthnAuthenticationOptions(locale: string, userId: number, requestOrigin?: string): Promise<PublicKeyCredentialRequestOptionsJSON> {
1371
1452
  try {
1372
1453
  const user = await this.prisma.user.findFirst({
1373
1454
  where: { id: userId },
@@ -1474,7 +1555,13 @@ export class ProfileService {
1474
1555
  }
1475
1556
  }
1476
1557
 
1477
- async removeWebAuthnMfa(locale: string, userId: number, mfaId: number) {
1558
+ async removeWebAuthnMfa(
1559
+ locale: string,
1560
+ userId: number,
1561
+ mfaId: number,
1562
+ assertionResponse: any,
1563
+ requestOrigin?: string,
1564
+ ) {
1478
1565
  try {
1479
1566
  const mfa = await this.prisma.user_mfa.findFirst({
1480
1567
  where: {
@@ -1490,6 +1577,22 @@ export class ProfileService {
1490
1577
  );
1491
1578
  }
1492
1579
 
1580
+ // Reautenticacao obrigatoria: sem isso, um token de acesso vazado bastava
1581
+ // para remover a chave de seguranca da conta sem provar posse dela.
1582
+ if (!assertionResponse) {
1583
+ throw new BadRequestException(
1584
+ getLocaleText('assertionResponseRequired', locale, 'Assertion response is required for WebAuthn.')
1585
+ );
1586
+ }
1587
+
1588
+ try {
1589
+ await this.verifyWebAuthnAuthentication(userId, assertionResponse, requestOrigin);
1590
+ } catch (error) {
1591
+ throw new BadRequestException(
1592
+ getLocaleText('invalidWebAuthn', locale, 'WebAuthn verification failed.')
1593
+ );
1594
+ }
1595
+
1493
1596
  await this.prisma.user_mfa.delete({
1494
1597
  where: { id: mfaId },
1495
1598
  });
@@ -1500,7 +1603,7 @@ export class ProfileService {
1500
1603
  }
1501
1604
  }
1502
1605
 
1503
- async generateWebAuthnAuthenticationOptionsForLogin(locale: string, mfaToken: string) {
1606
+ async generateWebAuthnAuthenticationOptionsForLogin(locale: string, mfaToken: string): Promise<PublicKeyCredentialRequestOptionsJSON> {
1504
1607
  try {
1505
1608
  const decoded = this.jwt.decode(mfaToken) as any;
1506
1609
  if (!decoded || !decoded.userId) {
@@ -1630,8 +1733,7 @@ export class ProfileService {
1630
1733
  }
1631
1734
  }
1632
1735
 
1633
- async getUserToken(userId: number){
1634
- const updatedUser = await this.prisma.user.findFirst({ where: { id: userId }})
1635
- return this.getToken(updatedUser);
1736
+ async getUserToken(userId: number, sessionId: number | null){
1737
+ return this.getToken(userId, sessionId);
1636
1738
  }
1637
1739
  }
@@ -0,0 +1,138 @@
1
+ import { Logger } from '@nestjs/common';
2
+ import { EventEmitter2 } from '@nestjs/event-emitter';
3
+ import {
4
+ ConnectedSocket,
5
+ MessageBody,
6
+ OnGatewayConnection,
7
+ OnGatewayDisconnect,
8
+ OnGatewayInit,
9
+ SubscribeMessage,
10
+ WebSocketGateway,
11
+ WebSocketServer,
12
+ } from '@nestjs/websockets';
13
+ import type { Server, Socket } from 'socket.io';
14
+ import { TokenService } from '../token/token.service';
15
+ import { RealtimeService } from './realtime.service';
16
+
17
+ /** Events other modules can listen to via `@OnEvent(...)`. */
18
+ export const REALTIME_EVENTS = {
19
+ userConnected: 'realtime.user.connected',
20
+ userDisconnected: 'realtime.user.disconnected',
21
+ } as const;
22
+
23
+ function corsOrigin(): string[] | boolean {
24
+ const raw = String(process.env.CORS_ALLOWED_ORIGINS || '').trim();
25
+ if (!raw) return true; // permissive handshake — the JWT is the real gate
26
+ return raw
27
+ .split(',')
28
+ .map((s) => s.trim())
29
+ .filter(Boolean);
30
+ }
31
+
32
+ /**
33
+ * Single Socket.IO gateway (`/realtime`) on the same HTTP server/port. It only
34
+ * handles transport + auth + room membership; the reusable emit API lives in
35
+ * {@link RealtimeService}. Auth reuses {@link TokenService.verify} (same JWT as
36
+ * the HTTP `AuthGuard`); connection lifecycle is broadcast via EventEmitter2 so
37
+ * features (e.g. presence) react without this layer knowing about them.
38
+ */
39
+ @WebSocketGateway({
40
+ namespace: '/realtime',
41
+ cors: { origin: corsOrigin(), credentials: true },
42
+ })
43
+ export class RealtimeGateway
44
+ implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
45
+ {
46
+ private readonly logger = new Logger(RealtimeGateway.name);
47
+
48
+ @WebSocketServer()
49
+ server!: Server;
50
+
51
+ constructor(
52
+ private readonly realtime: RealtimeService,
53
+ private readonly token: TokenService,
54
+ private readonly events: EventEmitter2,
55
+ ) {}
56
+
57
+ afterInit(server: Server) {
58
+ this.realtime.setServer(server);
59
+ this.logger.log('Realtime gateway initialized on /realtime');
60
+ }
61
+
62
+ private extractToken(socket: Socket): string | undefined {
63
+ const authToken = (socket.handshake.auth as { token?: string } | undefined)?.token;
64
+ if (authToken) return authToken;
65
+ const header = socket.handshake.headers.authorization;
66
+ const [type, value] = String(header ?? '').split(' ');
67
+ return type === 'Bearer' ? value : undefined;
68
+ }
69
+
70
+ async handleConnection(socket: Socket) {
71
+ const token = this.extractToken(socket);
72
+ if (!token) {
73
+ socket.disconnect(true);
74
+ return;
75
+ }
76
+ try {
77
+ const payload = await this.token.verify('en', token);
78
+ const userId = Number(payload?.sub);
79
+ if (!Number.isInteger(userId) || userId <= 0) {
80
+ socket.disconnect(true);
81
+ return;
82
+ }
83
+ socket.data.userId = userId;
84
+ socket.join(`user:${userId}`);
85
+ const localCount = this.realtime.trackConnect(userId);
86
+ this.events.emit(REALTIME_EVENTS.userConnected, {
87
+ userId,
88
+ firstConnection: localCount === 1,
89
+ });
90
+ } catch {
91
+ socket.disconnect(true);
92
+ }
93
+ }
94
+
95
+ handleDisconnect(socket: Socket) {
96
+ const userId = socket.data?.userId as number | undefined;
97
+ if (!userId) return;
98
+ const remaining = this.realtime.trackDisconnect(userId);
99
+ this.events.emit(REALTIME_EVENTS.userDisconnected, {
100
+ userId,
101
+ remainingLocalSockets: remaining,
102
+ });
103
+ }
104
+
105
+ /** Joins the socket to the given channels (rooms `channel:{name}`). */
106
+ @SubscribeMessage('subscribe')
107
+ onSubscribe(
108
+ @ConnectedSocket() socket: Socket,
109
+ @MessageBody() body: { channels?: string[] },
110
+ ) {
111
+ const channels = Array.isArray(body?.channels) ? body.channels : [];
112
+ for (const ch of channels) {
113
+ if (this.isAllowed(socket, String(ch))) socket.join(`channel:${ch}`);
114
+ }
115
+ return { ok: true, subscribed: channels };
116
+ }
117
+
118
+ @SubscribeMessage('unsubscribe')
119
+ onUnsubscribe(
120
+ @ConnectedSocket() socket: Socket,
121
+ @MessageBody() body: { channels?: string[] },
122
+ ) {
123
+ const channels = Array.isArray(body?.channels) ? body.channels : [];
124
+ for (const ch of channels) socket.leave(`channel:${ch}`);
125
+ return { ok: true };
126
+ }
127
+
128
+ /**
129
+ * Channel-subscription authorization. `presence:{id}` is readable by any
130
+ * authenticated user (presence is coarse/non-sensitive). Modules adding
131
+ * sensitive channels should extend this with per-channel checks.
132
+ */
133
+ private isAllowed(_socket: Socket, channel: string): boolean {
134
+ if (channel.startsWith('presence:')) return true;
135
+ // Default-allow other channels for now; tighten per feature as needed.
136
+ return true;
137
+ }
138
+ }
@@ -0,0 +1,16 @@
1
+ import { forwardRef, Module } from '@nestjs/common';
2
+ import { TokenModule } from '../token/token.module';
3
+ import { RealtimeGateway } from './realtime.gateway';
4
+ import { RealtimeService } from './realtime.service';
5
+
6
+ /**
7
+ * Generic real-time (WebSocket) layer for the whole app. Any module can inject
8
+ * {@link RealtimeService} to push events to users/channels, fanned out across
9
+ * instances via Redis. EventEmitter2 (global) delivers connection lifecycle.
10
+ */
11
+ @Module({
12
+ imports: [forwardRef(() => TokenModule)],
13
+ providers: [RealtimeGateway, RealtimeService],
14
+ exports: [RealtimeService],
15
+ })
16
+ export class RealtimeModule {}
@@ -0,0 +1,50 @@
1
+ import { beforeEach, describe, expect, it, jest } from '@jest/globals';
2
+ import { RealtimeService } from './realtime.service';
3
+
4
+ const makeServer = () => {
5
+ const emit = jest.fn();
6
+ const to = jest.fn(() => ({ emit }));
7
+ return { to, emit: emit as any, rootEmit: jest.fn(), server: { to, emit: jest.fn() } };
8
+ };
9
+
10
+ describe('RealtimeService', () => {
11
+ let service: RealtimeService;
12
+ let server: ReturnType<typeof makeServer>;
13
+
14
+ beforeEach(() => {
15
+ service = new RealtimeService();
16
+ server = makeServer();
17
+ service.setServer(server.server as any);
18
+ });
19
+
20
+ it('emits to the user room', () => {
21
+ service.emitToUser(7, 'presence:update', { online: true });
22
+ expect(server.to).toHaveBeenCalledWith('user:7');
23
+ });
24
+
25
+ it('emits to the channel room', () => {
26
+ service.emitToChannel('presence:7', 'presence:update', { online: true });
27
+ expect(server.to).toHaveBeenCalledWith('channel:presence:7');
28
+ });
29
+
30
+ it('broadcasts to everyone', () => {
31
+ service.broadcast('ping', {});
32
+ expect((server.server as any).emit).toHaveBeenCalledWith('ping', {});
33
+ });
34
+
35
+ it('does not throw when no server is bound yet', () => {
36
+ const bare = new RealtimeService();
37
+ expect(() => bare.emitToUser(1, 'x', {})).not.toThrow();
38
+ });
39
+
40
+ it('tracks local connections per user', () => {
41
+ expect(service.trackConnect(1)).toBe(1);
42
+ expect(service.trackConnect(1)).toBe(2);
43
+ expect(service.isLocallyConnected(1)).toBe(true);
44
+ expect(service.getLocallyConnectedUserIds()).toEqual([1]);
45
+ expect(service.trackDisconnect(1)).toBe(1);
46
+ expect(service.trackDisconnect(1)).toBe(0);
47
+ expect(service.isLocallyConnected(1)).toBe(false);
48
+ expect(service.getLocallyConnectedUserIds()).toEqual([]);
49
+ });
50
+ });