@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,139 @@
1
+ import { createHmac } from 'node:crypto';
2
+ import { fail, pass, probeJson, requireFields, str } from './http-probe';
3
+ import { IntegrationTester } from './integration-tester.types';
4
+
5
+ /**
6
+ * Testadores dos providers de captcha.
7
+ *
8
+ * Um captcha só é resolvido por um humano no navegador, então não há token válido para
9
+ * enviar aqui. O truque é que ambos os endpoints de `siteverify` validam o SEGREDO antes
10
+ * do token: mandamos um token vazio e lemos qual das duas reclamações voltou.
11
+ *
12
+ * invalid-input-secret → segredo errado → REPROVA
13
+ * invalid-input-response → segredo aceito, faltou só o token (era o esperado) → APROVA
14
+ */
15
+
16
+ const recaptchaTester: IntegrationTester = {
17
+ providerSlug: 'recaptcha',
18
+ test: async (config, ctx) => {
19
+ const missing = requireFields(config, [
20
+ ['site_key', 'Site key'],
21
+ ['secret_key', 'Secret key'],
22
+ ]);
23
+ if (missing) return missing;
24
+
25
+ const result = await probeJson(
26
+ 'https://www.google.com/recaptcha/api/siteverify',
27
+ {
28
+ method: 'POST',
29
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
30
+ body: new URLSearchParams({
31
+ secret: String(config.secret_key ?? ''),
32
+ response: '',
33
+ }).toString(),
34
+ },
35
+ ctx.signal,
36
+ );
37
+
38
+ const codes: string[] = Array.isArray(result.body?.['error-codes'])
39
+ ? result.body['error-codes']
40
+ : [];
41
+
42
+ if (codes.includes('invalid-input-secret')) {
43
+ return fail('Invalid reCAPTCHA secret key.');
44
+ }
45
+ if (codes.includes('missing-input-secret')) {
46
+ return fail('reCAPTCHA secret key is required.');
47
+ }
48
+ if (
49
+ codes.includes('missing-input-response') ||
50
+ codes.includes('invalid-input-response')
51
+ ) {
52
+ return pass('Google accepted the reCAPTCHA secret key');
53
+ }
54
+ if (!result.ok) {
55
+ return fail(`Google returned HTTP ${result.status}.`);
56
+ }
57
+ return pass('Google accepted the reCAPTCHA secret key');
58
+ },
59
+ };
60
+
61
+ const turnstileTester: IntegrationTester = {
62
+ providerSlug: 'cloudflare-turnstile',
63
+ test: async (config, ctx) => {
64
+ const missing = requireFields(config, [
65
+ ['site_key', 'Site key'],
66
+ ['secret_key', 'Secret key'],
67
+ ]);
68
+ if (missing) return missing;
69
+
70
+ const result = await probeJson(
71
+ 'https://challenges.cloudflare.com/turnstile/v0/siteverify',
72
+ {
73
+ method: 'POST',
74
+ headers: { 'Content-Type': 'application/json' },
75
+ body: JSON.stringify({
76
+ secret: String(config.secret_key ?? ''),
77
+ response: 'hedhog-connection-test',
78
+ }),
79
+ },
80
+ ctx.signal,
81
+ );
82
+
83
+ const codes: string[] = Array.isArray(result.body?.['error-codes'])
84
+ ? result.body['error-codes']
85
+ : [];
86
+
87
+ if (codes.includes('invalid-input-secret')) {
88
+ return fail('Invalid Turnstile secret key.');
89
+ }
90
+ if (codes.includes('missing-input-secret')) {
91
+ return fail('Turnstile secret key is required.');
92
+ }
93
+ if (
94
+ codes.includes('invalid-input-response') ||
95
+ codes.includes('missing-input-response')
96
+ ) {
97
+ return pass('Cloudflare accepted the Turnstile secret key');
98
+ }
99
+ if (!result.ok) {
100
+ return fail(`Cloudflare returned HTTP ${result.status}.`);
101
+ }
102
+ return pass('Cloudflare accepted the Turnstile secret key');
103
+ },
104
+ };
105
+
106
+ const altchaTester: IntegrationTester = {
107
+ providerSlug: 'altcha',
108
+ test: async (config) => {
109
+ const missing = requireFields(config, [['hmac_key', 'HMAC key']]);
110
+ if (missing) return missing;
111
+
112
+ const hmacKey = String(config.hmac_key ?? '');
113
+ if (hmacKey.length < 16) {
114
+ return fail('The HMAC key is too short — use at least 16 characters.');
115
+ }
116
+
117
+ // Altcha é self-hosted: não existe endpoint remoto para validar a chave. O que dá
118
+ // para provar é que ela gera um desafio assinado, que é o uso dela em produção.
119
+ try {
120
+ const challenge = createHmac('sha256', hmacKey)
121
+ .update('hedhog-connection-test')
122
+ .digest('hex');
123
+ if (!challenge) throw new Error('empty digest');
124
+ } catch {
125
+ return fail('Could not sign a challenge with this HMAC key.');
126
+ }
127
+
128
+ return pass(
129
+ 'HMAC key is usable',
130
+ 'Altcha is self-hosted: the key was validated locally, with no remote check.',
131
+ );
132
+ },
133
+ };
134
+
135
+ export const CAPTCHA_TESTERS: IntegrationTester[] = [
136
+ recaptchaTester,
137
+ turnstileTester,
138
+ altchaTester,
139
+ ];
@@ -0,0 +1,161 @@
1
+ import { verifySesCredentials, verifySmtpConnection } from '@hed-hog/api-mail';
2
+ import {
3
+ describeHttpError,
4
+ fail,
5
+ pass,
6
+ probeJson,
7
+ requireFields,
8
+ str,
9
+ } from './http-probe';
10
+ import { IntegrationTester } from './integration-tester.types';
11
+
12
+ /**
13
+ * Testadores dos providers de e-mail.
14
+ *
15
+ * Todos exigem `from_email`: sem remetente o perfil não envia nada, e essa validação
16
+ * já era o contrato do teste antes de existirem chamadas de rede.
17
+ */
18
+
19
+ const smtpTester: IntegrationTester = {
20
+ providerSlug: 'smtp',
21
+ test: async (config) => {
22
+ const missing = requireFields(config, [
23
+ ['host', 'SMTP host'],
24
+ ['from_email', 'Sender email'],
25
+ ]);
26
+ if (missing) return missing;
27
+
28
+ const result = await verifySmtpConnection({
29
+ host: str(config, 'host'),
30
+ port: Number(config.port ?? 587),
31
+ secure: Boolean(config.secure),
32
+ username: str(config, 'username'),
33
+ password: String(config.password ?? ''),
34
+ timeoutMs: 8_000,
35
+ });
36
+
37
+ return result.ok ? pass(result.info) : fail(result.error!);
38
+ },
39
+ };
40
+
41
+ const sesTester: IntegrationTester = {
42
+ providerSlug: 'ses',
43
+ test: async (config, ctx) => {
44
+ const missing = requireFields(config, [
45
+ ['region', 'AWS region'],
46
+ ['access_key_id', 'Access key ID'],
47
+ ['secret_access_key', 'Secret access key'],
48
+ ['from_email', 'Sender email'],
49
+ ]);
50
+ if (missing) return missing;
51
+
52
+ const result = await verifySesCredentials({
53
+ region: str(config, 'region'),
54
+ accessKeyId: str(config, 'access_key_id'),
55
+ secretAccessKey: String(config.secret_access_key ?? ''),
56
+ signal: ctx.signal,
57
+ });
58
+
59
+ return result.ok ? pass(result.info) : fail(result.error!);
60
+ },
61
+ };
62
+
63
+ const gmailTester: IntegrationTester = {
64
+ providerSlug: 'gmail',
65
+ test: async (config, ctx) => {
66
+ const missing = requireFields(config, [
67
+ ['client_id', 'Client ID'],
68
+ ['client_secret', 'Client secret'],
69
+ ['refresh_token', 'Refresh token'],
70
+ ['from_email', 'Sender email'],
71
+ ]);
72
+ if (missing) return missing;
73
+
74
+ // Troca real do refresh token: separa credencial de app errada (invalid_client)
75
+ // de autorização revogada pelo usuário (invalid_grant).
76
+ const result = await probeJson(
77
+ 'https://oauth2.googleapis.com/token',
78
+ {
79
+ method: 'POST',
80
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
81
+ body: new URLSearchParams({
82
+ client_id: str(config, 'client_id'),
83
+ client_secret: String(config.client_secret ?? ''),
84
+ refresh_token: String(config.refresh_token ?? ''),
85
+ grant_type: 'refresh_token',
86
+ }).toString(),
87
+ },
88
+ ctx.signal,
89
+ );
90
+
91
+ if (result.ok) {
92
+ return pass(`Gmail authorized for ${str(config, 'from_email')}`);
93
+ }
94
+
95
+ const code = String(result.body?.error ?? '');
96
+ if (code === 'invalid_client') {
97
+ return fail('Invalid Client ID or Client secret.');
98
+ }
99
+ if (code === 'invalid_grant') {
100
+ return fail(
101
+ 'The refresh token is invalid or was revoked. Authorize the account again.',
102
+ );
103
+ }
104
+ return fail(describeHttpError(result, 'Google rejected the credentials.'));
105
+ },
106
+ };
107
+
108
+ const resendTester: IntegrationTester = {
109
+ providerSlug: 'resend',
110
+ test: async (config, ctx) => {
111
+ const missing = requireFields(config, [
112
+ ['api_token', 'Resend API token'],
113
+ ['domain', 'Resend sending domain'],
114
+ ]);
115
+ if (missing) return missing;
116
+
117
+ const domain = str(config, 'domain').toLowerCase();
118
+ const result = await probeJson(
119
+ 'https://api.resend.com/domains',
120
+ { headers: { Authorization: `Bearer ${String(config.api_token ?? '')}` } },
121
+ ctx.signal,
122
+ );
123
+
124
+ if (result.status === 401 || result.status === 403) {
125
+ return fail('Invalid Resend API token.');
126
+ }
127
+ if (!result.ok) {
128
+ return fail(describeHttpError(result, 'Resend rejected the credentials.'));
129
+ }
130
+
131
+ const domains: Array<{ name?: string; status?: string }> = Array.isArray(
132
+ result.body?.data,
133
+ )
134
+ ? result.body.data
135
+ : [];
136
+ const match = domains.find(
137
+ (item) => String(item?.name ?? '').toLowerCase() === domain,
138
+ );
139
+
140
+ if (!match) {
141
+ return pass(
142
+ `Resend token is valid (${domains.length} domain(s))`,
143
+ `The domain "${domain}" is not registered in this Resend account.`,
144
+ );
145
+ }
146
+ if (String(match.status ?? '').toLowerCase() !== 'verified') {
147
+ return pass(
148
+ `Resend token is valid — ${domain}`,
149
+ `The domain "${domain}" is not verified yet (status: ${match.status}).`,
150
+ );
151
+ }
152
+ return pass(`Resend — ${domain} (verified)`);
153
+ },
154
+ };
155
+
156
+ export const EMAIL_TESTERS: IntegrationTester[] = [
157
+ smtpTester,
158
+ sesTester,
159
+ gmailTester,
160
+ resendTester,
161
+ ];
@@ -0,0 +1,153 @@
1
+ import { describe, expect, it } from '@jest/globals';
2
+ import {
3
+ assertHttpUrl,
4
+ describeHttpError,
5
+ redactSecrets,
6
+ requireFields,
7
+ sanitizeTesterError,
8
+ str,
9
+ } from './http-probe';
10
+
11
+ describe('sanitizeTesterError', () => {
12
+ it('nunca inclui o stack trace, só a mensagem', () => {
13
+ const error = new Error('Something specific went wrong');
14
+ error.stack = 'Error: secret-laden stack\n at somewhere.ts:1:1';
15
+
16
+ const message = sanitizeTesterError(error, []);
17
+
18
+ expect(message).toBe('Something specific went wrong');
19
+ expect(message).not.toContain('at somewhere.ts');
20
+ });
21
+
22
+ it('redige todos os valores de segredo, inclusive quando a API ecoa a entrada', () => {
23
+ const secret = 'sk_live_51H8xVeryLongToken';
24
+ const other = 'another-long-secret';
25
+ const error = new Error(
26
+ `Provider rejected key ${secret} and app secret ${other}.`,
27
+ );
28
+
29
+ const message = sanitizeTesterError(error, [secret, other]);
30
+
31
+ expect(message).not.toContain(secret);
32
+ expect(message).not.toContain(other);
33
+ expect(message).toContain('***');
34
+ });
35
+
36
+ it('ignora segredos curtos demais para não picotar a mensagem inteira', () => {
37
+ const message = sanitizeTesterError(new Error('bad host name'), ['a', 'ho']);
38
+
39
+ expect(message).toBe('bad host name');
40
+ });
41
+
42
+ it('usa um texto próprio para timeout, distinto de credencial inválida', () => {
43
+ const abort = new Error('The operation was aborted');
44
+ abort.name = 'AbortError';
45
+
46
+ const message = sanitizeTesterError(abort, [], 'api.example.com');
47
+
48
+ expect(message).toContain('Timed out');
49
+ expect(message).toContain('api.example.com');
50
+ expect(message).toContain('outbound network access');
51
+ });
52
+
53
+ it('traduz os códigos de rede mais comuns', () => {
54
+ const cases: Array<[string, string]> = [
55
+ ['ENOTFOUND', 'Host not found'],
56
+ ['ECONNREFUSED', 'Connection refused'],
57
+ ['ECONNRESET', 'Connection interrupted'],
58
+ ['CERT_HAS_EXPIRED', 'certificate has expired'],
59
+ ['DEPTH_ZERO_SELF_SIGNED_CERT', 'could not be verified'],
60
+ ];
61
+
62
+ for (const [code, expected] of cases) {
63
+ const error = Object.assign(new Error('raw driver noise'), { code });
64
+ expect(sanitizeTesterError(error, [])).toContain(expected);
65
+ }
66
+ });
67
+
68
+ it('trunca mensagens muito longas', () => {
69
+ const message = sanitizeTesterError(new Error('x'.repeat(1_000)), []);
70
+
71
+ expect(message.length).toBeLessThanOrEqual(300);
72
+ expect(message.endsWith('…')).toBe(true);
73
+ });
74
+
75
+ it('lida com valores que não são Error', () => {
76
+ expect(sanitizeTesterError('plain string failure', [])).toBe(
77
+ 'plain string failure',
78
+ );
79
+ expect(sanitizeTesterError(null, [])).toBe('Unexpected error.');
80
+ });
81
+ });
82
+
83
+ describe('redactSecrets', () => {
84
+ it('substitui todas as ocorrências de um mesmo segredo', () => {
85
+ const secret = 'super-secret-token';
86
+
87
+ expect(redactSecrets(`${secret} and ${secret}`, [secret])).toBe('*** and ***');
88
+ });
89
+ });
90
+
91
+ describe('assertHttpUrl', () => {
92
+ it('aceita http e https, incluindo endereços de rede privada', () => {
93
+ expect(assertHttpUrl('https://api.example.com/x', 'Endpoint').host).toBe(
94
+ 'api.example.com',
95
+ );
96
+ // k8s e Evolution self-hosted vivem em rede interna: bloqueá-los quebraria o caso de uso.
97
+ expect(assertHttpUrl('https://10.0.0.1:6443', 'API server').port).toBe('6443');
98
+ });
99
+
100
+ it('rejeita esquemas fora de http/https e URLs inválidas', () => {
101
+ expect(() => assertHttpUrl('file:///etc/passwd', 'Endpoint')).toThrow(
102
+ 'Endpoint must use http or https.',
103
+ );
104
+ expect(() => assertHttpUrl('não é url', 'Endpoint')).toThrow(
105
+ 'Endpoint is not a valid URL.',
106
+ );
107
+ });
108
+ });
109
+
110
+ describe('requireFields', () => {
111
+ it('devolve null quando todos os campos estão preenchidos', () => {
112
+ expect(requireFields({ host: 'h', token: 't' }, [
113
+ ['host', 'Host'],
114
+ ['token', 'Token'],
115
+ ])).toBeNull();
116
+ });
117
+
118
+ it('reprova no primeiro campo vazio, em branco ou ausente', () => {
119
+ expect(requireFields({ host: ' ' }, [['host', 'Host']])).toEqual({
120
+ ok: false,
121
+ error: 'Host is required.',
122
+ });
123
+ expect(requireFields({}, [['token', 'Token']])).toEqual({
124
+ ok: false,
125
+ error: 'Token is required.',
126
+ });
127
+ });
128
+ });
129
+
130
+ describe('str', () => {
131
+ it('normaliza para string trimada, com fallback vazio', () => {
132
+ expect(str({ a: ' x ' }, 'a')).toBe('x');
133
+ expect(str({}, 'a')).toBe('');
134
+ expect(str({ a: 42 }, 'a')).toBe('42');
135
+ });
136
+ });
137
+
138
+ describe('describeHttpError', () => {
139
+ it('encontra a mensagem nos formatos usados pelos provedores', () => {
140
+ const base = { ok: false, status: 400, text: '' };
141
+
142
+ expect(describeHttpError({ ...base, body: { error: { message: 'a' } } }, 'f')).toBe('a');
143
+ expect(describeHttpError({ ...base, body: { error_description: 'b' } }, 'f')).toBe('b');
144
+ expect(describeHttpError({ ...base, body: { message: 'c' } }, 'f')).toBe('c');
145
+ expect(describeHttpError({ ...base, body: { error: 'd' } }, 'f')).toBe('d');
146
+ });
147
+
148
+ it('cai no fallback com o status quando não há mensagem reconhecível', () => {
149
+ expect(
150
+ describeHttpError({ ok: false, status: 503, body: {}, text: '' }, 'Provider down.'),
151
+ ).toBe('Provider down. (HTTP 503)');
152
+ });
153
+ });
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Utilidades compartilhadas pelos testadores de conexão.
3
+ *
4
+ * Concentra as três coisas que todo tester precisa acertar e que são fáceis de errar
5
+ * caso a caso: respeitar o timeout, não vazar segredo na mensagem de erro e traduzir
6
+ * falha de rede em texto que o operador entenda.
7
+ */
8
+ import { IntegrationTestOutcome } from './integration-tester.types';
9
+
10
+ /** Tamanho máximo de uma mensagem devolvida à UI (ela também é persistida no config). */
11
+ const MAX_ERROR_LENGTH = 300;
12
+
13
+ /** Atalho para um veredito de sucesso. */
14
+ export function pass(info?: string, warning?: string): IntegrationTestOutcome {
15
+ return { ok: true, ...(info ? { info } : {}), ...(warning ? { warning } : {}) };
16
+ }
17
+
18
+ /** Atalho para um veredito de falha. */
19
+ export function fail(error: string): IntegrationTestOutcome {
20
+ return { ok: false, error };
21
+ }
22
+
23
+ /**
24
+ * Exige que um campo esteja preenchido. Devolve `null` quando está tudo certo, ou o
25
+ * veredito de falha pronto — evita repetir o mesmo `if` em 31 testers.
26
+ */
27
+ export function requireFields(
28
+ config: Record<string, unknown>,
29
+ fields: Array<[key: string, label: string]>,
30
+ ): IntegrationTestOutcome | null {
31
+ for (const [key, label] of fields) {
32
+ if (!String(config[key] ?? '').trim()) {
33
+ return fail(`${label} is required.`);
34
+ }
35
+ }
36
+ return null;
37
+ }
38
+
39
+ /** Lê uma chave do config como string já trimada. */
40
+ export function str(config: Record<string, unknown>, key: string): string {
41
+ return String(config[key] ?? '').trim();
42
+ }
43
+
44
+ /**
45
+ * Valida uma URL fornecida pelo usuário (host do Evolution, api_server do k8s,
46
+ * endpoint S3-compatible, base da ADN).
47
+ *
48
+ * Ranges privados são PERMITIDOS de propósito: k8s e Evolution self-hosted vivem em
49
+ * rede interna, e bloqueá-los quebraria o caso de uso principal. O que barramos são
50
+ * esquemas fora de http/https (file:, gopher:, etc.).
51
+ */
52
+ export function assertHttpUrl(raw: string, field: string): URL {
53
+ let url: URL;
54
+ try {
55
+ url = new URL(raw);
56
+ } catch {
57
+ throw new Error(`${field} is not a valid URL.`);
58
+ }
59
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') {
60
+ throw new Error(`${field} must use http or https.`);
61
+ }
62
+ return url;
63
+ }
64
+
65
+ export type ProbeResult = {
66
+ ok: boolean;
67
+ status: number;
68
+ /** Corpo parseado como JSON, ou `{}` quando a resposta não é JSON. */
69
+ body: any;
70
+ /** Corpo cru (truncado), útil quando a API responde texto puro. */
71
+ text: string;
72
+ };
73
+
74
+ /**
75
+ * `fetch` que não lança em status != 2xx — o status faz parte do veredito na maioria
76
+ * dos testers (401 vs 404 vs 403 dizem coisas diferentes).
77
+ */
78
+ export async function probeJson(
79
+ url: string,
80
+ init: RequestInit,
81
+ signal: AbortSignal,
82
+ ): Promise<ProbeResult> {
83
+ const response = await fetch(url, { ...init, signal });
84
+ const text = (await response.text().catch(() => '')).slice(0, 2_000);
85
+
86
+ let body: any = {};
87
+ try {
88
+ body = text ? JSON.parse(text) : {};
89
+ } catch {
90
+ body = {};
91
+ }
92
+
93
+ return { ok: response.ok, status: response.status, body, text };
94
+ }
95
+
96
+ /** Remove qualquer ocorrência dos segredos do texto. */
97
+ export function redactSecrets(text: string, secretValues: string[]): string {
98
+ let out = text;
99
+ for (const secret of secretValues) {
100
+ // Segredos muito curtos (ex.: uma senha de 3 letras) casariam com palavras comuns
101
+ // e transformariam a mensagem em ruído; o risco real está nos tokens longos.
102
+ if (secret && secret.length >= 6) {
103
+ out = out.split(secret).join('***');
104
+ }
105
+ }
106
+ return out;
107
+ }
108
+
109
+ /**
110
+ * Converte qualquer erro em mensagem segura para a UI e para o config do perfil.
111
+ *
112
+ * Ordem importa: timeout e falha de DNS/conexão precisam de texto PRÓPRIO, senão o
113
+ * operador de um cluster sem saída para a internet lê "não foi possível validar" e
114
+ * conclui que a credencial está errada.
115
+ */
116
+ export function sanitizeTesterError(
117
+ error: unknown,
118
+ secretValues: string[],
119
+ host?: string,
120
+ ): string {
121
+ const target = host ? ` (${host})` : '';
122
+ const name = (error as { name?: string })?.name ?? '';
123
+ const code = String((error as { code?: string })?.code ?? '');
124
+ const raw = error instanceof Error ? error.message : String(error ?? '');
125
+
126
+ if (name === 'AbortError' || name === 'TimeoutError' || code === 'ABORT_ERR') {
127
+ return `Timed out while contacting the provider${target}. Check the server's outbound network access.`;
128
+ }
129
+
130
+ const networkCode = [code, raw].join(' ');
131
+ if (/ENOTFOUND|EAI_AGAIN/.test(networkCode)) {
132
+ return `Host not found${target}. Check the address you typed.`;
133
+ }
134
+ if (/ECONNREFUSED/.test(networkCode)) {
135
+ return `Connection refused${target}. Check the address, the port and the firewall.`;
136
+ }
137
+ if (/ECONNRESET|EPIPE|ETIMEDOUT/.test(networkCode)) {
138
+ return `Connection interrupted${target}. Check the server's outbound network access.`;
139
+ }
140
+ if (/CERT_HAS_EXPIRED/.test(networkCode)) {
141
+ return `The provider's TLS certificate has expired${target}.`;
142
+ }
143
+ if (/DEPTH_ZERO_SELF_SIGNED_CERT|SELF_SIGNED_CERT_IN_CHAIN|UNABLE_TO_VERIFY_LEAF_SIGNATURE/.test(networkCode)) {
144
+ return `The provider's TLS certificate could not be verified${target}.`;
145
+ }
146
+
147
+ // Só a mensagem — nunca o objeto de erro inteiro nem o stack.
148
+ const message = redactSecrets(raw || 'Unexpected error.', secretValues).trim();
149
+ return message.length > MAX_ERROR_LENGTH
150
+ ? `${message.slice(0, MAX_ERROR_LENGTH - 1)}…`
151
+ : message;
152
+ }
153
+
154
+ /**
155
+ * Mensagem curta a partir de uma resposta HTTP de erro, procurando o campo de mensagem
156
+ * nos formatos mais comuns (`error.message`, `error_description`, `message`, `error`).
157
+ */
158
+ export function describeHttpError(result: ProbeResult, fallback: string): string {
159
+ const body = result.body ?? {};
160
+ const candidate =
161
+ body?.error?.message ??
162
+ body?.error_description ??
163
+ body?.message ??
164
+ (typeof body?.error === 'string' ? body.error : null) ??
165
+ body?.error?.error_user_msg;
166
+
167
+ const message = String(candidate ?? '').trim();
168
+ if (message) return message;
169
+
170
+ return `${fallback} (HTTP ${result.status})`;
171
+ }
@@ -0,0 +1,30 @@
1
+ import { AI_TESTERS } from './ai.testers';
2
+ import { CAPTCHA_TESTERS } from './captcha.testers';
3
+ import { EMAIL_TESTERS } from './email.testers';
4
+ import { INFRASTRUCTURE_TESTERS } from './infrastructure.testers';
5
+ import { IntegrationTester } from './integration-tester.types';
6
+ import { MESSAGING_TESTERS } from './messaging.testers';
7
+ import { OAUTH_TESTERS } from './oauth.testers';
8
+ import { PAYMENT_TESTERS } from './payment.testers';
9
+ import { STORAGE_TESTERS } from './storage.testers';
10
+
11
+ /**
12
+ * Testadores que o core registra sozinho no boot.
13
+ *
14
+ * Providers de outras libraries (nfse-national, da `fiscal`) se registram no próprio
15
+ * módulo, via IntegrationTesterRegistry.
16
+ */
17
+ export const BUILTIN_INTEGRATION_TESTERS: IntegrationTester[] = [
18
+ ...EMAIL_TESTERS,
19
+ ...MESSAGING_TESTERS,
20
+ ...STORAGE_TESTERS,
21
+ ...AI_TESTERS,
22
+ ...OAUTH_TESTERS,
23
+ ...PAYMENT_TESTERS,
24
+ ...CAPTCHA_TESTERS,
25
+ ...INFRASTRUCTURE_TESTERS,
26
+ ];
27
+
28
+ export * from './http-probe';
29
+ export * from './integration-tester.registry';
30
+ export * from './integration-tester.types';