@hed-hog/core 0.0.386 → 0.0.390
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -11
- package/dist/access-log/access-log.interceptor.d.ts.map +1 -1
- package/dist/access-log/access-log.interceptor.js +4 -2
- package/dist/access-log/access-log.interceptor.js.map +1 -1
- package/dist/ai/ai-attachment.fragments.d.ts +23 -0
- package/dist/ai/ai-attachment.fragments.d.ts.map +1 -0
- package/dist/ai/ai-attachment.fragments.js +34 -0
- package/dist/ai/ai-attachment.fragments.js.map +1 -0
- package/dist/ai/ai.controller.d.ts +7 -16
- package/dist/ai/ai.controller.d.ts.map +1 -1
- package/dist/ai/ai.prompts.d.ts +16 -0
- package/dist/ai/ai.prompts.d.ts.map +1 -0
- package/dist/ai/ai.prompts.js +37 -0
- package/dist/ai/ai.prompts.js.map +1 -0
- package/dist/ai/ai.service.d.ts +63 -12
- package/dist/ai/ai.service.d.ts.map +1 -1
- package/dist/ai/ai.service.js +215 -88
- package/dist/ai/ai.service.js.map +1 -1
- package/dist/ai/dto/chat.dto.d.ts +4 -1
- package/dist/ai/dto/chat.dto.d.ts.map +1 -1
- package/dist/ai/dto/chat.dto.js +23 -1
- package/dist/ai/dto/chat.dto.js.map +1 -1
- package/dist/ai/dto/create-agent.dto.d.ts +1 -1
- package/dist/ai/dto/create-agent.dto.d.ts.map +1 -1
- package/dist/ai/dto/create-agent.dto.js +1 -1
- package/dist/ai/dto/create-agent.dto.js.map +1 -1
- package/dist/ai/dto/update-agent.dto.d.ts +1 -1
- package/dist/ai/dto/update-agent.dto.d.ts.map +1 -1
- package/dist/ai/dto/update-agent.dto.js +1 -1
- package/dist/ai/dto/update-agent.dto.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.controller.d.ts +61 -7
- package/dist/ai-instruction/ai-instruction.controller.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.controller.js +63 -20
- package/dist/ai-instruction/ai-instruction.controller.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.module.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.module.js +13 -2
- package/dist/ai-instruction/ai-instruction.module.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.d.ts +131 -6
- package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.js +533 -60
- package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
- package/dist/ai-instruction/ai-prompt-builder.service.d.ts +8 -0
- package/dist/ai-instruction/ai-prompt-builder.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-prompt-builder.service.js +10 -1
- package/dist/ai-instruction/ai-prompt-builder.service.js.map +1 -1
- package/dist/ai-instruction/ai-prompt-registry.d.ts +45 -0
- package/dist/ai-instruction/ai-prompt-registry.d.ts.map +1 -0
- package/dist/ai-instruction/ai-prompt-registry.js +49 -0
- package/dist/ai-instruction/ai-prompt-registry.js.map +1 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.d.ts +89 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.d.ts.map +1 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.js +222 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.js.map +1 -0
- package/dist/ai-instruction/ai-prompt-template.util.d.ts +70 -0
- package/dist/ai-instruction/ai-prompt-template.util.d.ts.map +1 -0
- package/dist/ai-instruction/ai-prompt-template.util.js +154 -0
- package/dist/ai-instruction/ai-prompt-template.util.js.map +1 -0
- package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts +5 -0
- package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts.map +1 -1
- package/dist/ai-instruction/dto/create-ai-instruction.dto.js +27 -1
- package/dist/ai-instruction/dto/create-ai-instruction.dto.js.map +1 -1
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts +14 -0
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts.map +1 -0
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.js +42 -0
- package/dist/ai-instruction/dto/preview-ai-instruction.dto.js.map +1 -0
- package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts +11 -0
- package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts.map +1 -1
- package/dist/ai-instruction/dto/update-ai-instruction.dto.js +34 -0
- package/dist/ai-instruction/dto/update-ai-instruction.dto.js.map +1 -1
- package/dist/ai-instruction/types/ai-instruction.types.d.ts +13 -1
- package/dist/ai-instruction/types/ai-instruction.types.d.ts.map +1 -1
- package/dist/ai-instruction/types/ai-instruction.types.js +10 -0
- package/dist/ai-instruction/types/ai-instruction.types.js.map +1 -1
- package/dist/auth/auth.controller.d.ts +26 -10
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +49 -21
- package/dist/auth/auth.controller.js.map +1 -1
- package/dist/auth/auth.service.d.ts +35 -9
- package/dist/auth/auth.service.d.ts.map +1 -1
- package/dist/auth/auth.service.js +78 -29
- package/dist/auth/auth.service.js.map +1 -1
- package/dist/captcha/captcha.module.d.ts +3 -0
- package/dist/captcha/captcha.module.d.ts.map +1 -0
- package/dist/captcha/captcha.module.js +23 -0
- package/dist/captcha/captcha.module.js.map +1 -0
- package/dist/captcha/captcha.service.d.ts +38 -0
- package/dist/captcha/captcha.service.d.ts.map +1 -0
- package/dist/captcha/captcha.service.js +144 -0
- package/dist/captcha/captcha.service.js.map +1 -0
- package/dist/challenge/challenge.service.d.ts +16 -7
- package/dist/challenge/challenge.service.d.ts.map +1 -1
- package/dist/challenge/challenge.service.js +64 -16
- package/dist/challenge/challenge.service.js.map +1 -1
- package/dist/core.module.d.ts +3 -1
- package/dist/core.module.d.ts.map +1 -1
- package/dist/core.module.js +29 -2
- package/dist/core.module.js.map +1 -1
- package/dist/dashboard/dashboard/dashboard.controller.d.ts +15 -15
- package/dist/dashboard/dashboard/dashboard.service.d.ts +15 -15
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +6 -6
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +6 -6
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +20 -20
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +20 -20
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +1 -1
- package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +13 -13
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +13 -13
- package/dist/file/file.service.d.ts +6 -0
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +44 -4
- package/dist/file/file.service.js.map +1 -1
- package/dist/incident/incident-notifier.service.d.ts +36 -0
- package/dist/incident/incident-notifier.service.d.ts.map +1 -0
- package/dist/incident/incident-notifier.service.js +208 -0
- package/dist/incident/incident-notifier.service.js.map +1 -0
- package/dist/incident/incident.controller.d.ts +23 -0
- package/dist/incident/incident.controller.d.ts.map +1 -0
- package/dist/incident/incident.controller.js +75 -0
- package/dist/incident/incident.controller.js.map +1 -0
- package/dist/incident/incident.module.d.ts +7 -0
- package/dist/incident/incident.module.d.ts.map +1 -0
- package/dist/incident/incident.module.js +32 -0
- package/dist/incident/incident.module.js.map +1 -0
- package/dist/incident/incident.service.d.ts +72 -0
- package/dist/incident/incident.service.d.ts.map +1 -0
- package/dist/incident/incident.service.js +184 -0
- package/dist/incident/incident.service.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -1
- package/dist/integration-profile/dto/test.dto.d.ts +13 -0
- package/dist/integration-profile/dto/test.dto.d.ts.map +1 -0
- package/dist/integration-profile/dto/test.dto.js +26 -0
- package/dist/integration-profile/dto/test.dto.js.map +1 -0
- package/dist/integration-profile/integration-profile.controller.d.ts +12 -1
- package/dist/integration-profile/integration-profile.controller.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.controller.js +9 -1
- package/dist/integration-profile/integration-profile.controller.js.map +1 -1
- package/dist/integration-profile/integration-profile.module.d.ts +6 -1
- package/dist/integration-profile/integration-profile.module.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.module.js +26 -3
- package/dist/integration-profile/integration-profile.module.js.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.js +12 -2
- package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
- package/dist/integration-profile/integration-profile.service.d.ts +28 -2
- package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.service.js +105 -31
- package/dist/integration-profile/integration-profile.service.js.map +1 -1
- package/dist/integration-profile/integration-profile.utils.d.ts +31 -1
- package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.utils.js +35 -4
- package/dist/integration-profile/integration-profile.utils.js.map +1 -1
- package/dist/integration-profile/testers/ai.testers.d.ts +3 -0
- package/dist/integration-profile/testers/ai.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/ai.testers.js +125 -0
- package/dist/integration-profile/testers/ai.testers.js.map +1 -0
- package/dist/integration-profile/testers/captcha.testers.d.ts +3 -0
- package/dist/integration-profile/testers/captcha.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/captcha.testers.js +121 -0
- package/dist/integration-profile/testers/captcha.testers.js.map +1 -0
- package/dist/integration-profile/testers/email.testers.d.ts +3 -0
- package/dist/integration-profile/testers/email.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/email.testers.js +128 -0
- package/dist/integration-profile/testers/email.testers.js.map +1 -0
- package/dist/integration-profile/testers/http-probe.d.ts +57 -0
- package/dist/integration-profile/testers/http-probe.d.ts.map +1 -0
- package/dist/integration-profile/testers/http-probe.js +140 -0
- package/dist/integration-profile/testers/http-probe.js.map +1 -0
- package/dist/integration-profile/testers/index.d.ts +12 -0
- package/dist/integration-profile/testers/index.d.ts.map +1 -0
- package/dist/integration-profile/testers/index.js +45 -0
- package/dist/integration-profile/testers/index.js.map +1 -0
- package/dist/integration-profile/testers/infrastructure.testers.d.ts +3 -0
- package/dist/integration-profile/testers/infrastructure.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/infrastructure.testers.js +105 -0
- package/dist/integration-profile/testers/infrastructure.testers.js.map +1 -0
- package/dist/integration-profile/testers/integration-tester.registry.d.ts +17 -0
- package/dist/integration-profile/testers/integration-tester.registry.d.ts.map +1 -0
- package/dist/integration-profile/testers/integration-tester.registry.js +52 -0
- package/dist/integration-profile/testers/integration-tester.registry.js.map +1 -0
- package/dist/integration-profile/testers/integration-tester.types.d.ts +55 -0
- package/dist/integration-profile/testers/integration-tester.types.d.ts.map +1 -0
- package/dist/integration-profile/testers/integration-tester.types.js +16 -0
- package/dist/integration-profile/testers/integration-tester.types.js.map +1 -0
- package/dist/integration-profile/testers/messaging.testers.d.ts +3 -0
- package/dist/integration-profile/testers/messaging.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/messaging.testers.js +70 -0
- package/dist/integration-profile/testers/messaging.testers.js.map +1 -0
- package/dist/integration-profile/testers/oauth.testers.d.ts +3 -0
- package/dist/integration-profile/testers/oauth.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/oauth.testers.js +285 -0
- package/dist/integration-profile/testers/oauth.testers.js.map +1 -0
- package/dist/integration-profile/testers/payment.testers.d.ts +3 -0
- package/dist/integration-profile/testers/payment.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/payment.testers.js +169 -0
- package/dist/integration-profile/testers/payment.testers.js.map +1 -0
- package/dist/integration-profile/testers/storage.testers.d.ts +3 -0
- package/dist/integration-profile/testers/storage.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/storage.testers.js +208 -0
- package/dist/integration-profile/testers/storage.testers.js.map +1 -0
- package/dist/language/en.json +4 -2
- package/dist/language/pt.json +4 -2
- package/dist/leaked-password/leaked-password.controller.d.ts +24 -0
- package/dist/leaked-password/leaked-password.controller.d.ts.map +1 -0
- package/dist/leaked-password/leaked-password.controller.js +78 -0
- package/dist/leaked-password/leaked-password.controller.js.map +1 -0
- package/dist/leaked-password/leaked-password.module.d.ts +8 -0
- package/dist/leaked-password/leaked-password.module.d.ts.map +1 -0
- package/dist/leaked-password/leaked-password.module.js +31 -0
- package/dist/leaked-password/leaked-password.module.js.map +1 -0
- package/dist/leaked-password/leaked-password.service.d.ts +64 -0
- package/dist/leaked-password/leaked-password.service.d.ts.map +1 -0
- package/dist/leaked-password/leaked-password.service.js +218 -0
- package/dist/leaked-password/leaked-password.service.js.map +1 -0
- package/dist/locale/locale.controller.d.ts +1 -1
- package/dist/locale/locale.service.d.ts +1 -1
- package/dist/mail/dto/preview.dto.d.ts +18 -0
- package/dist/mail/dto/preview.dto.d.ts.map +1 -0
- package/dist/mail/dto/preview.dto.js +66 -0
- package/dist/mail/dto/preview.dto.js.map +1 -0
- package/dist/mail/dto/send.dto.d.ts +7 -0
- package/dist/mail/dto/send.dto.d.ts.map +1 -1
- package/dist/mail/dto/send.dto.js +10 -0
- package/dist/mail/dto/send.dto.js.map +1 -1
- package/dist/mail/mail.controller.d.ts +4 -0
- package/dist/mail/mail.controller.d.ts.map +1 -1
- package/dist/mail/mail.controller.js +16 -2
- package/dist/mail/mail.controller.js.map +1 -1
- package/dist/mail/mail.service.d.ts +23 -2
- package/dist/mail/mail.service.d.ts.map +1 -1
- package/dist/mail/mail.service.js +102 -13
- package/dist/mail/mail.service.js.map +1 -1
- package/dist/mail-layout/dto/update.dto.d.ts +17 -0
- package/dist/mail-layout/dto/update.dto.d.ts.map +1 -0
- package/dist/mail-layout/dto/update.dto.js +27 -0
- package/dist/mail-layout/dto/update.dto.js.map +1 -0
- package/dist/mail-layout/mail-layout.controller.d.ts +15 -0
- package/dist/mail-layout/mail-layout.controller.d.ts.map +1 -0
- package/dist/mail-layout/mail-layout.controller.js +71 -0
- package/dist/mail-layout/mail-layout.controller.js.map +1 -0
- package/dist/mail-layout/mail-layout.module.d.ts +3 -0
- package/dist/mail-layout/mail-layout.module.d.ts.map +1 -0
- package/dist/mail-layout/mail-layout.module.js +35 -0
- package/dist/mail-layout/mail-layout.module.js.map +1 -0
- package/dist/mail-layout/mail-layout.service.d.ts +27 -0
- package/dist/mail-layout/mail-layout.service.d.ts.map +1 -0
- package/dist/mail-layout/mail-layout.service.js +80 -0
- package/dist/mail-layout/mail-layout.service.js.map +1 -0
- package/dist/mcp-chat/mcp-chat.controller.d.ts +2 -2
- package/dist/mcp-chat/mcp-chat.service.d.ts +24 -2
- package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.js +80 -24
- package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
- package/dist/menu/menu.controller.d.ts +3 -3
- package/dist/menu/menu.service.d.ts +3 -3
- package/dist/notification/notification.controller.d.ts +12 -12
- package/dist/notification/notification.service.d.ts +12 -12
- package/dist/oauth/oauth-token-broker.service.d.ts +72 -0
- package/dist/oauth/oauth-token-broker.service.d.ts.map +1 -0
- package/dist/oauth/oauth-token-broker.service.js +258 -0
- package/dist/oauth/oauth-token-broker.service.js.map +1 -0
- package/dist/oauth/oauth.module.d.ts.map +1 -1
- package/dist/oauth/oauth.module.js +3 -1
- package/dist/oauth/oauth.module.js.map +1 -1
- package/dist/oauth/oauth.service.d.ts +2 -0
- package/dist/oauth/oauth.service.d.ts.map +1 -1
- package/dist/oauth/oauth.service.js +6 -3
- package/dist/oauth/oauth.service.js.map +1 -1
- package/dist/pdf/pdf.service.d.ts +8 -0
- package/dist/pdf/pdf.service.d.ts.map +1 -1
- package/dist/pdf/pdf.service.js +52 -0
- package/dist/pdf/pdf.service.js.map +1 -1
- package/dist/presence/presence.controller.d.ts +16 -0
- package/dist/presence/presence.controller.d.ts.map +1 -0
- package/dist/presence/presence.controller.js +60 -0
- package/dist/presence/presence.controller.js.map +1 -0
- package/dist/presence/presence.listener.d.ts +29 -0
- package/dist/presence/presence.listener.d.ts.map +1 -0
- package/dist/presence/presence.listener.js +82 -0
- package/dist/presence/presence.listener.js.map +1 -0
- package/dist/presence/presence.module.d.ts +3 -0
- package/dist/presence/presence.module.d.ts.map +1 -0
- package/dist/presence/presence.module.js +32 -0
- package/dist/presence/presence.module.js.map +1 -0
- package/dist/presence/presence.service.d.ts +42 -0
- package/dist/presence/presence.service.d.ts.map +1 -0
- package/dist/presence/presence.service.js +147 -0
- package/dist/presence/presence.service.js.map +1 -0
- package/dist/profile/dto/delete-account.dto.d.ts +8 -0
- package/dist/profile/dto/delete-account.dto.d.ts.map +1 -0
- package/dist/profile/dto/delete-account.dto.js +22 -0
- package/dist/profile/dto/delete-account.dto.js.map +1 -0
- package/dist/profile/events/profile-account-deleted.event.d.ts +12 -0
- package/dist/profile/events/profile-account-deleted.event.d.ts.map +1 -0
- package/dist/profile/events/profile-account-deleted.event.js +17 -0
- package/dist/profile/events/profile-account-deleted.event.js.map +1 -0
- package/dist/profile/profile.controller.d.ts +24 -17
- package/dist/profile/profile.controller.d.ts.map +1 -1
- package/dist/profile/profile.controller.js +75 -46
- package/dist/profile/profile.controller.js.map +1 -1
- package/dist/profile/profile.service.d.ts +34 -21
- package/dist/profile/profile.service.d.ts.map +1 -1
- package/dist/profile/profile.service.js +113 -37
- package/dist/profile/profile.service.js.map +1 -1
- package/dist/realtime/realtime.gateway.d.ts +48 -0
- package/dist/realtime/realtime.gateway.d.ts.map +1 -0
- package/dist/realtime/realtime.gateway.js +156 -0
- package/dist/realtime/realtime.gateway.js.map +1 -0
- package/dist/realtime/realtime.module.d.ts +8 -0
- package/dist/realtime/realtime.module.d.ts.map +1 -0
- package/dist/realtime/realtime.module.js +29 -0
- package/dist/realtime/realtime.module.js.map +1 -0
- package/dist/realtime/realtime.service.d.ts +51 -0
- package/dist/realtime/realtime.service.d.ts.map +1 -0
- package/dist/realtime/realtime.service.js +177 -0
- package/dist/realtime/realtime.service.js.map +1 -0
- package/dist/redis/redis-pubsub.d.ts +27 -0
- package/dist/redis/redis-pubsub.d.ts.map +1 -0
- package/dist/redis/redis-pubsub.js +140 -0
- package/dist/redis/redis-pubsub.js.map +1 -0
- package/dist/role/role.controller.d.ts +3 -3
- package/dist/role/role.service.d.ts +3 -3
- package/dist/setting/dto/create.dto.d.ts.map +1 -1
- package/dist/setting/dto/create.dto.js +9 -2
- package/dist/setting/dto/create.dto.js.map +1 -1
- package/dist/setting/setting.controller.d.ts +5 -5
- package/dist/setting/setting.service.d.ts +8 -5
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +25 -1
- package/dist/setting/setting.service.js.map +1 -1
- package/dist/user/dto/create-with-email-and-password.dto.d.ts +2 -0
- package/dist/user/dto/create-with-email-and-password.dto.d.ts.map +1 -1
- package/dist/user/dto/create-with-email-and-password.dto.js +5 -0
- package/dist/user/dto/create-with-email-and-password.dto.js.map +1 -1
- package/dist/user/dto/query-user-mail-list.dto.d.ts +5 -0
- package/dist/user/dto/query-user-mail-list.dto.d.ts.map +1 -0
- package/dist/user/dto/query-user-mail-list.dto.js +25 -0
- package/dist/user/dto/query-user-mail-list.dto.js.map +1 -0
- package/dist/user/user-credential.util.d.ts +19 -0
- package/dist/user/user-credential.util.d.ts.map +1 -0
- package/dist/user/user-credential.util.js +32 -0
- package/dist/user/user-credential.util.js.map +1 -0
- package/dist/user/user.controller.d.ts +17 -5
- package/dist/user/user.controller.d.ts.map +1 -1
- package/dist/user/user.controller.js +18 -3
- package/dist/user/user.controller.js.map +1 -1
- package/dist/user/user.service.d.ts +28 -6
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +204 -13
- package/dist/user/user.service.js.map +1 -1
- package/dist/validators/is-strong-password-with-settings.validator.d.ts.map +1 -1
- package/dist/validators/is-strong-password-with-settings.validator.js +11 -0
- package/dist/validators/is-strong-password-with-settings.validator.js.map +1 -1
- package/dist/validators/service-locator.d.ts +9 -0
- package/dist/validators/service-locator.d.ts.map +1 -1
- package/dist/validators/service-locator.js +12 -0
- package/dist/validators/service-locator.js.map +1 -1
- package/dist/webhook-integration/webhook-integration.controller.d.ts +5 -8
- package/dist/webhook-integration/webhook-integration.controller.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.controller.js +31 -8
- package/dist/webhook-integration/webhook-integration.controller.js.map +1 -1
- package/dist/webhook-integration/webhook-integration.module.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.module.js +5 -0
- package/dist/webhook-integration/webhook-integration.module.js.map +1 -1
- package/dist/webhook-integration/webhook-integration.service.d.ts +33 -1
- package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-integration.service.js +109 -4
- package/dist/webhook-integration/webhook-integration.service.js.map +1 -1
- package/dist/webhook-integration/webhook-protocol.registry.d.ts +63 -0
- package/dist/webhook-integration/webhook-protocol.registry.d.ts.map +1 -0
- package/dist/webhook-integration/webhook-protocol.registry.js +51 -0
- package/dist/webhook-integration/webhook-protocol.registry.js.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.module.d.ts +3 -0
- package/dist/whatsapp-sender/whatsapp-sender.module.d.ts.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.module.js +23 -0
- package/dist/whatsapp-sender/whatsapp-sender.module.js.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +50 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.js +224 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -0
- package/hedhog/data/integration_provider.yaml +16 -0
- package/hedhog/data/mail.yaml +88 -61
- package/hedhog/data/mail_layout.yaml +188 -0
- package/hedhog/data/menu.yaml +67 -3
- package/hedhog/data/route.yaml +135 -0
- package/hedhog/data/setting_group.yaml +139 -1
- package/hedhog/frontend/app/account/components/mfa-setup-dialog.tsx.ejs +36 -0
- package/hedhog/frontend/app/account/components/two-factor-auth.tsx.ejs +2 -0
- package/hedhog/frontend/app/account/hooks/use-mfa-setup.ts.ejs +10 -7
- package/hedhog/frontend/app/ai_agent/page.tsx.ejs +7 -4
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +580 -0
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-preview.tsx.ejs +150 -0
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +199 -0
- package/hedhog/frontend/app/ai_instruction/_components/prompt-diff.tsx.ejs +63 -0
- package/hedhog/frontend/app/ai_instruction/_lib/line-diff.spec.ts.ejs +59 -0
- package/hedhog/frontend/app/ai_instruction/_lib/line-diff.ts.ejs +72 -0
- package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.spec.ts.ejs +170 -0
- package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.ts.ejs +167 -0
- package/hedhog/frontend/app/ai_instruction/_lib/types.ts.ejs +99 -0
- package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +422 -0
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +51 -4
- package/hedhog/frontend/app/incidents/page.tsx.ejs +400 -0
- package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +169 -92
- package/hedhog/frontend/app/mail/layout/page.tsx.ejs +344 -0
- package/hedhog/frontend/app/mail/template/page.tsx.ejs +155 -121
- package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +129 -17
- package/hedhog/frontend/app/pages/_components/page-delete-dialog.tsx.ejs +343 -0
- package/hedhog/frontend/app/pages/_components/page-detail-sheet.tsx.ejs +438 -0
- package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1009 -0
- package/hedhog/frontend/app/pages/_components/system-page-types.ts.ejs +56 -0
- package/hedhog/frontend/app/pages/_components/use-system-pages.ts.ejs +171 -0
- package/hedhog/frontend/app/pages/page.tsx.ejs +514 -0
- package/hedhog/frontend/app/users/page.tsx.ejs +119 -13
- package/hedhog/frontend/app/users/user-activity-timeline.tsx.ejs +231 -0
- package/hedhog/frontend/app/users/user-mails.tsx.ejs +399 -0
- package/hedhog/frontend/app/users/user-sheet.tsx.ejs +60 -75
- package/hedhog/frontend/messages/en.json +521 -3
- package/hedhog/frontend/messages/pt.json +521 -3
- package/hedhog/table/ai_agent.yaml +1 -0
- package/hedhog/table/ai_instruction.yaml +15 -0
- package/hedhog/table/leaked_password.yaml +18 -0
- package/hedhog/table/mail_layout.yaml +35 -0
- package/hedhog/table/mail_var.yaml +4 -0
- package/hedhog/table/setting.yaml +1 -0
- package/hedhog/table/system_incident.yaml +59 -0
- package/hedhog/table/user_presence.yaml +36 -0
- package/hedhog/table/webhook_integration.yaml +64 -43
- package/package.json +8 -4
- package/src/access-log/access-log.interceptor.ts +4 -2
- package/src/ai/ai-attachment.fragments.spec.ts +319 -0
- package/src/ai/ai-attachment.fragments.ts +35 -0
- package/src/ai/ai.prompts.ts +38 -0
- package/src/ai/ai.service.spec.ts +280 -0
- package/src/ai/ai.service.ts +338 -82
- package/src/ai/dto/chat.dto.ts +33 -3
- package/src/ai/dto/create-agent.dto.ts +2 -2
- package/src/ai/dto/update-agent.dto.ts +2 -2
- package/src/ai-instruction/ai-instruction.controller.ts +40 -9
- package/src/ai-instruction/ai-instruction.module.ts +13 -2
- package/src/ai-instruction/ai-instruction.service.spec.ts +658 -0
- package/src/ai-instruction/ai-instruction.service.ts +661 -62
- package/src/ai-instruction/ai-prompt-builder.service.ts +10 -1
- package/src/ai-instruction/ai-prompt-registry.ts +87 -0
- package/src/ai-instruction/ai-prompt-resolver.service.spec.ts +375 -0
- package/src/ai-instruction/ai-prompt-resolver.service.ts +295 -0
- package/src/ai-instruction/ai-prompt-template.util.spec.ts +162 -0
- package/src/ai-instruction/ai-prompt-template.util.ts +199 -0
- package/src/ai-instruction/dto/create-ai-instruction.dto.ts +39 -3
- package/src/ai-instruction/dto/preview-ai-instruction.dto.ts +26 -0
- package/src/ai-instruction/dto/update-ai-instruction.dto.ts +42 -1
- package/src/ai-instruction/types/ai-instruction.types.ts +24 -1
- package/src/auth/auth.controller.ts +33 -6
- package/src/auth/auth.service.spec.ts +3 -1
- package/src/auth/auth.service.ts +103 -37
- package/src/captcha/captcha.module.ts +10 -0
- package/src/captcha/captcha.service.spec.ts +210 -0
- package/src/captcha/captcha.service.ts +191 -0
- package/src/challenge/challenge.service.spec.ts +39 -4
- package/src/challenge/challenge.service.ts +72 -17
- package/src/core.module.ts +27 -1
- package/src/file/file.service.spec.ts +105 -0
- package/src/file/file.service.ts +60 -3
- package/src/incident/incident-notifier.service.spec.ts +205 -0
- package/src/incident/incident-notifier.service.ts +241 -0
- package/src/incident/incident.controller.ts +38 -0
- package/src/incident/incident.module.ts +19 -0
- package/src/incident/incident.service.spec.ts +150 -0
- package/src/incident/incident.service.ts +209 -0
- package/src/index.ts +38 -0
- package/src/integration-profile/dto/test.dto.ts +19 -0
- package/src/integration-profile/integration-profile.controller.ts +10 -1
- package/src/integration-profile/integration-profile.module.spec.ts +51 -0
- package/src/integration-profile/integration-profile.module.ts +23 -4
- package/src/integration-profile/integration-profile.secrets.ts +12 -2
- package/src/integration-profile/integration-profile.service.spec.ts +279 -0
- package/src/integration-profile/integration-profile.service.ts +132 -29
- package/src/integration-profile/integration-profile.utils.spec.ts +97 -0
- package/src/integration-profile/integration-profile.utils.ts +79 -3
- package/src/integration-profile/testers/ai.testers.ts +165 -0
- package/src/integration-profile/testers/captcha.testers.spec.ts +92 -0
- package/src/integration-profile/testers/captcha.testers.ts +139 -0
- package/src/integration-profile/testers/email.testers.ts +161 -0
- package/src/integration-profile/testers/http-probe.spec.ts +153 -0
- package/src/integration-profile/testers/http-probe.ts +171 -0
- package/src/integration-profile/testers/index.ts +30 -0
- package/src/integration-profile/testers/infrastructure.testers.ts +122 -0
- package/src/integration-profile/testers/integration-tester.registry.spec.ts +75 -0
- package/src/integration-profile/testers/integration-tester.registry.ts +43 -0
- package/src/integration-profile/testers/integration-tester.types.ts +61 -0
- package/src/integration-profile/testers/messaging.testers.ts +102 -0
- package/src/integration-profile/testers/oauth.testers.spec.ts +220 -0
- package/src/integration-profile/testers/oauth.testers.ts +305 -0
- package/src/integration-profile/testers/payment.testers.ts +185 -0
- package/src/integration-profile/testers/remaining.testers.spec.ts +401 -0
- package/src/integration-profile/testers/storage.testers.spec.ts +185 -0
- package/src/integration-profile/testers/storage.testers.ts +226 -0
- package/src/integration-profile/testers/tester-coverage.spec.ts +58 -0
- package/src/language/en.json +4 -2
- package/src/language/pt.json +4 -2
- package/src/leaked-password/README.md +83 -0
- package/src/leaked-password/leaked-password.controller.ts +52 -0
- package/src/leaked-password/leaked-password.module.ts +18 -0
- package/src/leaked-password/leaked-password.service.ts +242 -0
- package/src/leaked-password/seed/build-seed-sql.mjs +180 -0
- package/src/leaked-password/seed/common-passwords.txt +335 -0
- package/src/mail/dto/preview.dto.ts +50 -0
- package/src/mail/dto/send.dto.ts +14 -1
- package/src/mail/mail-template.spec.ts +197 -0
- package/src/mail/mail.controller.ts +9 -2
- package/src/mail/mail.service.spec.ts +116 -1
- package/src/mail/mail.service.ts +118 -12
- package/src/mail-layout/dto/update.dto.ts +19 -0
- package/src/mail-layout/mail-layout.controller.ts +47 -0
- package/src/mail-layout/mail-layout.module.ts +22 -0
- package/src/mail-layout/mail-layout.service.ts +94 -0
- package/src/mcp-chat/mcp-chat.service.spec.ts +236 -0
- package/src/mcp-chat/mcp-chat.service.ts +122 -26
- package/src/oauth/oauth-token-broker.service.spec.ts +172 -0
- package/src/oauth/oauth-token-broker.service.ts +363 -0
- package/src/oauth/oauth.module.ts +3 -1
- package/src/oauth/oauth.service.ts +8 -2
- package/src/pdf/pdf.service.ts +75 -0
- package/src/presence/presence.controller.ts +29 -0
- package/src/presence/presence.listener.ts +53 -0
- package/src/presence/presence.module.ts +19 -0
- package/src/presence/presence.service.spec.ts +97 -0
- package/src/presence/presence.service.ts +160 -0
- package/src/profile/dto/delete-account.dto.ts +11 -0
- package/src/profile/events/profile-account-deleted.event.ts +13 -0
- package/src/profile/profile.controller.ts +52 -36
- package/src/profile/profile.service.ts +143 -41
- package/src/realtime/realtime.gateway.ts +138 -0
- package/src/realtime/realtime.module.ts +16 -0
- package/src/realtime/realtime.service.spec.ts +50 -0
- package/src/realtime/realtime.service.ts +187 -0
- package/src/redis/redis-pubsub.ts +179 -0
- package/src/setting/dto/create.dto.ts +13 -2
- package/src/setting/setting.service.spec.ts +56 -0
- package/src/setting/setting.service.ts +29 -1
- package/src/user/dto/create-with-email-and-password.dto.ts +6 -1
- package/src/user/dto/query-user-mail-list.dto.ts +10 -0
- package/src/user/user-credential.util.ts +35 -0
- package/src/user/user.controller.ts +17 -2
- package/src/user/user.service.spec.ts +153 -0
- package/src/user/user.service.ts +255 -12
- package/src/validators/is-strong-password-with-settings.validator.ts +12 -0
- package/src/validators/service-locator.ts +15 -0
- package/src/webhook-integration/webhook-integration.controller.ts +40 -2
- package/src/webhook-integration/webhook-integration.module.ts +5 -0
- package/src/webhook-integration/webhook-integration.service.ts +133 -0
- package/src/webhook-integration/webhook-protocol.registry.spec.ts +70 -0
- package/src/webhook-integration/webhook-protocol.registry.ts +93 -0
- package/src/whatsapp-sender/whatsapp-sender.module.ts +10 -0
- package/src/whatsapp-sender/whatsapp-sender.service.ts +313 -0
|
@@ -5,19 +5,26 @@ import {
|
|
|
5
5
|
BadRequestException,
|
|
6
6
|
Inject,
|
|
7
7
|
Injectable,
|
|
8
|
+
Logger,
|
|
8
9
|
NotFoundException,
|
|
9
10
|
forwardRef,
|
|
10
11
|
} from '@nestjs/common';
|
|
11
12
|
import * as pako from 'pako';
|
|
12
|
-
import { buildMailConfigFromIntegration } from './integration-profile.utils';
|
|
13
13
|
import { CreateDTO } from './dto/create.dto';
|
|
14
14
|
import {
|
|
15
15
|
ConflictResolutionDTO,
|
|
16
16
|
ImportProfileItemDTO,
|
|
17
17
|
} from './dto/import-confirm.dto';
|
|
18
|
+
import { TestDTO } from './dto/test.dto';
|
|
18
19
|
import { UpdateDTO } from './dto/update.dto';
|
|
19
20
|
import { IntegrationCredentialCryptoService } from './integration-credential-crypto.service';
|
|
20
21
|
import { getSensitiveConfigKeys } from './integration-profile.secrets';
|
|
22
|
+
import { sanitizeTesterError } from './testers/http-probe';
|
|
23
|
+
import { IntegrationTesterRegistry } from './testers/integration-tester.registry';
|
|
24
|
+
import {
|
|
25
|
+
INTEGRATION_TEST_TIMEOUT_MS,
|
|
26
|
+
IntegrationTestOutcome,
|
|
27
|
+
} from './testers/integration-tester.types';
|
|
21
28
|
|
|
22
29
|
type IntegrationProfileExportItem = {
|
|
23
30
|
slug: string;
|
|
@@ -55,6 +62,8 @@ type InvalidImportItem = {
|
|
|
55
62
|
|
|
56
63
|
@Injectable()
|
|
57
64
|
export class IntegrationProfileService {
|
|
65
|
+
private readonly logger = new Logger(IntegrationProfileService.name);
|
|
66
|
+
|
|
58
67
|
constructor(
|
|
59
68
|
@Inject(forwardRef(() => PrismaService))
|
|
60
69
|
private readonly prismaService: PrismaService,
|
|
@@ -62,6 +71,8 @@ export class IntegrationProfileService {
|
|
|
62
71
|
private readonly paginationService: PaginationService,
|
|
63
72
|
@Inject(forwardRef(() => IntegrationCredentialCryptoService))
|
|
64
73
|
private readonly credentialCrypto: IntegrationCredentialCryptoService,
|
|
74
|
+
@Inject(forwardRef(() => IntegrationTesterRegistry))
|
|
75
|
+
private readonly testerRegistry: IntegrationTesterRegistry,
|
|
65
76
|
) {}
|
|
66
77
|
|
|
67
78
|
async listTypes() {
|
|
@@ -430,7 +441,14 @@ export class IntegrationProfileService {
|
|
|
430
441
|
});
|
|
431
442
|
}
|
|
432
443
|
|
|
433
|
-
|
|
444
|
+
/**
|
|
445
|
+
* Testa as credenciais de um perfil contra o serviço real, sem salvar.
|
|
446
|
+
*
|
|
447
|
+
* Só despacha: quem sabe falar com cada provider é o `IntegrationTester` registrado
|
|
448
|
+
* no `IntegrationTesterRegistry`. Funciona tanto na edição (herda os segredos
|
|
449
|
+
* armazenados no lugar da máscara) quanto na criação de um perfil ainda inexistente.
|
|
450
|
+
*/
|
|
451
|
+
async test(data: TestDTO) {
|
|
434
452
|
await this.validateTypeAndProvider(data.type_id, data.provider_id);
|
|
435
453
|
|
|
436
454
|
const provider = await this.prismaService.integration_provider.findUnique({
|
|
@@ -451,17 +469,22 @@ export class IntegrationProfileService {
|
|
|
451
469
|
);
|
|
452
470
|
}
|
|
453
471
|
|
|
454
|
-
|
|
472
|
+
const typeSlug = provider.integration_type.slug;
|
|
473
|
+
const slug = data.slug.trim();
|
|
474
|
+
|
|
475
|
+
const tester = this.testerRegistry.find(provider.slug);
|
|
476
|
+
if (!tester) {
|
|
455
477
|
throw new BadRequestException(
|
|
456
|
-
|
|
478
|
+
`Connection test is not available for provider "${provider.slug}".`,
|
|
457
479
|
);
|
|
458
480
|
}
|
|
459
481
|
|
|
460
482
|
// "Deixe em branco para manter": ao testar na edição, herda os segredos já
|
|
461
483
|
// armazenados (decifrados pelo middleware) para os campos vazios/mascarados.
|
|
484
|
+
// Resolve por id quando ele veio: o slug é editável e pode ter mudado no form.
|
|
462
485
|
let effectiveConfig = (data.config as Record<string, unknown>) ?? null;
|
|
463
486
|
const stored = await this.prismaService.integration_profile.findUnique({
|
|
464
|
-
where: {
|
|
487
|
+
where: data.profile_id ? { id: data.profile_id } : { slug },
|
|
465
488
|
select: { config: true },
|
|
466
489
|
});
|
|
467
490
|
if (stored?.config) {
|
|
@@ -472,42 +495,122 @@ export class IntegrationProfileService {
|
|
|
472
495
|
) as Record<string, unknown>;
|
|
473
496
|
}
|
|
474
497
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
const domain = String(resendCfg.domain ?? '').trim();
|
|
480
|
-
|
|
481
|
-
if (!apiToken) {
|
|
482
|
-
throw new BadRequestException('Resend API token is required.');
|
|
483
|
-
}
|
|
484
|
-
if (!domain) {
|
|
485
|
-
throw new BadRequestException('Resend sending domain is required.');
|
|
486
|
-
}
|
|
498
|
+
const config = effectiveConfig ?? {};
|
|
499
|
+
const secretValues = getSensitiveConfigKeys(provider.slug)
|
|
500
|
+
.map((key) => String(config[key] ?? ''))
|
|
501
|
+
.filter((value) => value.length > 0);
|
|
487
502
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
503
|
+
const timeoutMs = tester.timeoutMs ?? INTEGRATION_TEST_TIMEOUT_MS;
|
|
504
|
+
let outcome: IntegrationTestOutcome;
|
|
505
|
+
try {
|
|
506
|
+
// Duplo guarda de tempo: o AbortSignal cobre quem o respeita (fetch/SDKs) e o
|
|
507
|
+
// race cobre quem não respeita (o transporter do nodemailer, por exemplo).
|
|
508
|
+
outcome = await Promise.race([
|
|
509
|
+
tester.test(config, {
|
|
510
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
511
|
+
typeSlug,
|
|
512
|
+
providerSlug: provider.slug,
|
|
513
|
+
secretValues,
|
|
514
|
+
}),
|
|
515
|
+
this.hardTimeout(timeoutMs + 2_000),
|
|
516
|
+
]);
|
|
517
|
+
} catch (error) {
|
|
518
|
+
outcome = {
|
|
519
|
+
ok: false,
|
|
520
|
+
error: sanitizeTesterError(error, secretValues),
|
|
491
521
|
};
|
|
492
522
|
}
|
|
493
523
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
)
|
|
524
|
+
const persisted = await this.recordValidation(
|
|
525
|
+
provider.slug,
|
|
526
|
+
slug,
|
|
527
|
+
outcome,
|
|
528
|
+
data.profile_id,
|
|
529
|
+
);
|
|
500
530
|
|
|
501
|
-
if (!
|
|
502
|
-
|
|
531
|
+
if (!outcome.ok) {
|
|
532
|
+
this.logger.warn(
|
|
533
|
+
`Integration test failed for provider "${provider.slug}" (profile "${slug}"): ${outcome.error}`,
|
|
534
|
+
);
|
|
535
|
+
throw new BadRequestException(outcome.error || 'Connection test failed.');
|
|
503
536
|
}
|
|
504
537
|
|
|
505
538
|
return {
|
|
539
|
+
// `success` e `destination` são o contrato legado consumido pela tela de
|
|
540
|
+
// e-mail (core/integrations-webhooks): mantidos com o mesmo significado.
|
|
506
541
|
success: true,
|
|
507
|
-
destination,
|
|
542
|
+
destination: String(config.from_email ?? '').trim() || outcome.info || '',
|
|
543
|
+
ok: true,
|
|
544
|
+
provider: provider.slug,
|
|
545
|
+
...(outcome.info ? { info: outcome.info } : {}),
|
|
546
|
+
...(outcome.warning ? { warning: outcome.warning } : {}),
|
|
547
|
+
tested_at: new Date().toISOString(),
|
|
548
|
+
persisted,
|
|
508
549
|
};
|
|
509
550
|
}
|
|
510
551
|
|
|
552
|
+
/** Rejeita depois de `ms`, para o caso de um tester ignorar o AbortSignal. */
|
|
553
|
+
private hardTimeout(ms: number): Promise<never> {
|
|
554
|
+
return new Promise((_resolve, reject) => {
|
|
555
|
+
const timer = setTimeout(() => {
|
|
556
|
+
const error = new Error('Connection test timed out.');
|
|
557
|
+
error.name = 'TimeoutError';
|
|
558
|
+
reject(error);
|
|
559
|
+
}, ms);
|
|
560
|
+
// Não segura o processo vivo caso o teste termine antes.
|
|
561
|
+
timer.unref?.();
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Grava metadados (não-secretos) da última validação no config do perfil.
|
|
567
|
+
*
|
|
568
|
+
* Devolve se gravou: no fluxo de criação não existe linha ainda, e a UI usa isso
|
|
569
|
+
* para avisar que o resultado não ficou registrado.
|
|
570
|
+
*/
|
|
571
|
+
private async recordValidation(
|
|
572
|
+
providerSlug: string,
|
|
573
|
+
slug: string,
|
|
574
|
+
outcome: IntegrationTestOutcome,
|
|
575
|
+
profileId?: number,
|
|
576
|
+
): Promise<boolean> {
|
|
577
|
+
try {
|
|
578
|
+
const stored = await this.prismaService.integration_profile.findUnique({
|
|
579
|
+
where: profileId ? { id: profileId } : { slug },
|
|
580
|
+
select: { id: true, config: true },
|
|
581
|
+
});
|
|
582
|
+
// Perfil ainda não salvo (teste no fluxo de criação): nada a registrar.
|
|
583
|
+
if (!stored) return false;
|
|
584
|
+
|
|
585
|
+
// Parte de `stored.config`, NUNCA do config recebido: o que o usuário digitou
|
|
586
|
+
// e ainda não salvou não pode ser persistido de carona num teste.
|
|
587
|
+
// `stored.config` vem decifrado pelo middleware; recifra-mos ao gravar.
|
|
588
|
+
const plain = {
|
|
589
|
+
...((stored.config as Record<string, unknown>) ?? {}),
|
|
590
|
+
last_validated_at: new Date().toISOString(),
|
|
591
|
+
last_validation_status: outcome.ok ? 'ok' : 'error',
|
|
592
|
+
last_error: outcome.ok ? null : (outcome.error ?? null),
|
|
593
|
+
last_validation_info: outcome.ok ? (outcome.info ?? null) : null,
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
await this.prismaService.integration_profile.update({
|
|
597
|
+
where: { id: stored.id },
|
|
598
|
+
data: {
|
|
599
|
+
config: this.credentialCrypto.encryptConfig(providerSlug, plain) as object,
|
|
600
|
+
},
|
|
601
|
+
});
|
|
602
|
+
return true;
|
|
603
|
+
} catch (error) {
|
|
604
|
+
// Falhar ao REGISTRAR não pode transformar um teste bem-sucedido em erro 500.
|
|
605
|
+
this.logger.error(
|
|
606
|
+
`Failed to record validation for profile "${slug}": ${
|
|
607
|
+
error instanceof Error ? error.message : String(error)
|
|
608
|
+
}`,
|
|
609
|
+
);
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
511
614
|
async exportProfiles({
|
|
512
615
|
ids,
|
|
513
616
|
includeSecrets = false,
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
buildDigitalOceanConfigFromIntegration,
|
|
13
13
|
buildKubernetesConfigFromIntegration,
|
|
14
14
|
buildAiConfigFromIntegration,
|
|
15
|
+
buildWhatsappOfficialConfigFromIntegration,
|
|
16
|
+
DEFAULT_GRAPH_API_VERSION,
|
|
15
17
|
} from './integration-profile.utils';
|
|
16
18
|
|
|
17
19
|
describe('integration-profile.utils', () => {
|
|
@@ -323,10 +325,105 @@ describe('integration-profile.utils', () => {
|
|
|
323
325
|
});
|
|
324
326
|
});
|
|
325
327
|
|
|
328
|
+
it('mapeia deepseek com a base URL padrão', () => {
|
|
329
|
+
expect(
|
|
330
|
+
buildAiConfigFromIntegration('deepseek', {
|
|
331
|
+
api_key: 'd',
|
|
332
|
+
model: 'deepseek-reasoner',
|
|
333
|
+
}),
|
|
334
|
+
).toEqual({
|
|
335
|
+
apiKey: 'd',
|
|
336
|
+
model: 'deepseek-reasoner',
|
|
337
|
+
baseUrl: 'https://api.deepseek.com',
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('respeita a base URL informada no perfil deepseek', () => {
|
|
342
|
+
expect(
|
|
343
|
+
buildAiConfigFromIntegration('deepseek', {
|
|
344
|
+
api_key: 'd',
|
|
345
|
+
base_url: 'https://proxy.interno/v1/',
|
|
346
|
+
}),
|
|
347
|
+
).toEqual({ apiKey: 'd', baseUrl: 'https://proxy.interno/v1' });
|
|
348
|
+
});
|
|
349
|
+
|
|
326
350
|
it('lança para provider desconhecido', () => {
|
|
327
351
|
expect(() => buildAiConfigFromIntegration('llama', {})).toThrow(
|
|
328
352
|
BadRequestException,
|
|
329
353
|
);
|
|
330
354
|
});
|
|
331
355
|
});
|
|
356
|
+
|
|
357
|
+
describe('buildWhatsappOfficialConfigFromIntegration', () => {
|
|
358
|
+
const fullConfig = {
|
|
359
|
+
app_id: '123456',
|
|
360
|
+
app_secret: 'secret',
|
|
361
|
+
business_id: 'BIZ',
|
|
362
|
+
waba_id: 'WABA',
|
|
363
|
+
access_token: 'token',
|
|
364
|
+
graph_api_version: 'v22.0',
|
|
365
|
+
verify_token: 'verify',
|
|
366
|
+
environment: 'test',
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
it('mapeia todos os campos do perfil', () => {
|
|
370
|
+
expect(buildWhatsappOfficialConfigFromIntegration(fullConfig)).toEqual({
|
|
371
|
+
appId: '123456',
|
|
372
|
+
appSecret: 'secret',
|
|
373
|
+
businessId: 'BIZ',
|
|
374
|
+
wabaId: 'WABA',
|
|
375
|
+
accessToken: 'token',
|
|
376
|
+
graphApiVersion: 'v22.0',
|
|
377
|
+
verifyToken: 'verify',
|
|
378
|
+
environment: 'test',
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it('assume a versão default da Graph API quando ausente ou vazia', () => {
|
|
383
|
+
expect(
|
|
384
|
+
buildWhatsappOfficialConfigFromIntegration({ ...fullConfig, graph_api_version: '' })
|
|
385
|
+
.graphApiVersion,
|
|
386
|
+
).toBe(DEFAULT_GRAPH_API_VERSION);
|
|
387
|
+
expect(
|
|
388
|
+
buildWhatsappOfficialConfigFromIntegration({}).graphApiVersion,
|
|
389
|
+
).toBe(DEFAULT_GRAPH_API_VERSION);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it('assume production quando o ambiente não é "test"', () => {
|
|
393
|
+
// Default seguro: um ambiente inválido não deve virar sandbox silenciosamente.
|
|
394
|
+
expect(
|
|
395
|
+
buildWhatsappOfficialConfigFromIntegration({ environment: 'qualquer' })
|
|
396
|
+
.environment,
|
|
397
|
+
).toBe('production');
|
|
398
|
+
expect(
|
|
399
|
+
buildWhatsappOfficialConfigFromIntegration({}).environment,
|
|
400
|
+
).toBe('production');
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it('omite business_id quando não informado (é opcional)', () => {
|
|
404
|
+
const result = buildWhatsappOfficialConfigFromIntegration({});
|
|
405
|
+
expect(result.businessId).toBeUndefined();
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('não quebra com config nulo e devolve campos vazios', () => {
|
|
409
|
+
expect(buildWhatsappOfficialConfigFromIntegration(null)).toMatchObject({
|
|
410
|
+
appId: '',
|
|
411
|
+
appSecret: '',
|
|
412
|
+
wabaId: '',
|
|
413
|
+
accessToken: '',
|
|
414
|
+
verifyToken: '',
|
|
415
|
+
});
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
it('remove espaços em volta dos segredos (copiar/colar do painel da Meta)', () => {
|
|
419
|
+
const result = buildWhatsappOfficialConfigFromIntegration({
|
|
420
|
+
access_token: ' token ',
|
|
421
|
+
app_secret: ' secret ',
|
|
422
|
+
verify_token: ' verify ',
|
|
423
|
+
});
|
|
424
|
+
expect(result.accessToken).toBe('token');
|
|
425
|
+
expect(result.appSecret).toBe('secret');
|
|
426
|
+
expect(result.verifyToken).toBe('verify');
|
|
427
|
+
});
|
|
428
|
+
});
|
|
332
429
|
});
|
|
@@ -98,6 +98,45 @@ export function getReplyToAddress(config: unknown): string | undefined {
|
|
|
98
98
|
return replyToName ? `${replyToName} <${replyToEmail}>` : replyToEmail;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
// ─── Messaging utilities ──────────────────────────────────────────────────────
|
|
102
|
+
|
|
103
|
+
export const DEFAULT_GRAPH_API_VERSION = 'v21.0';
|
|
104
|
+
|
|
105
|
+
export type WhatsappOfficialConfig = {
|
|
106
|
+
appId: string;
|
|
107
|
+
appSecret: string;
|
|
108
|
+
businessId?: string;
|
|
109
|
+
wabaId: string;
|
|
110
|
+
accessToken: string;
|
|
111
|
+
graphApiVersion: string;
|
|
112
|
+
verifyToken: string;
|
|
113
|
+
environment: 'test' | 'production';
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Maps an integration_profile config JSON to the Meta WhatsApp Cloud API credentials.
|
|
118
|
+
*
|
|
119
|
+
* Os números não vêm daqui: um WABA pode ter vários e cada um tem estado próprio,
|
|
120
|
+
* então eles vivem na tabela whatsapp_phone_number (library whatsapp).
|
|
121
|
+
*/
|
|
122
|
+
export function buildWhatsappOfficialConfigFromIntegration(
|
|
123
|
+
config: unknown,
|
|
124
|
+
): WhatsappOfficialConfig {
|
|
125
|
+
const cfg = (config as Cfg) ?? {};
|
|
126
|
+
const environment = String(cfg.environment ?? 'production').trim();
|
|
127
|
+
return {
|
|
128
|
+
appId: String(cfg.app_id ?? '').trim(),
|
|
129
|
+
appSecret: String(cfg.app_secret ?? '').trim(),
|
|
130
|
+
...(cfg.business_id ? { businessId: String(cfg.business_id).trim() } : {}),
|
|
131
|
+
wabaId: String(cfg.waba_id ?? '').trim(),
|
|
132
|
+
accessToken: String(cfg.access_token ?? '').trim(),
|
|
133
|
+
graphApiVersion:
|
|
134
|
+
String(cfg.graph_api_version ?? '').trim() || DEFAULT_GRAPH_API_VERSION,
|
|
135
|
+
verifyToken: String(cfg.verify_token ?? '').trim(),
|
|
136
|
+
environment: environment === 'test' ? 'test' : 'production',
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
101
140
|
// ─── Storage utilities ────────────────────────────────────────────────────────
|
|
102
141
|
|
|
103
142
|
/**
|
|
@@ -261,21 +300,58 @@ export function buildKubernetesConfigFromIntegration(
|
|
|
261
300
|
|
|
262
301
|
// ─── AI utilities ─────────────────────────────────────────────────────────────
|
|
263
302
|
|
|
264
|
-
/**
|
|
303
|
+
/**
|
|
304
|
+
* Base URL da API do DeepSeek. A API é compatível com o formato OpenAI
|
|
305
|
+
* (`POST {base}/chat/completions`), então os consumidores reaproveitam o mesmo
|
|
306
|
+
* corpo de requisição trocando apenas a URL e a chave.
|
|
307
|
+
*/
|
|
308
|
+
export const DEEPSEEK_API_BASE_URL = 'https://api.deepseek.com';
|
|
309
|
+
|
|
310
|
+
/** Modelo usado quando o perfil DeepSeek não define um (`deepseek-reasoner` é o de raciocínio). */
|
|
311
|
+
export const DEEPSEEK_DEFAULT_MODEL = 'deepseek-chat';
|
|
312
|
+
|
|
313
|
+
/** Maps an integration_profile config JSON to the API key and optional org/model/timeout needed by AI providers. */
|
|
265
314
|
export function buildAiConfigFromIntegration(
|
|
266
315
|
providerSlug: string,
|
|
267
316
|
config: unknown,
|
|
268
|
-
): {
|
|
317
|
+
): {
|
|
318
|
+
apiKey: string;
|
|
319
|
+
organization?: string;
|
|
320
|
+
model?: string;
|
|
321
|
+
timeoutMs?: number;
|
|
322
|
+
/** Endpoint OpenAI-compatible do provider (hoje só o DeepSeek usa). */
|
|
323
|
+
baseUrl?: string;
|
|
324
|
+
} {
|
|
269
325
|
const cfg = (config as Cfg) ?? {};
|
|
326
|
+
const model = String(cfg.model ?? '').trim() || undefined;
|
|
327
|
+
const parsedTimeout = Number(cfg.timeout_ms);
|
|
328
|
+
const timeoutMs = Number.isFinite(parsedTimeout) && parsedTimeout > 0 ? parsedTimeout : undefined;
|
|
329
|
+
|
|
270
330
|
switch (providerSlug.toLowerCase()) {
|
|
271
331
|
case 'openai':
|
|
272
332
|
return {
|
|
273
333
|
apiKey: String(cfg.api_key ?? ''),
|
|
274
334
|
...(cfg.organization ? { organization: String(cfg.organization) } : {}),
|
|
335
|
+
...(model ? { model } : {}),
|
|
336
|
+
...(timeoutMs ? { timeoutMs } : {}),
|
|
337
|
+
};
|
|
338
|
+
case 'deepseek':
|
|
339
|
+
return {
|
|
340
|
+
apiKey: String(cfg.api_key ?? ''),
|
|
341
|
+
...(model ? { model } : {}),
|
|
342
|
+
...(timeoutMs ? { timeoutMs } : {}),
|
|
343
|
+
baseUrl:
|
|
344
|
+
String(cfg.base_url ?? '')
|
|
345
|
+
.trim()
|
|
346
|
+
.replace(/\/+$/, '') || DEEPSEEK_API_BASE_URL,
|
|
275
347
|
};
|
|
276
348
|
case 'gemini':
|
|
277
349
|
case 'claude':
|
|
278
|
-
return {
|
|
350
|
+
return {
|
|
351
|
+
apiKey: String(cfg.api_key ?? ''),
|
|
352
|
+
...(model ? { model } : {}),
|
|
353
|
+
...(timeoutMs ? { timeoutMs } : {}),
|
|
354
|
+
};
|
|
279
355
|
default:
|
|
280
356
|
throw new BadRequestException(`Unsupported AI provider: ${providerSlug}`);
|
|
281
357
|
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import {
|
|
2
|
+
describeHttpError,
|
|
3
|
+
fail,
|
|
4
|
+
pass,
|
|
5
|
+
probeJson,
|
|
6
|
+
requireFields,
|
|
7
|
+
str,
|
|
8
|
+
} from './http-probe';
|
|
9
|
+
import { IntegrationTester } from './integration-tester.types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Testadores dos providers de IA e geração de vídeo.
|
|
13
|
+
*
|
|
14
|
+
* Todos listam modelos: é a chamada autenticada mais barata de cada API (não consome
|
|
15
|
+
* token nem gera cobrança) e prova que a chave está ativa.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const openAiTester: IntegrationTester = {
|
|
19
|
+
providerSlug: 'openai',
|
|
20
|
+
test: async (config, ctx) => {
|
|
21
|
+
const missing = requireFields(config, [['api_key', 'API key']]);
|
|
22
|
+
if (missing) return missing;
|
|
23
|
+
|
|
24
|
+
const organization = str(config, 'organization');
|
|
25
|
+
const headers: Record<string, string> = {
|
|
26
|
+
Authorization: `Bearer ${String(config.api_key ?? '')}`,
|
|
27
|
+
...(organization ? { 'OpenAI-Organization': organization } : {}),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const result = await probeJson(
|
|
31
|
+
'https://api.openai.com/v1/models',
|
|
32
|
+
{ headers },
|
|
33
|
+
ctx.signal,
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
if (result.status === 401) return fail('Invalid OpenAI API key.');
|
|
37
|
+
if (result.status === 403) {
|
|
38
|
+
return fail('This API key has no permission to list models.');
|
|
39
|
+
}
|
|
40
|
+
if (!result.ok) {
|
|
41
|
+
return fail(describeHttpError(result, 'OpenAI rejected the credentials.'));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const models: Array<{ id?: string }> = Array.isArray(result.body?.data)
|
|
45
|
+
? result.body.data
|
|
46
|
+
: [];
|
|
47
|
+
const wanted = str(config, 'model');
|
|
48
|
+
|
|
49
|
+
// Modelo indisponível para a conta não invalida a chave — o operador só precisa
|
|
50
|
+
// saber antes de descobrir na primeira chamada real.
|
|
51
|
+
if (wanted && !models.some((model) => model.id === wanted)) {
|
|
52
|
+
return pass(
|
|
53
|
+
`OpenAI — ${models.length} model(s) available`,
|
|
54
|
+
`The model "${wanted}" is not available for this account.`,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
return pass(
|
|
58
|
+
`OpenAI — ${models.length} model(s) available${wanted ? ` (${wanted} ok)` : ''}`,
|
|
59
|
+
);
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const geminiTester: IntegrationTester = {
|
|
64
|
+
providerSlug: 'gemini',
|
|
65
|
+
test: async (config, ctx) => {
|
|
66
|
+
const missing = requireFields(config, [['api_key', 'API key']]);
|
|
67
|
+
if (missing) return missing;
|
|
68
|
+
|
|
69
|
+
const url = `https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(
|
|
70
|
+
String(config.api_key ?? ''),
|
|
71
|
+
)}`;
|
|
72
|
+
const result = await probeJson(url, {}, ctx.signal);
|
|
73
|
+
|
|
74
|
+
if (result.status === 400 || result.status === 401 || result.status === 403) {
|
|
75
|
+
return fail('Invalid Gemini API key.');
|
|
76
|
+
}
|
|
77
|
+
if (!result.ok) {
|
|
78
|
+
return fail(describeHttpError(result, 'Google rejected the credentials.'));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const models: unknown[] = Array.isArray(result.body?.models)
|
|
82
|
+
? result.body.models
|
|
83
|
+
: [];
|
|
84
|
+
return pass(`Gemini — ${models.length} model(s) available`);
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const claudeTester: IntegrationTester = {
|
|
89
|
+
providerSlug: 'claude',
|
|
90
|
+
test: async (config, ctx) => {
|
|
91
|
+
const missing = requireFields(config, [['api_key', 'API key']]);
|
|
92
|
+
if (missing) return missing;
|
|
93
|
+
|
|
94
|
+
const result = await probeJson(
|
|
95
|
+
'https://api.anthropic.com/v1/models',
|
|
96
|
+
{
|
|
97
|
+
headers: {
|
|
98
|
+
'x-api-key': String(config.api_key ?? ''),
|
|
99
|
+
'anthropic-version': '2023-06-01',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
ctx.signal,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
if (result.status === 401) return fail('Invalid Anthropic API key.');
|
|
106
|
+
if (!result.ok) {
|
|
107
|
+
return fail(describeHttpError(result, 'Anthropic rejected the credentials.'));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const models: unknown[] = Array.isArray(result.body?.data) ? result.body.data : [];
|
|
111
|
+
return pass(`Claude — ${models.length} model(s) available`);
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const deepseekTester: IntegrationTester = {
|
|
116
|
+
providerSlug: 'deepseek',
|
|
117
|
+
test: async (config, ctx) => {
|
|
118
|
+
const missing = requireFields(config, [['api_key', 'API key']]);
|
|
119
|
+
if (missing) return missing;
|
|
120
|
+
|
|
121
|
+
const result = await probeJson(
|
|
122
|
+
'https://api.deepseek.com/models',
|
|
123
|
+
{ headers: { Authorization: `Bearer ${String(config.api_key ?? '')}` } },
|
|
124
|
+
ctx.signal,
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
if (result.status === 401) return fail('Invalid DeepSeek API key.');
|
|
128
|
+
if (!result.ok) {
|
|
129
|
+
return fail(describeHttpError(result, 'DeepSeek rejected the credentials.'));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const models: unknown[] = Array.isArray(result.body?.data) ? result.body.data : [];
|
|
133
|
+
return pass(`DeepSeek — ${models.length} model(s) available`);
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const lumaTester: IntegrationTester = {
|
|
138
|
+
providerSlug: 'luma',
|
|
139
|
+
test: async (config, ctx) => {
|
|
140
|
+
const missing = requireFields(config, [['api_key', 'API key']]);
|
|
141
|
+
if (missing) return missing;
|
|
142
|
+
|
|
143
|
+
const result = await probeJson(
|
|
144
|
+
'https://api.lumalabs.ai/dream-machine/v1/generations?limit=1',
|
|
145
|
+
{ headers: { Authorization: `Bearer ${String(config.api_key ?? '')}` } },
|
|
146
|
+
ctx.signal,
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
if (result.status === 401 || result.status === 403) {
|
|
150
|
+
return fail('Invalid Luma API key.');
|
|
151
|
+
}
|
|
152
|
+
if (!result.ok) {
|
|
153
|
+
return fail(describeHttpError(result, 'Luma rejected the credentials.'));
|
|
154
|
+
}
|
|
155
|
+
return pass('Luma Dream Machine');
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export const AI_TESTERS: IntegrationTester[] = [
|
|
160
|
+
openAiTester,
|
|
161
|
+
geminiTester,
|
|
162
|
+
claudeTester,
|
|
163
|
+
deepseekTester,
|
|
164
|
+
lumaTester,
|
|
165
|
+
];
|