@hed-hog/core 0.0.387 → 0.0.390

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (535) hide show
  1. package/README.md +12 -11
  2. package/dist/access-log/access-log.interceptor.d.ts.map +1 -1
  3. package/dist/access-log/access-log.interceptor.js +4 -2
  4. package/dist/access-log/access-log.interceptor.js.map +1 -1
  5. package/dist/ai/ai-attachment.fragments.d.ts +23 -0
  6. package/dist/ai/ai-attachment.fragments.d.ts.map +1 -0
  7. package/dist/ai/ai-attachment.fragments.js +34 -0
  8. package/dist/ai/ai-attachment.fragments.js.map +1 -0
  9. package/dist/ai/ai.controller.d.ts +7 -16
  10. package/dist/ai/ai.controller.d.ts.map +1 -1
  11. package/dist/ai/ai.prompts.d.ts +16 -0
  12. package/dist/ai/ai.prompts.d.ts.map +1 -0
  13. package/dist/ai/ai.prompts.js +37 -0
  14. package/dist/ai/ai.prompts.js.map +1 -0
  15. package/dist/ai/ai.service.d.ts +63 -12
  16. package/dist/ai/ai.service.d.ts.map +1 -1
  17. package/dist/ai/ai.service.js +215 -88
  18. package/dist/ai/ai.service.js.map +1 -1
  19. package/dist/ai/dto/chat.dto.d.ts +4 -1
  20. package/dist/ai/dto/chat.dto.d.ts.map +1 -1
  21. package/dist/ai/dto/chat.dto.js +23 -1
  22. package/dist/ai/dto/chat.dto.js.map +1 -1
  23. package/dist/ai/dto/create-agent.dto.d.ts +1 -1
  24. package/dist/ai/dto/create-agent.dto.d.ts.map +1 -1
  25. package/dist/ai/dto/create-agent.dto.js +1 -1
  26. package/dist/ai/dto/create-agent.dto.js.map +1 -1
  27. package/dist/ai/dto/update-agent.dto.d.ts +1 -1
  28. package/dist/ai/dto/update-agent.dto.d.ts.map +1 -1
  29. package/dist/ai/dto/update-agent.dto.js +1 -1
  30. package/dist/ai/dto/update-agent.dto.js.map +1 -1
  31. package/dist/ai-instruction/ai-instruction.controller.d.ts +61 -7
  32. package/dist/ai-instruction/ai-instruction.controller.d.ts.map +1 -1
  33. package/dist/ai-instruction/ai-instruction.controller.js +63 -20
  34. package/dist/ai-instruction/ai-instruction.controller.js.map +1 -1
  35. package/dist/ai-instruction/ai-instruction.module.d.ts.map +1 -1
  36. package/dist/ai-instruction/ai-instruction.module.js +13 -2
  37. package/dist/ai-instruction/ai-instruction.module.js.map +1 -1
  38. package/dist/ai-instruction/ai-instruction.service.d.ts +131 -6
  39. package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
  40. package/dist/ai-instruction/ai-instruction.service.js +533 -60
  41. package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
  42. package/dist/ai-instruction/ai-prompt-builder.service.d.ts +8 -0
  43. package/dist/ai-instruction/ai-prompt-builder.service.d.ts.map +1 -1
  44. package/dist/ai-instruction/ai-prompt-builder.service.js +10 -1
  45. package/dist/ai-instruction/ai-prompt-builder.service.js.map +1 -1
  46. package/dist/ai-instruction/ai-prompt-registry.d.ts +45 -0
  47. package/dist/ai-instruction/ai-prompt-registry.d.ts.map +1 -0
  48. package/dist/ai-instruction/ai-prompt-registry.js +49 -0
  49. package/dist/ai-instruction/ai-prompt-registry.js.map +1 -0
  50. package/dist/ai-instruction/ai-prompt-resolver.service.d.ts +89 -0
  51. package/dist/ai-instruction/ai-prompt-resolver.service.d.ts.map +1 -0
  52. package/dist/ai-instruction/ai-prompt-resolver.service.js +222 -0
  53. package/dist/ai-instruction/ai-prompt-resolver.service.js.map +1 -0
  54. package/dist/ai-instruction/ai-prompt-template.util.d.ts +70 -0
  55. package/dist/ai-instruction/ai-prompt-template.util.d.ts.map +1 -0
  56. package/dist/ai-instruction/ai-prompt-template.util.js +154 -0
  57. package/dist/ai-instruction/ai-prompt-template.util.js.map +1 -0
  58. package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts +5 -0
  59. package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts.map +1 -1
  60. package/dist/ai-instruction/dto/create-ai-instruction.dto.js +27 -1
  61. package/dist/ai-instruction/dto/create-ai-instruction.dto.js.map +1 -1
  62. package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts +14 -0
  63. package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts.map +1 -0
  64. package/dist/ai-instruction/dto/preview-ai-instruction.dto.js +42 -0
  65. package/dist/ai-instruction/dto/preview-ai-instruction.dto.js.map +1 -0
  66. package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts +11 -0
  67. package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts.map +1 -1
  68. package/dist/ai-instruction/dto/update-ai-instruction.dto.js +34 -0
  69. package/dist/ai-instruction/dto/update-ai-instruction.dto.js.map +1 -1
  70. package/dist/ai-instruction/types/ai-instruction.types.d.ts +13 -1
  71. package/dist/ai-instruction/types/ai-instruction.types.d.ts.map +1 -1
  72. package/dist/ai-instruction/types/ai-instruction.types.js +10 -0
  73. package/dist/ai-instruction/types/ai-instruction.types.js.map +1 -1
  74. package/dist/auth/auth.controller.d.ts +24 -9
  75. package/dist/auth/auth.controller.d.ts.map +1 -1
  76. package/dist/auth/auth.controller.js +49 -21
  77. package/dist/auth/auth.controller.js.map +1 -1
  78. package/dist/auth/auth.service.d.ts +33 -8
  79. package/dist/auth/auth.service.d.ts.map +1 -1
  80. package/dist/auth/auth.service.js +78 -29
  81. package/dist/auth/auth.service.js.map +1 -1
  82. package/dist/captcha/captcha.module.d.ts +3 -0
  83. package/dist/captcha/captcha.module.d.ts.map +1 -0
  84. package/dist/captcha/captcha.module.js +23 -0
  85. package/dist/captcha/captcha.module.js.map +1 -0
  86. package/dist/captcha/captcha.service.d.ts +38 -0
  87. package/dist/captcha/captcha.service.d.ts.map +1 -0
  88. package/dist/captcha/captcha.service.js +144 -0
  89. package/dist/captcha/captcha.service.js.map +1 -0
  90. package/dist/challenge/challenge.service.d.ts +16 -7
  91. package/dist/challenge/challenge.service.d.ts.map +1 -1
  92. package/dist/challenge/challenge.service.js +64 -16
  93. package/dist/challenge/challenge.service.js.map +1 -1
  94. package/dist/core.module.d.ts +3 -1
  95. package/dist/core.module.d.ts.map +1 -1
  96. package/dist/core.module.js +29 -2
  97. package/dist/core.module.js.map +1 -1
  98. package/dist/dashboard/dashboard/dashboard.controller.d.ts +15 -15
  99. package/dist/dashboard/dashboard/dashboard.service.d.ts +15 -15
  100. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +6 -6
  101. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +6 -6
  102. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +20 -20
  103. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +20 -20
  104. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +1 -1
  105. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +1 -1
  106. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +13 -13
  107. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +13 -13
  108. package/dist/file/file.service.d.ts +6 -0
  109. package/dist/file/file.service.d.ts.map +1 -1
  110. package/dist/file/file.service.js +44 -4
  111. package/dist/file/file.service.js.map +1 -1
  112. package/dist/incident/incident-notifier.service.d.ts +36 -0
  113. package/dist/incident/incident-notifier.service.d.ts.map +1 -0
  114. package/dist/incident/incident-notifier.service.js +208 -0
  115. package/dist/incident/incident-notifier.service.js.map +1 -0
  116. package/dist/incident/incident.controller.d.ts +23 -0
  117. package/dist/incident/incident.controller.d.ts.map +1 -0
  118. package/dist/incident/incident.controller.js +75 -0
  119. package/dist/incident/incident.controller.js.map +1 -0
  120. package/dist/incident/incident.module.d.ts +7 -0
  121. package/dist/incident/incident.module.d.ts.map +1 -0
  122. package/dist/incident/incident.module.js +32 -0
  123. package/dist/incident/incident.module.js.map +1 -0
  124. package/dist/incident/incident.service.d.ts +72 -0
  125. package/dist/incident/incident.service.d.ts.map +1 -0
  126. package/dist/incident/incident.service.js +184 -0
  127. package/dist/incident/incident.service.js.map +1 -0
  128. package/dist/index.d.ts +26 -0
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +30 -0
  131. package/dist/index.js.map +1 -1
  132. package/dist/integration-profile/dto/test.dto.d.ts +13 -0
  133. package/dist/integration-profile/dto/test.dto.d.ts.map +1 -0
  134. package/dist/integration-profile/dto/test.dto.js +26 -0
  135. package/dist/integration-profile/dto/test.dto.js.map +1 -0
  136. package/dist/integration-profile/integration-profile.controller.d.ts +12 -1
  137. package/dist/integration-profile/integration-profile.controller.d.ts.map +1 -1
  138. package/dist/integration-profile/integration-profile.controller.js +9 -1
  139. package/dist/integration-profile/integration-profile.controller.js.map +1 -1
  140. package/dist/integration-profile/integration-profile.module.d.ts +6 -1
  141. package/dist/integration-profile/integration-profile.module.d.ts.map +1 -1
  142. package/dist/integration-profile/integration-profile.module.js +26 -3
  143. package/dist/integration-profile/integration-profile.module.js.map +1 -1
  144. package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
  145. package/dist/integration-profile/integration-profile.secrets.js +9 -1
  146. package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
  147. package/dist/integration-profile/integration-profile.service.d.ts +26 -7
  148. package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
  149. package/dist/integration-profile/integration-profile.service.js +94 -91
  150. package/dist/integration-profile/integration-profile.service.js.map +1 -1
  151. package/dist/integration-profile/integration-profile.utils.d.ts +13 -1
  152. package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
  153. package/dist/integration-profile/integration-profile.utils.js +20 -5
  154. package/dist/integration-profile/integration-profile.utils.js.map +1 -1
  155. package/dist/integration-profile/testers/ai.testers.d.ts +3 -0
  156. package/dist/integration-profile/testers/ai.testers.d.ts.map +1 -0
  157. package/dist/integration-profile/testers/ai.testers.js +125 -0
  158. package/dist/integration-profile/testers/ai.testers.js.map +1 -0
  159. package/dist/integration-profile/testers/captcha.testers.d.ts +3 -0
  160. package/dist/integration-profile/testers/captcha.testers.d.ts.map +1 -0
  161. package/dist/integration-profile/testers/captcha.testers.js +121 -0
  162. package/dist/integration-profile/testers/captcha.testers.js.map +1 -0
  163. package/dist/integration-profile/testers/email.testers.d.ts +3 -0
  164. package/dist/integration-profile/testers/email.testers.d.ts.map +1 -0
  165. package/dist/integration-profile/testers/email.testers.js +128 -0
  166. package/dist/integration-profile/testers/email.testers.js.map +1 -0
  167. package/dist/integration-profile/testers/http-probe.d.ts +57 -0
  168. package/dist/integration-profile/testers/http-probe.d.ts.map +1 -0
  169. package/dist/integration-profile/testers/http-probe.js +140 -0
  170. package/dist/integration-profile/testers/http-probe.js.map +1 -0
  171. package/dist/integration-profile/testers/index.d.ts +12 -0
  172. package/dist/integration-profile/testers/index.d.ts.map +1 -0
  173. package/dist/integration-profile/testers/index.js +45 -0
  174. package/dist/integration-profile/testers/index.js.map +1 -0
  175. package/dist/integration-profile/testers/infrastructure.testers.d.ts +3 -0
  176. package/dist/integration-profile/testers/infrastructure.testers.d.ts.map +1 -0
  177. package/dist/integration-profile/testers/infrastructure.testers.js +105 -0
  178. package/dist/integration-profile/testers/infrastructure.testers.js.map +1 -0
  179. package/dist/integration-profile/testers/integration-tester.registry.d.ts +17 -0
  180. package/dist/integration-profile/testers/integration-tester.registry.d.ts.map +1 -0
  181. package/dist/integration-profile/testers/integration-tester.registry.js +52 -0
  182. package/dist/integration-profile/testers/integration-tester.registry.js.map +1 -0
  183. package/dist/integration-profile/testers/integration-tester.types.d.ts +55 -0
  184. package/dist/integration-profile/testers/integration-tester.types.d.ts.map +1 -0
  185. package/dist/integration-profile/testers/integration-tester.types.js +16 -0
  186. package/dist/integration-profile/testers/integration-tester.types.js.map +1 -0
  187. package/dist/integration-profile/testers/messaging.testers.d.ts +3 -0
  188. package/dist/integration-profile/testers/messaging.testers.d.ts.map +1 -0
  189. package/dist/integration-profile/testers/messaging.testers.js +70 -0
  190. package/dist/integration-profile/testers/messaging.testers.js.map +1 -0
  191. package/dist/integration-profile/testers/oauth.testers.d.ts +3 -0
  192. package/dist/integration-profile/testers/oauth.testers.d.ts.map +1 -0
  193. package/dist/integration-profile/testers/oauth.testers.js +285 -0
  194. package/dist/integration-profile/testers/oauth.testers.js.map +1 -0
  195. package/dist/integration-profile/testers/payment.testers.d.ts +3 -0
  196. package/dist/integration-profile/testers/payment.testers.d.ts.map +1 -0
  197. package/dist/integration-profile/testers/payment.testers.js +169 -0
  198. package/dist/integration-profile/testers/payment.testers.js.map +1 -0
  199. package/dist/integration-profile/testers/storage.testers.d.ts +3 -0
  200. package/dist/integration-profile/testers/storage.testers.d.ts.map +1 -0
  201. package/dist/integration-profile/testers/storage.testers.js +208 -0
  202. package/dist/integration-profile/testers/storage.testers.js.map +1 -0
  203. package/dist/language/en.json +4 -2
  204. package/dist/language/pt.json +4 -2
  205. package/dist/leaked-password/leaked-password.controller.d.ts +24 -0
  206. package/dist/leaked-password/leaked-password.controller.d.ts.map +1 -0
  207. package/dist/leaked-password/leaked-password.controller.js +78 -0
  208. package/dist/leaked-password/leaked-password.controller.js.map +1 -0
  209. package/dist/leaked-password/leaked-password.module.d.ts +8 -0
  210. package/dist/leaked-password/leaked-password.module.d.ts.map +1 -0
  211. package/dist/leaked-password/leaked-password.module.js +31 -0
  212. package/dist/leaked-password/leaked-password.module.js.map +1 -0
  213. package/dist/leaked-password/leaked-password.service.d.ts +64 -0
  214. package/dist/leaked-password/leaked-password.service.d.ts.map +1 -0
  215. package/dist/leaked-password/leaked-password.service.js +218 -0
  216. package/dist/leaked-password/leaked-password.service.js.map +1 -0
  217. package/dist/locale/locale.controller.d.ts +1 -1
  218. package/dist/locale/locale.service.d.ts +1 -1
  219. package/dist/mail/dto/preview.dto.d.ts +18 -0
  220. package/dist/mail/dto/preview.dto.d.ts.map +1 -0
  221. package/dist/mail/dto/preview.dto.js +66 -0
  222. package/dist/mail/dto/preview.dto.js.map +1 -0
  223. package/dist/mail/dto/send.dto.d.ts +7 -0
  224. package/dist/mail/dto/send.dto.d.ts.map +1 -1
  225. package/dist/mail/dto/send.dto.js +10 -0
  226. package/dist/mail/dto/send.dto.js.map +1 -1
  227. package/dist/mail/mail.controller.d.ts +4 -0
  228. package/dist/mail/mail.controller.d.ts.map +1 -1
  229. package/dist/mail/mail.controller.js +16 -2
  230. package/dist/mail/mail.controller.js.map +1 -1
  231. package/dist/mail/mail.service.d.ts +23 -2
  232. package/dist/mail/mail.service.d.ts.map +1 -1
  233. package/dist/mail/mail.service.js +102 -13
  234. package/dist/mail/mail.service.js.map +1 -1
  235. package/dist/mail-layout/dto/update.dto.d.ts +17 -0
  236. package/dist/mail-layout/dto/update.dto.d.ts.map +1 -0
  237. package/dist/mail-layout/dto/update.dto.js +27 -0
  238. package/dist/mail-layout/dto/update.dto.js.map +1 -0
  239. package/dist/mail-layout/mail-layout.controller.d.ts +15 -0
  240. package/dist/mail-layout/mail-layout.controller.d.ts.map +1 -0
  241. package/dist/mail-layout/mail-layout.controller.js +71 -0
  242. package/dist/mail-layout/mail-layout.controller.js.map +1 -0
  243. package/dist/mail-layout/mail-layout.module.d.ts +3 -0
  244. package/dist/mail-layout/mail-layout.module.d.ts.map +1 -0
  245. package/dist/mail-layout/mail-layout.module.js +35 -0
  246. package/dist/mail-layout/mail-layout.module.js.map +1 -0
  247. package/dist/mail-layout/mail-layout.service.d.ts +27 -0
  248. package/dist/mail-layout/mail-layout.service.d.ts.map +1 -0
  249. package/dist/mail-layout/mail-layout.service.js +80 -0
  250. package/dist/mail-layout/mail-layout.service.js.map +1 -0
  251. package/dist/mcp-chat/mcp-chat.controller.d.ts +2 -2
  252. package/dist/mcp-chat/mcp-chat.service.d.ts +24 -2
  253. package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
  254. package/dist/mcp-chat/mcp-chat.service.js +80 -24
  255. package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
  256. package/dist/menu/menu.controller.d.ts +3 -3
  257. package/dist/menu/menu.service.d.ts +3 -3
  258. package/dist/notification/notification.controller.d.ts +12 -12
  259. package/dist/notification/notification.service.d.ts +12 -12
  260. package/dist/oauth/oauth-token-broker.service.d.ts +72 -0
  261. package/dist/oauth/oauth-token-broker.service.d.ts.map +1 -0
  262. package/dist/oauth/oauth-token-broker.service.js +258 -0
  263. package/dist/oauth/oauth-token-broker.service.js.map +1 -0
  264. package/dist/oauth/oauth.module.d.ts.map +1 -1
  265. package/dist/oauth/oauth.module.js +3 -1
  266. package/dist/oauth/oauth.module.js.map +1 -1
  267. package/dist/oauth/oauth.service.d.ts +2 -0
  268. package/dist/oauth/oauth.service.d.ts.map +1 -1
  269. package/dist/oauth/oauth.service.js +6 -3
  270. package/dist/oauth/oauth.service.js.map +1 -1
  271. package/dist/pdf/pdf.service.d.ts +8 -0
  272. package/dist/pdf/pdf.service.d.ts.map +1 -1
  273. package/dist/pdf/pdf.service.js +52 -0
  274. package/dist/pdf/pdf.service.js.map +1 -1
  275. package/dist/presence/presence.controller.d.ts +16 -0
  276. package/dist/presence/presence.controller.d.ts.map +1 -0
  277. package/dist/presence/presence.controller.js +60 -0
  278. package/dist/presence/presence.controller.js.map +1 -0
  279. package/dist/presence/presence.listener.d.ts +29 -0
  280. package/dist/presence/presence.listener.d.ts.map +1 -0
  281. package/dist/presence/presence.listener.js +82 -0
  282. package/dist/presence/presence.listener.js.map +1 -0
  283. package/dist/presence/presence.module.d.ts +3 -0
  284. package/dist/presence/presence.module.d.ts.map +1 -0
  285. package/dist/presence/presence.module.js +32 -0
  286. package/dist/presence/presence.module.js.map +1 -0
  287. package/dist/presence/presence.service.d.ts +42 -0
  288. package/dist/presence/presence.service.d.ts.map +1 -0
  289. package/dist/presence/presence.service.js +147 -0
  290. package/dist/presence/presence.service.js.map +1 -0
  291. package/dist/profile/dto/delete-account.dto.d.ts +8 -0
  292. package/dist/profile/dto/delete-account.dto.d.ts.map +1 -0
  293. package/dist/profile/dto/delete-account.dto.js +22 -0
  294. package/dist/profile/dto/delete-account.dto.js.map +1 -0
  295. package/dist/profile/events/profile-account-deleted.event.d.ts +12 -0
  296. package/dist/profile/events/profile-account-deleted.event.d.ts.map +1 -0
  297. package/dist/profile/events/profile-account-deleted.event.js +17 -0
  298. package/dist/profile/events/profile-account-deleted.event.js.map +1 -0
  299. package/dist/profile/profile.controller.d.ts +21 -15
  300. package/dist/profile/profile.controller.d.ts.map +1 -1
  301. package/dist/profile/profile.controller.js +75 -46
  302. package/dist/profile/profile.controller.js.map +1 -1
  303. package/dist/profile/profile.service.d.ts +30 -18
  304. package/dist/profile/profile.service.d.ts.map +1 -1
  305. package/dist/profile/profile.service.js +113 -37
  306. package/dist/profile/profile.service.js.map +1 -1
  307. package/dist/realtime/realtime.gateway.d.ts +48 -0
  308. package/dist/realtime/realtime.gateway.d.ts.map +1 -0
  309. package/dist/realtime/realtime.gateway.js +156 -0
  310. package/dist/realtime/realtime.gateway.js.map +1 -0
  311. package/dist/realtime/realtime.module.d.ts +8 -0
  312. package/dist/realtime/realtime.module.d.ts.map +1 -0
  313. package/dist/realtime/realtime.module.js +29 -0
  314. package/dist/realtime/realtime.module.js.map +1 -0
  315. package/dist/realtime/realtime.service.d.ts +51 -0
  316. package/dist/realtime/realtime.service.d.ts.map +1 -0
  317. package/dist/realtime/realtime.service.js +177 -0
  318. package/dist/realtime/realtime.service.js.map +1 -0
  319. package/dist/redis/redis-pubsub.d.ts +27 -0
  320. package/dist/redis/redis-pubsub.d.ts.map +1 -0
  321. package/dist/redis/redis-pubsub.js +140 -0
  322. package/dist/redis/redis-pubsub.js.map +1 -0
  323. package/dist/role/role.controller.d.ts +3 -3
  324. package/dist/role/role.service.d.ts +3 -3
  325. package/dist/setting/dto/create.dto.d.ts.map +1 -1
  326. package/dist/setting/dto/create.dto.js +9 -2
  327. package/dist/setting/dto/create.dto.js.map +1 -1
  328. package/dist/setting/setting.controller.d.ts +5 -5
  329. package/dist/setting/setting.service.d.ts +8 -5
  330. package/dist/setting/setting.service.d.ts.map +1 -1
  331. package/dist/setting/setting.service.js +25 -1
  332. package/dist/setting/setting.service.js.map +1 -1
  333. package/dist/user/dto/create-with-email-and-password.dto.d.ts +2 -0
  334. package/dist/user/dto/create-with-email-and-password.dto.d.ts.map +1 -1
  335. package/dist/user/dto/create-with-email-and-password.dto.js +5 -0
  336. package/dist/user/dto/create-with-email-and-password.dto.js.map +1 -1
  337. package/dist/user/dto/query-user-mail-list.dto.d.ts +5 -0
  338. package/dist/user/dto/query-user-mail-list.dto.d.ts.map +1 -0
  339. package/dist/user/dto/query-user-mail-list.dto.js +25 -0
  340. package/dist/user/dto/query-user-mail-list.dto.js.map +1 -0
  341. package/dist/user/user-credential.util.d.ts +19 -0
  342. package/dist/user/user-credential.util.d.ts.map +1 -0
  343. package/dist/user/user-credential.util.js +32 -0
  344. package/dist/user/user-credential.util.js.map +1 -0
  345. package/dist/user/user.controller.d.ts +17 -5
  346. package/dist/user/user.controller.d.ts.map +1 -1
  347. package/dist/user/user.controller.js +18 -3
  348. package/dist/user/user.controller.js.map +1 -1
  349. package/dist/user/user.service.d.ts +28 -6
  350. package/dist/user/user.service.d.ts.map +1 -1
  351. package/dist/user/user.service.js +204 -13
  352. package/dist/user/user.service.js.map +1 -1
  353. package/dist/validators/is-strong-password-with-settings.validator.d.ts.map +1 -1
  354. package/dist/validators/is-strong-password-with-settings.validator.js +11 -0
  355. package/dist/validators/is-strong-password-with-settings.validator.js.map +1 -1
  356. package/dist/validators/service-locator.d.ts +9 -0
  357. package/dist/validators/service-locator.d.ts.map +1 -1
  358. package/dist/validators/service-locator.js +12 -0
  359. package/dist/validators/service-locator.js.map +1 -1
  360. package/dist/whatsapp-sender/whatsapp-sender.module.d.ts +3 -0
  361. package/dist/whatsapp-sender/whatsapp-sender.module.d.ts.map +1 -0
  362. package/dist/whatsapp-sender/whatsapp-sender.module.js +23 -0
  363. package/dist/whatsapp-sender/whatsapp-sender.module.js.map +1 -0
  364. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +50 -0
  365. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -0
  366. package/dist/whatsapp-sender/whatsapp-sender.service.js +224 -0
  367. package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -0
  368. package/hedhog/data/integration_provider.yaml +16 -0
  369. package/hedhog/data/mail.yaml +88 -61
  370. package/hedhog/data/mail_layout.yaml +188 -0
  371. package/hedhog/data/menu.yaml +67 -3
  372. package/hedhog/data/route.yaml +135 -0
  373. package/hedhog/data/setting_group.yaml +139 -1
  374. package/hedhog/frontend/app/account/components/mfa-setup-dialog.tsx.ejs +36 -0
  375. package/hedhog/frontend/app/account/components/two-factor-auth.tsx.ejs +2 -0
  376. package/hedhog/frontend/app/account/hooks/use-mfa-setup.ts.ejs +10 -7
  377. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +7 -4
  378. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +580 -0
  379. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-preview.tsx.ejs +150 -0
  380. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +199 -0
  381. package/hedhog/frontend/app/ai_instruction/_components/prompt-diff.tsx.ejs +63 -0
  382. package/hedhog/frontend/app/ai_instruction/_lib/line-diff.spec.ts.ejs +59 -0
  383. package/hedhog/frontend/app/ai_instruction/_lib/line-diff.ts.ejs +72 -0
  384. package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.spec.ts.ejs +170 -0
  385. package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.ts.ejs +167 -0
  386. package/hedhog/frontend/app/ai_instruction/_lib/types.ts.ejs +99 -0
  387. package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +422 -0
  388. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +51 -4
  389. package/hedhog/frontend/app/incidents/page.tsx.ejs +400 -0
  390. package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +153 -84
  391. package/hedhog/frontend/app/mail/layout/page.tsx.ejs +344 -0
  392. package/hedhog/frontend/app/mail/template/page.tsx.ejs +155 -121
  393. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +129 -17
  394. package/hedhog/frontend/app/pages/_components/page-delete-dialog.tsx.ejs +343 -0
  395. package/hedhog/frontend/app/pages/_components/page-detail-sheet.tsx.ejs +438 -0
  396. package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1009 -0
  397. package/hedhog/frontend/app/pages/_components/system-page-types.ts.ejs +56 -0
  398. package/hedhog/frontend/app/pages/_components/use-system-pages.ts.ejs +171 -0
  399. package/hedhog/frontend/app/pages/page.tsx.ejs +514 -0
  400. package/hedhog/frontend/app/users/page.tsx.ejs +119 -13
  401. package/hedhog/frontend/app/users/user-activity-timeline.tsx.ejs +231 -0
  402. package/hedhog/frontend/app/users/user-mails.tsx.ejs +399 -0
  403. package/hedhog/frontend/app/users/user-sheet.tsx.ejs +60 -75
  404. package/hedhog/frontend/messages/en.json +499 -3
  405. package/hedhog/frontend/messages/pt.json +499 -3
  406. package/hedhog/table/ai_agent.yaml +1 -0
  407. package/hedhog/table/ai_instruction.yaml +15 -0
  408. package/hedhog/table/leaked_password.yaml +18 -0
  409. package/hedhog/table/mail_layout.yaml +35 -0
  410. package/hedhog/table/mail_var.yaml +4 -0
  411. package/hedhog/table/setting.yaml +1 -0
  412. package/hedhog/table/system_incident.yaml +59 -0
  413. package/hedhog/table/user_presence.yaml +36 -0
  414. package/package.json +8 -4
  415. package/src/access-log/access-log.interceptor.ts +4 -2
  416. package/src/ai/ai-attachment.fragments.spec.ts +319 -0
  417. package/src/ai/ai-attachment.fragments.ts +35 -0
  418. package/src/ai/ai.prompts.ts +38 -0
  419. package/src/ai/ai.service.spec.ts +280 -0
  420. package/src/ai/ai.service.ts +338 -82
  421. package/src/ai/dto/chat.dto.ts +33 -3
  422. package/src/ai/dto/create-agent.dto.ts +2 -2
  423. package/src/ai/dto/update-agent.dto.ts +2 -2
  424. package/src/ai-instruction/ai-instruction.controller.ts +40 -9
  425. package/src/ai-instruction/ai-instruction.module.ts +13 -2
  426. package/src/ai-instruction/ai-instruction.service.spec.ts +658 -0
  427. package/src/ai-instruction/ai-instruction.service.ts +661 -62
  428. package/src/ai-instruction/ai-prompt-builder.service.ts +10 -1
  429. package/src/ai-instruction/ai-prompt-registry.ts +87 -0
  430. package/src/ai-instruction/ai-prompt-resolver.service.spec.ts +375 -0
  431. package/src/ai-instruction/ai-prompt-resolver.service.ts +295 -0
  432. package/src/ai-instruction/ai-prompt-template.util.spec.ts +162 -0
  433. package/src/ai-instruction/ai-prompt-template.util.ts +199 -0
  434. package/src/ai-instruction/dto/create-ai-instruction.dto.ts +39 -3
  435. package/src/ai-instruction/dto/preview-ai-instruction.dto.ts +26 -0
  436. package/src/ai-instruction/dto/update-ai-instruction.dto.ts +42 -1
  437. package/src/ai-instruction/types/ai-instruction.types.ts +24 -1
  438. package/src/auth/auth.controller.ts +31 -5
  439. package/src/auth/auth.service.spec.ts +3 -1
  440. package/src/auth/auth.service.ts +101 -36
  441. package/src/captcha/captcha.module.ts +10 -0
  442. package/src/captcha/captcha.service.spec.ts +210 -0
  443. package/src/captcha/captcha.service.ts +191 -0
  444. package/src/challenge/challenge.service.spec.ts +39 -4
  445. package/src/challenge/challenge.service.ts +72 -17
  446. package/src/core.module.ts +27 -1
  447. package/src/file/file.service.spec.ts +105 -0
  448. package/src/file/file.service.ts +60 -3
  449. package/src/incident/incident-notifier.service.spec.ts +205 -0
  450. package/src/incident/incident-notifier.service.ts +241 -0
  451. package/src/incident/incident.controller.ts +38 -0
  452. package/src/incident/incident.module.ts +19 -0
  453. package/src/incident/incident.service.spec.ts +150 -0
  454. package/src/incident/incident.service.ts +209 -0
  455. package/src/index.ts +37 -0
  456. package/src/integration-profile/dto/test.dto.ts +19 -0
  457. package/src/integration-profile/integration-profile.controller.ts +10 -1
  458. package/src/integration-profile/integration-profile.module.spec.ts +51 -0
  459. package/src/integration-profile/integration-profile.module.ts +23 -4
  460. package/src/integration-profile/integration-profile.secrets.ts +9 -1
  461. package/src/integration-profile/integration-profile.service.spec.ts +279 -0
  462. package/src/integration-profile/integration-profile.service.ts +120 -124
  463. package/src/integration-profile/integration-profile.utils.spec.ts +22 -0
  464. package/src/integration-profile/integration-profile.utils.ts +40 -3
  465. package/src/integration-profile/testers/ai.testers.ts +165 -0
  466. package/src/integration-profile/testers/captcha.testers.spec.ts +92 -0
  467. package/src/integration-profile/testers/captcha.testers.ts +139 -0
  468. package/src/integration-profile/testers/email.testers.ts +161 -0
  469. package/src/integration-profile/testers/http-probe.spec.ts +153 -0
  470. package/src/integration-profile/testers/http-probe.ts +171 -0
  471. package/src/integration-profile/testers/index.ts +30 -0
  472. package/src/integration-profile/testers/infrastructure.testers.ts +122 -0
  473. package/src/integration-profile/testers/integration-tester.registry.spec.ts +75 -0
  474. package/src/integration-profile/testers/integration-tester.registry.ts +43 -0
  475. package/src/integration-profile/testers/integration-tester.types.ts +61 -0
  476. package/src/integration-profile/testers/messaging.testers.ts +102 -0
  477. package/src/integration-profile/testers/oauth.testers.spec.ts +220 -0
  478. package/src/integration-profile/testers/oauth.testers.ts +305 -0
  479. package/src/integration-profile/testers/payment.testers.ts +185 -0
  480. package/src/integration-profile/testers/remaining.testers.spec.ts +401 -0
  481. package/src/integration-profile/testers/storage.testers.spec.ts +185 -0
  482. package/src/integration-profile/testers/storage.testers.ts +226 -0
  483. package/src/integration-profile/testers/tester-coverage.spec.ts +58 -0
  484. package/src/language/en.json +4 -2
  485. package/src/language/pt.json +4 -2
  486. package/src/leaked-password/README.md +83 -0
  487. package/src/leaked-password/leaked-password.controller.ts +52 -0
  488. package/src/leaked-password/leaked-password.module.ts +18 -0
  489. package/src/leaked-password/leaked-password.service.ts +242 -0
  490. package/src/leaked-password/seed/build-seed-sql.mjs +180 -0
  491. package/src/leaked-password/seed/common-passwords.txt +335 -0
  492. package/src/mail/dto/preview.dto.ts +50 -0
  493. package/src/mail/dto/send.dto.ts +14 -1
  494. package/src/mail/mail-template.spec.ts +197 -0
  495. package/src/mail/mail.controller.ts +9 -2
  496. package/src/mail/mail.service.spec.ts +116 -1
  497. package/src/mail/mail.service.ts +118 -12
  498. package/src/mail-layout/dto/update.dto.ts +19 -0
  499. package/src/mail-layout/mail-layout.controller.ts +47 -0
  500. package/src/mail-layout/mail-layout.module.ts +22 -0
  501. package/src/mail-layout/mail-layout.service.ts +94 -0
  502. package/src/mcp-chat/mcp-chat.service.spec.ts +236 -0
  503. package/src/mcp-chat/mcp-chat.service.ts +122 -26
  504. package/src/oauth/oauth-token-broker.service.spec.ts +172 -0
  505. package/src/oauth/oauth-token-broker.service.ts +363 -0
  506. package/src/oauth/oauth.module.ts +3 -1
  507. package/src/oauth/oauth.service.ts +8 -2
  508. package/src/pdf/pdf.service.ts +75 -0
  509. package/src/presence/presence.controller.ts +29 -0
  510. package/src/presence/presence.listener.ts +53 -0
  511. package/src/presence/presence.module.ts +19 -0
  512. package/src/presence/presence.service.spec.ts +97 -0
  513. package/src/presence/presence.service.ts +160 -0
  514. package/src/profile/dto/delete-account.dto.ts +11 -0
  515. package/src/profile/events/profile-account-deleted.event.ts +13 -0
  516. package/src/profile/profile.controller.ts +46 -34
  517. package/src/profile/profile.service.ts +138 -38
  518. package/src/realtime/realtime.gateway.ts +138 -0
  519. package/src/realtime/realtime.module.ts +16 -0
  520. package/src/realtime/realtime.service.spec.ts +50 -0
  521. package/src/realtime/realtime.service.ts +187 -0
  522. package/src/redis/redis-pubsub.ts +179 -0
  523. package/src/setting/dto/create.dto.ts +13 -2
  524. package/src/setting/setting.service.spec.ts +56 -0
  525. package/src/setting/setting.service.ts +29 -1
  526. package/src/user/dto/create-with-email-and-password.dto.ts +6 -1
  527. package/src/user/dto/query-user-mail-list.dto.ts +10 -0
  528. package/src/user/user-credential.util.ts +35 -0
  529. package/src/user/user.controller.ts +17 -2
  530. package/src/user/user.service.spec.ts +153 -0
  531. package/src/user/user.service.ts +255 -12
  532. package/src/validators/is-strong-password-with-settings.validator.ts +12 -0
  533. package/src/validators/service-locator.ts +15 -0
  534. package/src/whatsapp-sender/whatsapp-sender.module.ts +10 -0
  535. package/src/whatsapp-sender/whatsapp-sender.service.ts +313 -0
@@ -0,0 +1,122 @@
1
+ import axios from 'axios';
2
+ import { Agent } from 'node:https';
3
+ import {
4
+ assertHttpUrl,
5
+ describeHttpError,
6
+ fail,
7
+ pass,
8
+ probeJson,
9
+ requireFields,
10
+ str,
11
+ } from './http-probe';
12
+ import { IntegrationTester } from './integration-tester.types';
13
+
14
+ /**
15
+ * Testadores dos providers de infraestrutura (autoscaling).
16
+ *
17
+ * DUPLICAÇÃO INTENCIONAL: `libraries/queue/src/scaling/{digital-ocean,kubernetes-scaler}
18
+ * .service.ts` têm um `testCredentials` equivalente, batendo nos mesmos endpoints.
19
+ * Não dá para reaproveitar: `@hed-hog-pro/queue` depende do core, então o core não pode
20
+ * importá-lo de volta — e os providers `digitalocean`/`kubernetes` são semeados por uma
21
+ * migration do core, existindo mesmo em instalações sem o pacote da fila. Registrar o
22
+ * tester pela queue deixaria o botão quebrado nessas instalações. Se mudar um endpoint
23
+ * aqui, olhe o outro lado também.
24
+ */
25
+
26
+ const digitalOceanTester: IntegrationTester = {
27
+ providerSlug: 'digitalocean',
28
+ test: async (config, ctx) => {
29
+ const missing = requireFields(config, [
30
+ ['api_token', 'API token'],
31
+ ['cluster_id', 'Cluster ID'],
32
+ ]);
33
+ if (missing) return missing;
34
+
35
+ const token = String(config.api_token ?? '');
36
+ const clusterId = str(config, 'cluster_id');
37
+ const result = await probeJson(
38
+ `https://api.digitalocean.com/v2/kubernetes/clusters/${encodeURIComponent(clusterId)}`,
39
+ { headers: { Authorization: `Bearer ${token}` } },
40
+ ctx.signal,
41
+ );
42
+
43
+ if (result.status === 401) return fail('Invalid DigitalOcean API token.');
44
+ if (result.status === 403) {
45
+ return fail('This token has no permission to read Kubernetes clusters.');
46
+ }
47
+ if (result.status === 404) {
48
+ return fail(`Cluster "${clusterId}" was not found in this account.`);
49
+ }
50
+ if (!result.ok) {
51
+ return fail(describeHttpError(result, 'DigitalOcean rejected the request.'));
52
+ }
53
+
54
+ const cluster = result.body?.kubernetes_cluster ?? {};
55
+ const label = `${cluster.name ?? clusterId} (${cluster.region ?? str(config, 'region')})`;
56
+
57
+ // O pool de vídeo é escolhido por nome; se ele sumiu do cluster, o autoscaling
58
+ // falha silenciosamente depois — melhor avisar agora.
59
+ const poolName = str(config, 'video_node_pool_name');
60
+ if (poolName) {
61
+ const pools: Array<{ name?: string }> = Array.isArray(cluster.node_pools)
62
+ ? cluster.node_pools
63
+ : [];
64
+ if (pools.length > 0 && !pools.some((pool) => pool.name === poolName)) {
65
+ return pass(label, `The node pool "${poolName}" no longer exists in this cluster.`);
66
+ }
67
+ }
68
+ return pass(label);
69
+ },
70
+ };
71
+
72
+ const kubernetesTester: IntegrationTester = {
73
+ providerSlug: 'kubernetes',
74
+ test: async (config, ctx) => {
75
+ const missing = requireFields(config, [
76
+ ['api_server', 'API server'],
77
+ ['token', 'Token'],
78
+ ]);
79
+ if (missing) return missing;
80
+
81
+ const apiServer = assertHttpUrl(str(config, 'api_server'), 'API server');
82
+ const caCert = String(config.ca_cert ?? '').trim();
83
+
84
+ // Não usamos `fetch` aqui: o CA do cluster é quase sempre privado e a API de fetch
85
+ // não aceita um contexto TLS customizado.
86
+ const httpsAgent = new Agent(
87
+ caCert ? { ca: caCert } : { rejectUnauthorized: false },
88
+ );
89
+
90
+ try {
91
+ const response = await axios.get(`${apiServer.origin}/version`, {
92
+ headers: { Authorization: `Bearer ${String(config.token ?? '')}` },
93
+ httpsAgent,
94
+ signal: ctx.signal,
95
+ validateStatus: () => true,
96
+ });
97
+
98
+ if (response.status === 401) return fail('The Kubernetes token was rejected.');
99
+ if (response.status === 403) {
100
+ return fail('This token has no permission to read the cluster version.');
101
+ }
102
+ if (response.status >= 400) {
103
+ return fail(`The Kubernetes API returned HTTP ${response.status}.`);
104
+ }
105
+
106
+ const version = String(response.data?.gitVersion ?? '').trim();
107
+ return caCert
108
+ ? pass(`${apiServer.host}${version ? ` — ${version}` : ''}`)
109
+ : pass(
110
+ `${apiServer.host}${version ? ` — ${version}` : ''}`,
111
+ 'No CA certificate provided: the TLS certificate was not verified.',
112
+ );
113
+ } finally {
114
+ httpsAgent.destroy();
115
+ }
116
+ },
117
+ };
118
+
119
+ export const INFRASTRUCTURE_TESTERS: IntegrationTester[] = [
120
+ digitalOceanTester,
121
+ kubernetesTester,
122
+ ];
@@ -0,0 +1,75 @@
1
+ import { describe, expect, it, jest } from '@jest/globals';
2
+ import { IntegrationTesterRegistry } from './integration-tester.registry';
3
+ import { IntegrationTester } from './integration-tester.types';
4
+
5
+ function makeTester(providerSlug: string, info = 'ok'): IntegrationTester {
6
+ return {
7
+ providerSlug,
8
+ test: async () => ({ ok: true, info }),
9
+ };
10
+ }
11
+
12
+ describe('IntegrationTesterRegistry', () => {
13
+ it('registra e recupera um tester pelo slug do provider', () => {
14
+ const registry = new IntegrationTesterRegistry();
15
+ const tester = makeTester('smtp');
16
+
17
+ registry.register(tester);
18
+
19
+ expect(registry.find('smtp')).toBe(tester);
20
+ expect(registry.has('smtp')).toBe(true);
21
+ expect(registry.list()).toEqual(['smtp']);
22
+ });
23
+
24
+ it('normaliza o slug (case e espaços) na escrita e na leitura', () => {
25
+ const registry = new IntegrationTesterRegistry();
26
+ registry.register(makeTester(' S3-Compatible '));
27
+
28
+ expect(registry.find('s3-compatible')).not.toBeNull();
29
+ expect(registry.find('S3-COMPATIBLE')).not.toBeNull();
30
+ });
31
+
32
+ it('devolve null para provider desconhecido, nulo ou vazio', () => {
33
+ const registry = new IntegrationTesterRegistry();
34
+
35
+ expect(registry.find('inexistente')).toBeNull();
36
+ expect(registry.find(null)).toBeNull();
37
+ expect(registry.find(undefined)).toBeNull();
38
+ expect(registry.find('')).toBeNull();
39
+ expect(registry.has('inexistente')).toBe(false);
40
+ });
41
+
42
+ it('avisa ao sobrescrever um tester já registrado, mas aceita a substituição', () => {
43
+ const registry = new IntegrationTesterRegistry();
44
+ const warn = jest
45
+ .spyOn((registry as any).logger, 'warn')
46
+ .mockImplementation(() => undefined);
47
+
48
+ const first = makeTester('stripe', 'primeiro');
49
+ const second = makeTester('stripe', 'segundo');
50
+ registry.register(first);
51
+ registry.register(second);
52
+
53
+ expect(warn).toHaveBeenCalledWith(
54
+ 'Integration tester for provider "stripe" was overwritten.',
55
+ );
56
+ expect(registry.find('stripe')).toBe(second);
57
+ });
58
+
59
+ it('recusa um tester sem providerSlug', () => {
60
+ const registry = new IntegrationTesterRegistry();
61
+
62
+ expect(() => registry.register({} as IntegrationTester)).toThrow(
63
+ 'Integration tester requires a providerSlug.',
64
+ );
65
+ });
66
+
67
+ it('lista os providers registrados em ordem alfabética', () => {
68
+ const registry = new IntegrationTesterRegistry();
69
+ ['stripe', 'azure-blob', 'openai'].forEach((slug) =>
70
+ registry.register(makeTester(slug)),
71
+ );
72
+
73
+ expect(registry.list()).toEqual(['azure-blob', 'openai', 'stripe']);
74
+ });
75
+ });
@@ -0,0 +1,43 @@
1
+ import { Injectable, Logger } from '@nestjs/common';
2
+ import { IntegrationTester } from './integration-tester.types';
3
+
4
+ /**
5
+ * Registro dos testadores de conexão, no mesmo padrão do WebhookProtocolRegistry e do
6
+ * FiscalProviderRegistry: os testers embutidos entram no boot do IntegrationProfileModule
7
+ * e libraries externas registram os seus (é assim que a `fiscal` pluga o nfse-national,
8
+ * que precisa abrir o certificado A1 — código que não pode viver no core).
9
+ */
10
+ @Injectable()
11
+ export class IntegrationTesterRegistry {
12
+ private readonly logger = new Logger(IntegrationTesterRegistry.name);
13
+ private readonly testers = new Map<string, IntegrationTester>();
14
+
15
+ register(tester: IntegrationTester): void {
16
+ const key = normalizeSlug(tester?.providerSlug);
17
+ if (!key) throw new Error('Integration tester requires a providerSlug.');
18
+
19
+ if (this.testers.has(key)) {
20
+ this.logger.warn(`Integration tester for provider "${key}" was overwritten.`);
21
+ }
22
+
23
+ this.testers.set(key, tester);
24
+ }
25
+
26
+ find(providerSlug: string | null | undefined): IntegrationTester | null {
27
+ const key = normalizeSlug(providerSlug);
28
+ return key ? (this.testers.get(key) ?? null) : null;
29
+ }
30
+
31
+ has(providerSlug: string | null | undefined): boolean {
32
+ return this.find(providerSlug) !== null;
33
+ }
34
+
35
+ /** Providers com teste disponível (para a UI decidir se mostra o botão). */
36
+ list(): string[] {
37
+ return [...this.testers.keys()].sort();
38
+ }
39
+ }
40
+
41
+ function normalizeSlug(slug: string | null | undefined): string {
42
+ return String(slug ?? '').trim().toLowerCase();
43
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Contrato dos testadores de conexão dos Perfis de Integração.
3
+ *
4
+ * Cada provider (smtp, s3, stripe, google-oauth, …) implementa um `IntegrationTester`
5
+ * que faz uma chamada verificável contra o serviço real e devolve um veredito. O
6
+ * `IntegrationProfileService.test()` só despacha; nenhum `if (provider === 'x')` sobra lá.
7
+ *
8
+ * Os testers são objetos literais sem estado (mesmo estilo de integration-profile.utils.ts),
9
+ * não providers do Nest: assim cada spec é um teste puro de função com `fetch` mockado.
10
+ */
11
+
12
+ /** Timeout padrão de um teste de conexão. */
13
+ export const INTEGRATION_TEST_TIMEOUT_MS = 10_000;
14
+
15
+ export type IntegrationTestOutcome = {
16
+ ok: boolean;
17
+ /**
18
+ * Evidência legível do que foi verificado (nome do bucket, da conta, do cluster…).
19
+ * NUNCA pode conter segredo: vai para a UI e é gravada no config do perfil.
20
+ */
21
+ info?: string;
22
+ /** Motivo legível da falha. NUNCA contém segredo nem stack trace. */
23
+ error?: string;
24
+ /**
25
+ * Credencial válida, mas algo secundário não pôde ser comprovado (domínio não
26
+ * verificado, service account sem acesso ao app, pool inexistente). Não reprova.
27
+ */
28
+ warning?: string;
29
+ };
30
+
31
+ export type IntegrationTestContext = {
32
+ /** Já combinado com o timeout do tester. Repassar a TODA chamada de rede. */
33
+ signal: AbortSignal;
34
+ /** Slug do integration_type (email, storage, oauth, …). */
35
+ typeSlug: string;
36
+ /** Slug do provider sendo testado. */
37
+ providerSlug: string;
38
+ /**
39
+ * Valores dos segredos deste perfil, usados só para redigir mensagens de erro
40
+ * (algumas APIs ecoam a entrada de volta). Nunca logar nem devolver.
41
+ */
42
+ secretValues: string[];
43
+ };
44
+
45
+ export interface IntegrationTester {
46
+ /** Slug do integration_provider que esta implementação atende. */
47
+ readonly providerSlug: string;
48
+ /** Timeout específico deste provider (default INTEGRATION_TEST_TIMEOUT_MS). */
49
+ readonly timeoutMs?: number;
50
+ /**
51
+ * `config` chega DECIFRADO e já mesclado com os segredos armazenados
52
+ * ("deixe em branco para manter"), então o tester nunca vê a máscara.
53
+ *
54
+ * Não deve lançar: devolve `{ ok: false, error }`. Exceções que escaparem viram
55
+ * `ok: false` com a mensagem sanitizada no dispatcher.
56
+ */
57
+ test(
58
+ config: Record<string, unknown>,
59
+ ctx: IntegrationTestContext,
60
+ ): Promise<IntegrationTestOutcome>;
61
+ }
@@ -0,0 +1,102 @@
1
+ import { buildWhatsappOfficialConfigFromIntegration } from '../integration-profile.utils';
2
+ import {
3
+ assertHttpUrl,
4
+ describeHttpError,
5
+ fail,
6
+ pass,
7
+ probeJson,
8
+ requireFields,
9
+ str,
10
+ } from './http-probe';
11
+ import { IntegrationTester } from './integration-tester.types';
12
+
13
+ const evolutionApiTester: IntegrationTester = {
14
+ providerSlug: 'evolution-api',
15
+ test: async (config, ctx) => {
16
+ const missing = requireFields(config, [
17
+ ['host', 'Evolution API host'],
18
+ ['token', 'Evolution API token'],
19
+ ['instance_name', 'Instance name'],
20
+ ]);
21
+ if (missing) return missing;
22
+
23
+ const base = assertHttpUrl(str(config, 'host'), 'Evolution API host');
24
+ const instance = str(config, 'instance_name');
25
+ const url = `${base.origin}/instance/connectionState/${encodeURIComponent(instance)}`;
26
+
27
+ const result = await probeJson(
28
+ url,
29
+ { headers: { apikey: String(config.token ?? '') } },
30
+ ctx.signal,
31
+ );
32
+
33
+ if (result.status === 401 || result.status === 403) {
34
+ return fail('Invalid Evolution API token.');
35
+ }
36
+ if (result.status === 404) {
37
+ return fail(`Instance "${instance}" was not found on this Evolution API server.`);
38
+ }
39
+ if (!result.ok) {
40
+ return fail(describeHttpError(result, 'Evolution API rejected the request.'));
41
+ }
42
+
43
+ const state = String(
44
+ result.body?.instance?.state ?? result.body?.state ?? '',
45
+ ).trim();
46
+
47
+ // Credencial válida mas sessão desconectada: o perfil está certo e o QR code é
48
+ // outro problema — avisar sem reprovar.
49
+ if (state && state !== 'open') {
50
+ return pass(
51
+ `${instance} — ${state}`,
52
+ `The instance is not connected (state: ${state}). Scan the QR code in Evolution API.`,
53
+ );
54
+ }
55
+ return pass(`${instance}${state ? ` — ${state}` : ''}`);
56
+ },
57
+ };
58
+
59
+ /**
60
+ * Valida um perfil whatsapp-official contra a Graph API (lê o WABA com o token).
61
+ * Nunca devolve o token/secret na resposta.
62
+ */
63
+ const whatsappOfficialTester: IntegrationTester = {
64
+ providerSlug: 'whatsapp-official',
65
+ test: async (config, ctx) => {
66
+ const cfg = buildWhatsappOfficialConfigFromIntegration(config);
67
+
68
+ if (!cfg.accessToken) return fail('WhatsApp access token is required.');
69
+ if (!cfg.wabaId) return fail('WhatsApp Business Account ID is required.');
70
+ if (!cfg.appSecret) {
71
+ return fail('Meta App Secret is required to validate webhook signatures.');
72
+ }
73
+ if (!cfg.verifyToken) return fail('Webhook verify token is required.');
74
+
75
+ const url = `https://graph.facebook.com/${cfg.graphApiVersion}/${encodeURIComponent(
76
+ cfg.wabaId,
77
+ )}?fields=id,name`;
78
+
79
+ const result = await probeJson(
80
+ url,
81
+ { headers: { Authorization: `Bearer ${cfg.accessToken}` } },
82
+ ctx.signal,
83
+ );
84
+
85
+ if (!result.ok) {
86
+ // A mensagem da Meta não contém o token; ainda assim só propagamos o texto dela.
87
+ return fail(
88
+ `WhatsApp validation failed: ${describeHttpError(
89
+ result,
90
+ 'Graph API rejected the request.',
91
+ )}`,
92
+ );
93
+ }
94
+
95
+ return pass(String(result.body?.name ?? '') || cfg.wabaId);
96
+ },
97
+ };
98
+
99
+ export const MESSAGING_TESTERS: IntegrationTester[] = [
100
+ evolutionApiTester,
101
+ whatsappOfficialTester,
102
+ ];
@@ -0,0 +1,220 @@
1
+ import { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals';
2
+ import { OAUTH_TESTERS } from './oauth.testers';
3
+ import { IntegrationTestContext, IntegrationTester } from './integration-tester.types';
4
+
5
+ const bySlug = (slug: string): IntegrationTester =>
6
+ OAUTH_TESTERS.find((tester) => tester.providerSlug === slug)!;
7
+
8
+ const ctx = (): IntegrationTestContext => ({
9
+ signal: AbortSignal.timeout(5_000),
10
+ typeSlug: 'oauth',
11
+ providerSlug: 'test',
12
+ secretValues: [],
13
+ });
14
+
15
+ /** Resposta JSON crua, como `probeJson` a consome (via response.text()). */
16
+ function jsonResponse(body: unknown, status = 200) {
17
+ return {
18
+ ok: status >= 200 && status < 300,
19
+ status,
20
+ text: async () => JSON.stringify(body),
21
+ } as unknown as Response;
22
+ }
23
+
24
+ let fetchMock: jest.Mock;
25
+
26
+ beforeEach(() => {
27
+ fetchMock = jest.fn();
28
+ global.fetch = fetchMock as unknown as typeof fetch;
29
+ });
30
+
31
+ afterEach(() => {
32
+ jest.restoreAllMocks();
33
+ });
34
+
35
+ describe('google-oauth tester', () => {
36
+ const tester = bySlug('google-oauth');
37
+
38
+ it('aprova quando o Google recusa apenas o código de teste (invalid_grant)', async () => {
39
+ fetchMock.mockResolvedValue(jsonResponse({ error: 'invalid_grant' }, 400));
40
+
41
+ const outcome = await tester.test(
42
+ { client_id: 'id', client_secret: 'secret' },
43
+ ctx(),
44
+ );
45
+
46
+ expect(outcome.ok).toBe(true);
47
+ });
48
+
49
+ it('reprova quando o Google recusa as credenciais do app (invalid_client)', async () => {
50
+ fetchMock.mockResolvedValue(jsonResponse({ error: 'invalid_client' }, 401));
51
+
52
+ const outcome = await tester.test(
53
+ { client_id: 'id', client_secret: 'wrong' },
54
+ ctx(),
55
+ );
56
+
57
+ expect(outcome).toEqual({
58
+ ok: false,
59
+ error: 'Invalid Client ID or Client secret.',
60
+ });
61
+ });
62
+
63
+ it('reprova sem ir à rede quando falta uma credencial', async () => {
64
+ const outcome = await tester.test({ client_id: 'id' }, ctx());
65
+
66
+ expect(outcome.ok).toBe(false);
67
+ expect(outcome.error).toBe('Client secret is required.');
68
+ expect(fetchMock).not.toHaveBeenCalled();
69
+ });
70
+ });
71
+
72
+ describe('github-oauth tester', () => {
73
+ const tester = bySlug('github-oauth');
74
+
75
+ it('aprova em bad_verification_code e reprova em incorrect_client_credentials', async () => {
76
+ fetchMock.mockResolvedValueOnce(
77
+ jsonResponse({ error: 'bad_verification_code' }),
78
+ );
79
+ await expect(
80
+ tester.test({ client_id: 'a', client_secret: 'b' }, ctx()),
81
+ ).resolves.toMatchObject({ ok: true });
82
+
83
+ fetchMock.mockResolvedValueOnce(
84
+ jsonResponse({ error: 'incorrect_client_credentials' }),
85
+ );
86
+ await expect(
87
+ tester.test({ client_id: 'a', client_secret: 'b' }, ctx()),
88
+ ).resolves.toMatchObject({ ok: false });
89
+ });
90
+ });
91
+
92
+ describe('facebook-oauth tester', () => {
93
+ const tester = bySlug('facebook-oauth');
94
+
95
+ it('aprova quando recebe um app token real', async () => {
96
+ fetchMock.mockResolvedValue(jsonResponse({ access_token: 'app-token' }));
97
+
98
+ await expect(
99
+ tester.test({ client_id: 'a', client_secret: 'b' }, ctx()),
100
+ ).resolves.toMatchObject({ ok: true });
101
+ });
102
+
103
+ it('reprova quando a Meta rejeita', async () => {
104
+ fetchMock.mockResolvedValue(
105
+ jsonResponse({ error: { message: 'Invalid appsecret' } }, 400),
106
+ );
107
+
108
+ await expect(
109
+ tester.test({ client_id: 'a', client_secret: 'b' }, ctx()),
110
+ ).resolves.toMatchObject({ ok: false, error: 'Invalid appsecret' });
111
+ });
112
+ });
113
+
114
+ describe('microsoft-oauth tester', () => {
115
+ const tester = bySlug('microsoft-oauth');
116
+
117
+ it('aprova quando o client_credentials devolve token', async () => {
118
+ fetchMock.mockResolvedValue(jsonResponse({ access_token: 'token' }));
119
+
120
+ const outcome = await tester.test(
121
+ { client_id: 'a', client_secret: 'b', tenant_id: 'contoso' },
122
+ ctx(),
123
+ );
124
+
125
+ expect(outcome.ok).toBe(true);
126
+ expect(outcome.info).toContain('contoso');
127
+ });
128
+
129
+ it.each([
130
+ ['AADSTS7000215', 'Invalid client secret.'],
131
+ ['AADSTS700016', 'Application not found in tenant "contoso".'],
132
+ ['AADSTS90002', 'Tenant "contoso" does not exist.'],
133
+ ['AADSTS7000222', 'The client secret has expired.'],
134
+ ])('traduz %s numa mensagem acionável', async (code, expected) => {
135
+ fetchMock.mockResolvedValue(
136
+ jsonResponse(
137
+ {
138
+ error: 'invalid_client',
139
+ error_description: `${code}: long Microsoft blurb with correlation id and a help URL`,
140
+ },
141
+ 401,
142
+ ),
143
+ );
144
+
145
+ const outcome = await tester.test(
146
+ { client_id: 'a', client_secret: 'b', tenant_id: 'contoso' },
147
+ ctx(),
148
+ );
149
+
150
+ expect(outcome).toEqual({ ok: false, error: expected });
151
+ });
152
+
153
+ it('sem tenant_id, não reprova o app quando o endpoint "common" recusa client_credentials', async () => {
154
+ fetchMock.mockResolvedValue(
155
+ jsonResponse(
156
+ { error_description: 'AADSTS900023: tenant common is not supported' },
157
+ 400,
158
+ ),
159
+ );
160
+
161
+ const outcome = await tester.test({ client_id: 'a', client_secret: 'b' }, ctx());
162
+
163
+ expect(outcome.ok).toBe(true);
164
+ expect(outcome.warning).toContain('Tenant ID');
165
+ });
166
+
167
+ it('está registrado também para microsoft-entra-id-oauth', () => {
168
+ expect(bySlug('microsoft-entra-id-oauth')).toBeDefined();
169
+ });
170
+ });
171
+
172
+ describe('apple-oauth tester', () => {
173
+ const tester = bySlug('apple-oauth');
174
+
175
+ it('reprova sem ir à rede quando a chave .p8 não assina', async () => {
176
+ const outcome = await tester.test(
177
+ {
178
+ client_id: 'com.acme.service',
179
+ team_id: 'TEAM123',
180
+ key_id: 'KEY123',
181
+ private_key: 'não é uma chave EC válida',
182
+ },
183
+ ctx(),
184
+ );
185
+
186
+ expect(outcome.ok).toBe(false);
187
+ expect(outcome.error).toContain('Could not sign with the private key');
188
+ expect(fetchMock).not.toHaveBeenCalled();
189
+ });
190
+ });
191
+
192
+ describe('linkedin-oauth tester', () => {
193
+ const tester = bySlug('linkedin-oauth');
194
+
195
+ it('aprova quando o LinkedIn só reclama do código', async () => {
196
+ fetchMock.mockResolvedValue(
197
+ jsonResponse(
198
+ { error: 'invalid_request', error_description: 'Bad authorization code' },
199
+ 400,
200
+ ),
201
+ );
202
+
203
+ await expect(
204
+ tester.test({ client_id: 'a', client_secret: 'b' }, ctx()),
205
+ ).resolves.toMatchObject({ ok: true });
206
+ });
207
+
208
+ it('reprova quando o LinkedIn reclama do client', async () => {
209
+ fetchMock.mockResolvedValue(
210
+ jsonResponse(
211
+ { error: 'invalid_client', error_description: 'Client authentication failed' },
212
+ 401,
213
+ ),
214
+ );
215
+
216
+ await expect(
217
+ tester.test({ client_id: 'a', client_secret: 'b' }, ctx()),
218
+ ).resolves.toMatchObject({ ok: false });
219
+ });
220
+ });