@hed-hog/core 0.0.399 → 0.0.400
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/dist/ai/ai-agent.sort.d.ts +6 -0
- package/dist/ai/ai-agent.sort.d.ts.map +1 -0
- package/dist/ai/ai-agent.sort.js +21 -0
- package/dist/ai/ai-agent.sort.js.map +1 -0
- package/dist/ai/ai.controller.d.ts +4 -4
- package/dist/ai/ai.service.d.ts +35 -4
- package/dist/ai/ai.service.d.ts.map +1 -1
- package/dist/ai/ai.service.js +51 -137
- package/dist/ai/ai.service.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-instruction.service.js +26 -23
- package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
- package/dist/ai-instruction/ai-instruction.sort.d.ts +16 -0
- package/dist/ai-instruction/ai-instruction.sort.d.ts.map +1 -0
- package/dist/ai-instruction/ai-instruction.sort.js +32 -0
- package/dist/ai-instruction/ai-instruction.sort.js.map +1 -0
- package/dist/auth/auth.controller.d.ts +24 -8
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +8 -1
- package/dist/auth/auth.module.js.map +1 -1
- package/dist/auth/auth.service.d.ts +72 -25
- package/dist/auth/auth.service.d.ts.map +1 -1
- package/dist/auth/auth.service.js +41 -4
- package/dist/auth/auth.service.js.map +1 -1
- package/dist/auth/guards/auth.guard.d.ts +3 -1
- package/dist/auth/guards/auth.guard.d.ts.map +1 -1
- package/dist/auth/guards/auth.guard.js +12 -3
- package/dist/auth/guards/auth.guard.js.map +1 -1
- package/dist/authorize/authorize.controller.d.ts +29 -5
- package/dist/authorize/authorize.controller.d.ts.map +1 -1
- package/dist/authorize/authorize.controller.js +120 -13
- package/dist/authorize/authorize.controller.js.map +1 -1
- package/dist/authorize/authorize.errors.d.ts +34 -0
- package/dist/authorize/authorize.errors.d.ts.map +1 -0
- package/dist/authorize/authorize.errors.js +37 -0
- package/dist/authorize/authorize.errors.js.map +1 -0
- package/dist/authorize/authorize.module.d.ts.map +1 -1
- package/dist/authorize/authorize.module.js +6 -1
- package/dist/authorize/authorize.module.js.map +1 -1
- package/dist/authorize/authorize.service.d.ts +77 -3
- package/dist/authorize/authorize.service.d.ts.map +1 -1
- package/dist/authorize/authorize.service.js +212 -21
- package/dist/authorize/authorize.service.js.map +1 -1
- package/dist/authorize/dto/authorize-info.dto.d.ts +10 -1
- package/dist/authorize/dto/authorize-info.dto.d.ts.map +1 -1
- package/dist/authorize/dto/authorize-info.dto.js +16 -1
- package/dist/authorize/dto/authorize-info.dto.js.map +1 -1
- package/dist/authorize/dto/consent.dto.d.ts +10 -1
- package/dist/authorize/dto/consent.dto.d.ts.map +1 -1
- package/dist/authorize/dto/consent.dto.js +16 -1
- package/dist/authorize/dto/consent.dto.js.map +1 -1
- package/dist/authorize/dto/token.dto.d.ts +12 -0
- package/dist/authorize/dto/token.dto.d.ts.map +1 -1
- package/dist/authorize/dto/token.dto.js +21 -1
- package/dist/authorize/dto/token.dto.js.map +1 -1
- package/dist/authorize/oauth-exception.filter.d.ts +17 -0
- package/dist/authorize/oauth-exception.filter.d.ts.map +1 -0
- package/dist/authorize/oauth-exception.filter.js +54 -0
- package/dist/authorize/oauth-exception.filter.js.map +1 -0
- package/dist/authorize/oauth-metadata.service.d.ts +39 -0
- package/dist/authorize/oauth-metadata.service.d.ts.map +1 -0
- package/dist/authorize/oauth-metadata.service.js +81 -0
- package/dist/authorize/oauth-metadata.service.js.map +1 -0
- package/dist/authorize/well-known.controller.d.ts +67 -0
- package/dist/authorize/well-known.controller.d.ts.map +1 -0
- package/dist/authorize/well-known.controller.js +126 -0
- package/dist/authorize/well-known.controller.js.map +1 -0
- package/dist/captcha/captcha.service.d.ts +32 -2
- package/dist/captcha/captcha.service.d.ts.map +1 -1
- package/dist/captcha/captcha.service.js +85 -12
- package/dist/captcha/captcha.service.js.map +1 -1
- package/dist/challenge/challenge.service.d.ts +2 -2
- package/dist/core.module.d.ts.map +1 -1
- package/dist/core.module.js +6 -0
- package/dist/core.module.js.map +1 -1
- package/dist/dashboard/dashboard/dashboard.controller.d.ts +9 -9
- package/dist/dashboard/dashboard/dashboard.service.d.ts +9 -9
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +3 -3
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +3 -3
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +3 -3
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +3 -3
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js +2 -4
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js.map +1 -1
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts +8 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts.map +1 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js +18 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js.map +1 -0
- package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.service.js +2 -4
- package/dist/dashboard/dashboard-item/dashboard-item.service.js.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts +9 -0
- package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts.map +1 -0
- package/dist/dashboard/dashboard-item/dashboard-item.sort.js +19 -0
- package/dist/dashboard/dashboard-item/dashboard-item.sort.js.map +1 -0
- package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +3 -3
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +3 -3
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-role/dashboard-role.service.js +2 -4
- package/dist/dashboard/dashboard-role/dashboard-role.service.js.map +1 -1
- package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts +8 -0
- package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts.map +1 -0
- package/dist/dashboard/dashboard-role/dashboard-role.sort.js +16 -0
- package/dist/dashboard/dashboard-role/dashboard-role.sort.js.map +1 -0
- package/dist/file/file-upload-ticket.service.d.ts +160 -0
- package/dist/file/file-upload-ticket.service.d.ts.map +1 -0
- package/dist/file/file-upload-ticket.service.js +382 -0
- package/dist/file/file-upload-ticket.service.js.map +1 -0
- package/dist/file/file.controller.d.ts +24 -1
- package/dist/file/file.controller.d.ts.map +1 -1
- package/dist/file/file.controller.js +63 -2
- package/dist/file/file.controller.js.map +1 -1
- package/dist/file/file.module.d.ts.map +1 -1
- package/dist/file/file.module.js +14 -2
- package/dist/file/file.module.js.map +1 -1
- package/dist/file/file.service.d.ts +182 -6
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +386 -54
- package/dist/file/file.service.js.map +1 -1
- package/dist/file/filename-encoding.util.d.ts +24 -0
- package/dist/file/filename-encoding.util.d.ts.map +1 -0
- package/dist/file/filename-encoding.util.js +63 -0
- package/dist/file/filename-encoding.util.js.map +1 -0
- package/dist/file/image-optimization.service.d.ts +27 -0
- package/dist/file/image-optimization.service.d.ts.map +1 -1
- package/dist/file/image-optimization.service.js +63 -14
- package/dist/file/image-optimization.service.js.map +1 -1
- package/dist/file/mcp-file-source.schema.d.ts +33 -0
- package/dist/file/mcp-file-source.schema.d.ts.map +1 -0
- package/dist/file/mcp-file-source.schema.js +75 -0
- package/dist/file/mcp-file-source.schema.js.map +1 -0
- package/dist/file/mcp-file-source.service.d.ts +124 -0
- package/dist/file/mcp-file-source.service.d.ts.map +1 -0
- package/dist/file/mcp-file-source.service.js +262 -0
- package/dist/file/mcp-file-source.service.js.map +1 -0
- package/dist/file/mimetype-sniff.util.d.ts +62 -0
- package/dist/file/mimetype-sniff.util.d.ts.map +1 -0
- package/dist/file/mimetype-sniff.util.js +226 -0
- package/dist/file/mimetype-sniff.util.js.map +1 -0
- package/dist/file/remote-fetch.util.d.ts +35 -0
- package/dist/file/remote-fetch.util.d.ts.map +1 -0
- package/dist/file/remote-fetch.util.js +236 -0
- package/dist/file/remote-fetch.util.js.map +1 -0
- package/dist/impersonation/dto/start-impersonation.dto.d.ts +4 -1
- package/dist/impersonation/dto/start-impersonation.dto.d.ts.map +1 -1
- package/dist/impersonation/dto/start-impersonation.dto.js +1 -1
- package/dist/impersonation/dto/start-impersonation.dto.js.map +1 -1
- package/dist/impersonation/impersonation.service.d.ts +8 -3
- package/dist/impersonation/impersonation.service.d.ts.map +1 -1
- package/dist/impersonation/impersonation.service.js +14 -4
- package/dist/impersonation/impersonation.service.js.map +1 -1
- package/dist/incident/incident.controller.d.ts +2 -1
- package/dist/incident/incident.controller.d.ts.map +1 -1
- package/dist/incident/incident.controller.js +10 -6
- package/dist/incident/incident.controller.js.map +1 -1
- package/dist/incident/incident.service.d.ts +2 -0
- package/dist/incident/incident.service.d.ts.map +1 -1
- package/dist/incident/incident.service.js +4 -0
- package/dist/incident/incident.service.js.map +1 -1
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.secrets.js +7 -0
- package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
- package/dist/integration-profile/integration-profile.service.d.ts +0 -13
- package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
- package/dist/integration-profile/integration-profile.service.js +5 -40
- package/dist/integration-profile/integration-profile.service.js.map +1 -1
- package/dist/integration-profile/integration-profile.utils.js +5 -5
- package/dist/integration-profile/integration-profile.utils.js.map +1 -1
- package/dist/integration-profile/testers/index.d.ts.map +1 -1
- package/dist/integration-profile/testers/index.js +2 -0
- package/dist/integration-profile/testers/index.js.map +1 -1
- package/dist/integration-profile/testers/shipping.testers.d.ts +3 -0
- package/dist/integration-profile/testers/shipping.testers.d.ts.map +1 -0
- package/dist/integration-profile/testers/shipping.testers.js +71 -0
- package/dist/integration-profile/testers/shipping.testers.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/send.dto.d.ts +6 -1
- package/dist/mail/dto/send.dto.d.ts.map +1 -1
- package/dist/mail/dto/send.dto.js.map +1 -1
- package/dist/mail/mail.service.d.ts +9 -0
- package/dist/mail/mail.service.d.ts.map +1 -1
- package/dist/mail/mail.service.js +34 -14
- package/dist/mail/mail.service.js.map +1 -1
- package/dist/mail-sent/mail-sent.controller.d.ts +1 -1
- package/dist/mail-sent/mail-sent.service.d.ts +1 -1
- package/dist/mail-sent/mail-sent.service.d.ts.map +1 -1
- package/dist/mail-sent/mail-sent.service.js +2 -1
- package/dist/mail-sent/mail-sent.service.js.map +1 -1
- package/dist/mail-sent/mail-sent.sort.d.ts +9 -0
- package/dist/mail-sent/mail-sent.sort.d.ts.map +1 -0
- package/dist/mail-sent/mail-sent.sort.js +19 -0
- package/dist/mail-sent/mail-sent.sort.js.map +1 -0
- package/dist/mcp/filters/mcp-challenge.filter.d.ts +20 -0
- package/dist/mcp/filters/mcp-challenge.filter.d.ts.map +1 -0
- package/dist/mcp/filters/mcp-challenge.filter.js +69 -0
- package/dist/mcp/filters/mcp-challenge.filter.js.map +1 -0
- package/dist/mcp/guards/mcp-auth.guard.d.ts +4 -1
- package/dist/mcp/guards/mcp-auth.guard.d.ts.map +1 -1
- package/dist/mcp/guards/mcp-auth.guard.js +19 -5
- package/dist/mcp/guards/mcp-auth.guard.js.map +1 -1
- package/dist/mcp/guards/mcp-permission.guard.d.ts +25 -3
- package/dist/mcp/guards/mcp-permission.guard.d.ts.map +1 -1
- package/dist/mcp/guards/mcp-permission.guard.js +46 -26
- package/dist/mcp/guards/mcp-permission.guard.js.map +1 -1
- package/dist/mcp/mcp-audit.service.d.ts +17 -0
- package/dist/mcp/mcp-audit.service.d.ts.map +1 -1
- package/dist/mcp/mcp-audit.service.js +32 -3
- package/dist/mcp/mcp-audit.service.js.map +1 -1
- package/dist/mcp/mcp-permission.service.d.ts +64 -0
- package/dist/mcp/mcp-permission.service.d.ts.map +1 -0
- package/dist/mcp/mcp-permission.service.js +178 -0
- package/dist/mcp/mcp-permission.service.js.map +1 -0
- package/dist/mcp/mcp-server.service.d.ts +3 -1
- package/dist/mcp/mcp-server.service.d.ts.map +1 -1
- package/dist/mcp/mcp-server.service.js +36 -15
- package/dist/mcp/mcp-server.service.js.map +1 -1
- package/dist/mcp/mcp.controller.d.ts.map +1 -1
- package/dist/mcp/mcp.controller.js +10 -2
- package/dist/mcp/mcp.controller.js.map +1 -1
- package/dist/mcp/mcp.module.d.ts.map +1 -1
- package/dist/mcp/mcp.module.js +5 -1
- package/dist/mcp/mcp.module.js.map +1 -1
- package/dist/mcp/tools/core-ai.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-ai.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-dashboard-items.mcp-tools.js +1 -1
- package/dist/mcp/tools/core-dashboard-items.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-dashboard.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-dashboard.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-event-webhooks.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-event-webhooks.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-event-webhooks.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-files.mcp-tools.d.ts +17 -5
- package/dist/mcp/tools/core-files.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-files.mcp-tools.js +186 -24
- package/dist/mcp/tools/core-files.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-integration-events.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-integration-events.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-mail-sent.mcp-tools.js +2 -14
- package/dist/mcp/tools/core-mail-sent.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-mail.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-mail.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-menus.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-menus.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-menus.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-notifications.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-notifications.mcp-tools.js +0 -1
- package/dist/mcp/tools/core-notifications.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-roles.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-roles.mcp-tools.js +2 -13
- package/dist/mcp/tools/core-roles.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-routes.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-routes.mcp-tools.js +2 -11
- package/dist/mcp/tools/core-routes.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-screens.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-screens.mcp-tools.js +2 -11
- package/dist/mcp/tools/core-screens.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-sessions.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-sessions.mcp-tools.js +0 -2
- package/dist/mcp/tools/core-sessions.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-settings.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-settings.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-settings.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-users.mcp-tools.js +2 -9
- package/dist/mcp/tools/core-users.mcp-tools.js.map +1 -1
- package/dist/mcp/tools/core-webhooks.mcp-tools.d.ts.map +1 -1
- package/dist/mcp/tools/core-webhooks.mcp-tools.js +2 -10
- package/dist/mcp/tools/core-webhooks.mcp-tools.js.map +1 -1
- package/dist/mcp/types/mcp-context.type.d.ts +9 -0
- package/dist/mcp/types/mcp-context.type.d.ts.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
- package/dist/mcp-chat/mcp-chat.service.js +8 -0
- package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
- package/dist/meeting/meeting-provider.registry.d.ts +115 -0
- package/dist/meeting/meeting-provider.registry.d.ts.map +1 -1
- package/dist/meeting/meeting-provider.registry.js.map +1 -1
- package/dist/meeting/meeting.constants.d.ts +70 -0
- package/dist/meeting/meeting.constants.d.ts.map +1 -1
- package/dist/meeting/meeting.constants.js +9 -1
- package/dist/meeting/meeting.constants.js.map +1 -1
- package/dist/menu/menu.service.d.ts.map +1 -1
- package/dist/menu/menu.service.js +29 -9
- package/dist/menu/menu.service.js.map +1 -1
- package/dist/message-template/dto/update-message-template.dto.d.ts +18 -0
- package/dist/message-template/dto/update-message-template.dto.d.ts.map +1 -0
- package/dist/message-template/dto/update-message-template.dto.js +38 -0
- package/dist/message-template/dto/update-message-template.dto.js.map +1 -0
- package/dist/message-template/message-template-admin.service.d.ts +70 -0
- package/dist/message-template/message-template-admin.service.d.ts.map +1 -0
- package/dist/message-template/message-template-admin.service.js +226 -0
- package/dist/message-template/message-template-admin.service.js.map +1 -0
- package/dist/message-template/message-template.controller.d.ts +29 -0
- package/dist/message-template/message-template.controller.d.ts.map +1 -0
- package/dist/message-template/message-template.controller.js +101 -0
- package/dist/message-template/message-template.controller.js.map +1 -0
- package/dist/message-template/message-template.module.d.ts +10 -0
- package/dist/message-template/message-template.module.d.ts.map +1 -0
- package/dist/message-template/message-template.module.js +33 -0
- package/dist/message-template/message-template.module.js.map +1 -0
- package/dist/message-template/message-template.registry.d.ts +55 -0
- package/dist/message-template/message-template.registry.d.ts.map +1 -0
- package/dist/message-template/message-template.registry.js +64 -0
- package/dist/message-template/message-template.registry.js.map +1 -0
- package/dist/message-template/message-template.service.d.ts +59 -0
- package/dist/message-template/message-template.service.d.ts.map +1 -0
- package/dist/message-template/message-template.service.js +166 -0
- package/dist/message-template/message-template.service.js.map +1 -0
- package/dist/notification/notification.constants.d.ts +11 -0
- package/dist/notification/notification.constants.d.ts.map +1 -0
- package/dist/notification/notification.constants.js +14 -0
- package/dist/notification/notification.constants.js.map +1 -0
- package/dist/notification/notification.controller.d.ts +20 -20
- package/dist/notification/notification.module.d.ts.map +1 -1
- package/dist/notification/notification.module.js +3 -0
- package/dist/notification/notification.module.js.map +1 -1
- package/dist/notification/notification.service.d.ts +33 -21
- package/dist/notification/notification.service.d.ts.map +1 -1
- package/dist/notification/notification.service.js +36 -2
- package/dist/notification/notification.service.js.map +1 -1
- package/dist/oauth/oauth.controller.d.ts +4 -6
- package/dist/oauth/oauth.controller.d.ts.map +1 -1
- package/dist/oauth/oauth.controller.js +0 -1
- package/dist/oauth/oauth.controller.js.map +1 -1
- package/dist/oauth/oauth.errors.d.ts +15 -1
- package/dist/oauth/oauth.errors.d.ts.map +1 -1
- package/dist/oauth/oauth.errors.js +9 -1
- package/dist/oauth/oauth.errors.js.map +1 -1
- package/dist/oauth/oauth.module.d.ts.map +1 -1
- package/dist/oauth/oauth.module.js +6 -1
- package/dist/oauth/oauth.module.js.map +1 -1
- package/dist/oauth/oauth.service.d.ts +25 -5
- package/dist/oauth/oauth.service.d.ts.map +1 -1
- package/dist/oauth/oauth.service.js +63 -27
- package/dist/oauth/oauth.service.js.map +1 -1
- package/dist/oauth/providers/abstract.provider.d.ts +10 -0
- package/dist/oauth/providers/abstract.provider.d.ts.map +1 -1
- package/dist/oauth/providers/abstract.provider.js +39 -12
- package/dist/oauth/providers/abstract.provider.js.map +1 -1
- package/dist/oauth/providers/github.provider.d.ts +1 -1
- package/dist/oauth/providers/github.provider.d.ts.map +1 -1
- package/dist/oauth/providers/github.provider.js +48 -22
- package/dist/oauth/providers/github.provider.js.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.js +6 -0
- package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
- package/dist/observability/monitored-cron.d.ts +29 -12
- package/dist/observability/monitored-cron.d.ts.map +1 -1
- package/dist/observability/monitored-cron.js +131 -46
- package/dist/observability/monitored-cron.js.map +1 -1
- package/dist/pairing/pairing.service.d.ts +6 -2
- package/dist/pairing/pairing.service.d.ts.map +1 -1
- package/dist/profile/dto/change-password.dto.d.ts.map +1 -1
- package/dist/profile/dto/change-password.dto.js +4 -6
- package/dist/profile/dto/change-password.dto.js.map +1 -1
- package/dist/profile/profile.controller.d.ts +1 -1
- package/dist/profile/profile.service.d.ts +1 -1
- package/dist/profile/profile.service.d.ts.map +1 -1
- package/dist/profile/profile.service.js +9 -3
- package/dist/profile/profile.service.js.map +1 -1
- package/dist/realtime/realtime-tick.coalescer.d.ts +34 -0
- package/dist/realtime/realtime-tick.coalescer.d.ts.map +1 -0
- package/dist/realtime/realtime-tick.coalescer.js +60 -0
- package/dist/realtime/realtime-tick.coalescer.js.map +1 -0
- package/dist/realtime/realtime.service.d.ts +2 -0
- package/dist/realtime/realtime.service.d.ts.map +1 -1
- package/dist/realtime/realtime.service.js +22 -2
- package/dist/realtime/realtime.service.js.map +1 -1
- package/dist/redis/redis-kv.service.d.ts +90 -0
- package/dist/redis/redis-kv.service.d.ts.map +1 -0
- package/dist/redis/redis-kv.service.js +247 -0
- package/dist/redis/redis-kv.service.js.map +1 -0
- package/dist/redis/redis-master.d.ts +29 -0
- package/dist/redis/redis-master.d.ts.map +1 -0
- package/dist/redis/redis-master.js +81 -0
- package/dist/redis/redis-master.js.map +1 -0
- package/dist/redis/redis-pubsub.d.ts +12 -0
- package/dist/redis/redis-pubsub.d.ts.map +1 -1
- package/dist/redis/redis-pubsub.js +25 -2
- package/dist/redis/redis-pubsub.js.map +1 -1
- package/dist/redis/redis.module.d.ts +11 -0
- package/dist/redis/redis.module.d.ts.map +1 -0
- package/dist/redis/redis.module.js +30 -0
- package/dist/redis/redis.module.js.map +1 -0
- package/dist/session/session.controller.d.ts +6 -2
- package/dist/session/session.controller.d.ts.map +1 -1
- package/dist/session/session.service.d.ts +118 -15
- package/dist/session/session.service.d.ts.map +1 -1
- package/dist/session/session.service.js +251 -77
- package/dist/session/session.service.js.map +1 -1
- package/dist/setting/setting.controller.d.ts +5 -0
- package/dist/setting/setting.controller.d.ts.map +1 -1
- package/dist/setting/setting.service.d.ts +7 -0
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +38 -3
- package/dist/setting/setting.service.js.map +1 -1
- package/dist/task/task.service.d.ts +17 -0
- package/dist/task/task.service.d.ts.map +1 -1
- package/dist/task/task.service.js +48 -13
- package/dist/task/task.service.js.map +1 -1
- package/dist/token/token.service.d.ts +19 -1
- package/dist/token/token.service.d.ts.map +1 -1
- package/dist/token/token.service.js +39 -2
- package/dist/token/token.service.js.map +1 -1
- package/dist/user/user-credential.util.d.ts +10 -0
- package/dist/user/user-credential.util.d.ts.map +1 -1
- package/dist/user/user-credential.util.js +14 -1
- package/dist/user/user-credential.util.js.map +1 -1
- package/dist/user/user.service.d.ts +12 -4
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +2 -11
- package/dist/user/user.service.js.map +1 -1
- package/dist/user/user.sort.d.ts +16 -0
- package/dist/user/user.sort.d.ts.map +1 -0
- package/dist/user/user.sort.js +25 -0
- package/dist/user/user.sort.js.map +1 -0
- package/dist/utils/abbreviate-name.d.ts +13 -0
- package/dist/utils/abbreviate-name.d.ts.map +1 -0
- package/dist/utils/abbreviate-name.js +42 -0
- package/dist/utils/abbreviate-name.js.map +1 -0
- package/dist/utils/date-range-query.dto.d.ts +11 -0
- package/dist/utils/date-range-query.dto.d.ts.map +1 -0
- package/dist/utils/date-range-query.dto.js +63 -0
- package/dist/utils/date-range-query.dto.js.map +1 -0
- package/dist/utils/date-range.d.ts +96 -0
- package/dist/utils/date-range.d.ts.map +1 -0
- package/dist/utils/date-range.js +172 -0
- package/dist/utils/date-range.js.map +1 -0
- package/dist/webhook-integration/webhook-utils.d.ts.map +1 -1
- package/dist/webhook-integration/webhook-utils.js +24 -0
- package/dist/webhook-integration/webhook-utils.js.map +1 -1
- package/dist/whatsapp-sender/whatsapp-recipients.d.ts +49 -0
- package/dist/whatsapp-sender/whatsapp-recipients.d.ts.map +1 -0
- package/dist/whatsapp-sender/whatsapp-recipients.js +66 -0
- package/dist/whatsapp-sender/whatsapp-recipients.js.map +1 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +25 -0
- package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -1
- package/dist/whatsapp-sender/whatsapp-sender.service.js +46 -5
- package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -1
- package/hedhog/data/integration_provider.yaml +9 -0
- package/hedhog/data/integration_type.yaml +6 -0
- package/hedhog/data/locale.yaml +0 -1
- package/hedhog/data/mail.yaml +2 -2
- package/hedhog/data/mail_layout.yaml +6 -3
- package/hedhog/data/menu.yaml +25 -5
- package/hedhog/data/route.yaml +140 -0
- package/hedhog/data/setting_group.yaml +137 -3
- package/hedhog/frontend/app/access-log/page.tsx.ejs +47 -53
- package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +33 -8
- package/hedhog/frontend/app/account/components/mcp-tokens.tsx.ejs +54 -13
- package/hedhog/frontend/app/account/components/mfa-method-card.tsx.ejs +7 -1
- package/hedhog/frontend/app/account/components/recovery-codes-dialog.tsx.ejs +1 -0
- package/hedhog/frontend/app/account/components/tokens.tsx.ejs +47 -17
- package/hedhog/frontend/app/ai_agent/page.tsx.ejs +46 -5
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +101 -30
- package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +24 -8
- package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +80 -15
- package/hedhog/frontend/app/configurations/[slug]/components/image-optimization-action.tsx.ejs +166 -0
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.test.tsx.ejs +145 -45
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +99 -219
- package/hedhog/frontend/app/configurations/[slug]/page.tsx.ejs +19 -1
- package/hedhog/frontend/app/configurations/layout.tsx.ejs +19 -5
- package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +2 -8
- package/hedhog/frontend/app/dashboard/components/dynamic-widget.tsx.ejs +3 -0
- package/hedhog/frontend/app/dashboard/components/widget-wrapper.tsx.ejs +4 -0
- package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +43 -44
- package/hedhog/frontend/app/dashboard/management/tabs/component-roles-tab.tsx.ejs +41 -3
- package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +42 -2
- package/hedhog/frontend/app/dashboard/management/tabs/dashboard-roles-tab.tsx.ejs +41 -3
- package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +39 -4
- package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +42 -3
- package/hedhog/frontend/app/incidents/page.tsx.ejs +60 -31
- package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +45 -5
- package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +92 -15
- package/hedhog/frontend/app/mail/log/page.tsx.ejs +109 -61
- package/hedhog/frontend/app/mail/template/page.tsx.ejs +125 -23
- package/hedhog/frontend/app/mcp_chat/chat-components.tsx.ejs +13 -15
- package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +116 -110
- package/hedhog/frontend/app/message-templates/_components/message-template-sheet.tsx.ejs +245 -0
- package/hedhog/frontend/app/message-templates/_lib/types.ts.ejs +24 -0
- package/hedhog/frontend/app/message-templates/page.tsx.ejs +182 -0
- package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1 -0
- package/hedhog/frontend/app/pages/page.tsx.ejs +94 -9
- package/hedhog/frontend/app/roles/menus.tsx.ejs +4 -4
- package/hedhog/frontend/app/roles/routes.tsx.ejs +4 -4
- package/hedhog/frontend/app/roles/users.tsx.ejs +4 -4
- package/hedhog/frontend/app/setting-list/page.tsx.ejs +71 -9
- package/hedhog/frontend/app/users/page.tsx.ejs +77 -67
- package/hedhog/frontend/messages/en.json +183 -36
- package/hedhog/frontend/messages/pt.json +183 -36
- package/hedhog/table/cron_lock.yaml +17 -0
- package/hedhog/table/file.yaml +13 -1
- package/hedhog/table/file_upload_chunk.yaml +23 -0
- package/hedhog/table/file_upload_ticket.yaml +67 -0
- package/hedhog/table/mcp_tool_call_log.yaml +30 -22
- package/hedhog/table/message_template.yaml +33 -0
- package/hedhog/table/setting.yaml +8 -0
- package/hedhog/table/user_session.yaml +36 -1
- package/package.json +7 -5
- package/src/ai/ai-agent.sort.ts +21 -0
- package/src/ai/ai.service.spec.ts +173 -1
- package/src/ai/ai.service.ts +64 -193
- package/src/ai-instruction/ai-instruction.service.ts +32 -28
- package/src/ai-instruction/ai-instruction.sort.ts +32 -0
- package/src/auth/auth.module.ts +8 -1
- package/src/auth/auth.service.spec.ts +108 -1
- package/src/auth/auth.service.ts +59 -5
- package/src/auth/guards/auth.guard.ts +9 -1
- package/src/authorize/authorize.controller.ts +126 -11
- package/src/authorize/authorize.errors.ts +55 -0
- package/src/authorize/authorize.module.ts +6 -1
- package/src/authorize/authorize.service.spec.ts +379 -7
- package/src/authorize/authorize.service.ts +309 -23
- package/src/authorize/dto/authorize-info.dto.ts +21 -3
- package/src/authorize/dto/consent.dto.ts +21 -3
- package/src/authorize/dto/token.dto.ts +24 -2
- package/src/authorize/oauth-exception.filter.ts +58 -0
- package/src/authorize/oauth-metadata.service.ts +67 -0
- package/src/authorize/well-known.controller.spec.ts +84 -0
- package/src/authorize/well-known.controller.ts +96 -0
- package/src/captcha/captcha.service.spec.ts +211 -4
- package/src/captcha/captcha.service.ts +127 -10
- package/src/core.module.ts +6 -0
- package/src/dashboard/dashboard-component-role/dashboard-component-role.service.ts +2 -3
- package/src/dashboard/dashboard-component-role/dashboard-component-role.sort.ts +18 -0
- package/src/dashboard/dashboard-item/dashboard-item.service.ts +2 -3
- package/src/dashboard/dashboard-item/dashboard-item.sort.ts +19 -0
- package/src/dashboard/dashboard-role/dashboard-role.service.ts +2 -3
- package/src/dashboard/dashboard-role/dashboard-role.sort.ts +16 -0
- package/src/file/file-upload-ticket.service.spec.ts +422 -0
- package/src/file/file-upload-ticket.service.ts +513 -0
- package/src/file/file.controller.ts +65 -0
- package/src/file/file.module.ts +14 -2
- package/src/file/file.service.spec.ts +94 -0
- package/src/file/file.service.ts +433 -53
- package/src/file/filename-encoding.util.spec.ts +54 -0
- package/src/file/filename-encoding.util.ts +67 -0
- package/src/file/image-optimization.service.spec.ts +156 -19
- package/src/file/image-optimization.service.ts +106 -21
- package/src/file/mcp-file-source.schema.ts +83 -0
- package/src/file/mcp-file-source.service.spec.ts +473 -0
- package/src/file/mcp-file-source.service.ts +445 -0
- package/src/file/mimetype-sniff.util.spec.ts +126 -0
- package/src/file/mimetype-sniff.util.ts +265 -0
- package/src/file/remote-fetch.util.spec.ts +117 -0
- package/src/file/remote-fetch.util.ts +330 -0
- package/src/impersonation/dto/start-impersonation.dto.ts +5 -2
- package/src/impersonation/impersonation.service.spec.ts +24 -1
- package/src/impersonation/impersonation.service.ts +14 -4
- package/src/incident/incident.controller.ts +9 -1
- package/src/incident/incident.service.ts +7 -0
- package/src/index.ts +17 -0
- package/src/integration-profile/integration-profile.secrets.ts +7 -0
- package/src/integration-profile/integration-profile.service.ts +7 -64
- package/src/integration-profile/integration-profile.utils.spec.ts +9 -0
- package/src/integration-profile/integration-profile.utils.ts +5 -5
- package/src/integration-profile/testers/index.ts +2 -0
- package/src/integration-profile/testers/remaining.testers.spec.ts +79 -0
- package/src/integration-profile/testers/shipping.testers.ts +94 -0
- package/src/mail/dto/send.dto.ts +6 -1
- package/src/mail/mail-template.spec.ts +58 -1
- package/src/mail/mail.service.spec.ts +112 -0
- package/src/mail/mail.service.ts +42 -4
- package/src/mail-sent/mail-sent.service.ts +3 -0
- package/src/mail-sent/mail-sent.sort.ts +19 -0
- package/src/mcp/filters/mcp-challenge.filter.spec.ts +76 -0
- package/src/mcp/filters/mcp-challenge.filter.ts +70 -0
- package/src/mcp/guards/mcp-auth.guard.spec.ts +51 -2
- package/src/mcp/guards/mcp-auth.guard.ts +24 -1
- package/src/mcp/guards/mcp-permission.guard.spec.ts +109 -15
- package/src/mcp/guards/mcp-permission.guard.ts +76 -51
- package/src/mcp/mcp-audit.service.spec.ts +107 -0
- package/src/mcp/mcp-audit.service.ts +37 -1
- package/src/mcp/mcp-permission.service.spec.ts +197 -0
- package/src/mcp/mcp-permission.service.ts +184 -0
- package/src/mcp/mcp-server.service.spec.ts +84 -2
- package/src/mcp/mcp-server.service.ts +111 -87
- package/src/mcp/mcp.controller.ts +8 -1
- package/src/mcp/mcp.module.ts +5 -1
- package/src/mcp/tools/core-ai.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-dashboard-items.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-dashboard.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-event-webhooks.mcp-tools.ts +1 -2
- package/src/mcp/tools/core-files.mcp-tools.ts +202 -22
- package/src/mcp/tools/core-integration-events.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-mail-sent.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-mail.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-menus.mcp-tools.ts +1 -2
- package/src/mcp/tools/core-notifications.mcp-tools.ts +0 -1
- package/src/mcp/tools/core-roles.mcp-tools.ts +1 -5
- package/src/mcp/tools/core-routes.mcp-tools.ts +1 -3
- package/src/mcp/tools/core-screens.mcp-tools.ts +1 -3
- package/src/mcp/tools/core-sessions.mcp-tools.ts +0 -2
- package/src/mcp/tools/core-settings.mcp-tools.ts +1 -2
- package/src/mcp/tools/core-users.mcp-tools.ts +1 -1
- package/src/mcp/tools/core-webhooks.mcp-tools.ts +1 -2
- package/src/mcp/types/mcp-context.type.ts +15 -6
- package/src/mcp-chat/mcp-chat.service.ts +8 -0
- package/src/meeting/meeting-provider.registry.ts +121 -0
- package/src/meeting/meeting.constants.ts +74 -0
- package/src/menu/menu.service.spec.ts +89 -0
- package/src/menu/menu.service.ts +29 -11
- package/src/message-template/dto/update-message-template.dto.ts +22 -0
- package/src/message-template/message-template-admin.service.spec.ts +163 -0
- package/src/message-template/message-template-admin.service.ts +239 -0
- package/src/message-template/message-template.controller.ts +52 -0
- package/src/message-template/message-template.module.ts +21 -0
- package/src/message-template/message-template.registry.spec.ts +62 -0
- package/src/message-template/message-template.registry.ts +125 -0
- package/src/message-template/message-template.service.spec.ts +149 -0
- package/src/message-template/message-template.service.ts +149 -0
- package/src/notification/notification.constants.ts +10 -0
- package/src/notification/notification.module.ts +3 -0
- package/src/notification/notification.service.spec.ts +75 -1
- package/src/notification/notification.service.ts +39 -1
- package/src/oauth/oauth.controller.ts +0 -1
- package/src/oauth/oauth.errors.ts +7 -0
- package/src/oauth/oauth.module.ts +6 -1
- package/src/oauth/oauth.service.spec.ts +58 -7
- package/src/oauth/oauth.service.ts +71 -32
- package/src/oauth/providers/abstract.provider.spec.ts +192 -0
- package/src/oauth/providers/abstract.provider.ts +46 -14
- package/src/oauth/providers/github.provider.ts +57 -34
- package/src/oauth/providers/microsoft-entra-id.provider.ts +8 -1
- package/src/observability/monitored-cron.spec.ts +164 -31
- package/src/observability/monitored-cron.ts +154 -62
- package/src/profile/dto/change-password.dto.ts +25 -7
- package/src/profile/profile.service.spec.ts +97 -0
- package/src/profile/profile.service.ts +9 -3
- package/src/realtime/realtime-tick.coalescer.spec.ts +92 -0
- package/src/realtime/realtime-tick.coalescer.ts +60 -0
- package/src/realtime/realtime.service.spec.ts +33 -0
- package/src/realtime/realtime.service.ts +28 -2
- package/src/redis/redis-kv.service.ts +261 -0
- package/src/redis/redis-master.spec.ts +111 -0
- package/src/redis/redis-master.ts +86 -0
- package/src/redis/redis-pubsub.ts +27 -3
- package/src/redis/redis.module.ts +17 -0
- package/src/session/session.service.spec.ts +121 -42
- package/src/session/session.service.ts +279 -82
- package/src/setting/setting.service.ts +44 -3
- package/src/task/task.service.spec.ts +41 -0
- package/src/task/task.service.ts +53 -13
- package/src/token/token.service.spec.ts +90 -0
- package/src/token/token.service.ts +48 -2
- package/src/user/user-credential.util.ts +14 -5
- package/src/user/user.service.ts +2 -12
- package/src/user/user.sort.ts +25 -0
- package/src/utils/abbreviate-name.spec.ts +50 -0
- package/src/utils/abbreviate-name.ts +44 -0
- package/src/utils/date-range-query.dto.ts +56 -0
- package/src/utils/date-range.spec.ts +175 -0
- package/src/utils/date-range.ts +246 -0
- package/src/webhook-integration/webhook-utils.spec.ts +67 -0
- package/src/webhook-integration/webhook-utils.ts +26 -0
- package/src/whatsapp-sender/whatsapp-recipients.spec.ts +89 -0
- package/src/whatsapp-sender/whatsapp-recipients.ts +83 -0
- package/src/whatsapp-sender/whatsapp-sender.service.spec.ts +112 -0
- package/src/whatsapp-sender/whatsapp-sender.service.ts +58 -5
- package/hedhog/query/device_pairing_request.sql +0 -46
- package/hedhog/query/impersonation_grant.sql +0 -71
- package/hedhog/query/oauth_authorize_pkce.sql +0 -58
- package/hedhog/query/oauth_mobile_state_token.sql +0 -30
- package/hedhog/query/oauth_web_ref_token.sql +0 -25
|
@@ -4,6 +4,8 @@ import { AccessLogService } from '../access-log/access-log.service';
|
|
|
4
4
|
|
|
5
5
|
interface AuditRecord {
|
|
6
6
|
userId: number;
|
|
7
|
+
/** Client OAuth externo, ou null para o caminho interno. */
|
|
8
|
+
clientId?: string | null;
|
|
7
9
|
toolName: string;
|
|
8
10
|
input: Record<string, any>;
|
|
9
11
|
success: boolean;
|
|
@@ -21,12 +23,46 @@ export class McpAuditService {
|
|
|
21
23
|
private readonly accessLogService: AccessLogService,
|
|
22
24
|
) {}
|
|
23
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Campos que carregam o conteúdo de um arquivo. Serializá-los custa memória à toa e o
|
|
28
|
+
* que sobraria no log são mil caracteres de base64, que não dizem nada sobre a chamada.
|
|
29
|
+
*/
|
|
30
|
+
private static readonly REDACTED_FIELDS = ['fileBase64', 'chunkBase64'];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Troca o conteúdo de arquivo por uma marca antes de serializar.
|
|
34
|
+
*
|
|
35
|
+
* Sem isto, `JSON.stringify` de uma chamada com `fileBase64` monta uma string de
|
|
36
|
+
* dezenas de MB só para o `slice(0, 1000)` logo abaixo jogar fora quase tudo — e o
|
|
37
|
+
* pedaço que fica é base64, não a informação que a auditoria quer. Com a troca, o log
|
|
38
|
+
* passa a mostrar os demais argumentos (o id do título, a modalidade escolhida), que é
|
|
39
|
+
* o que permite reconstruir o que foi feito.
|
|
40
|
+
*/
|
|
41
|
+
private redact(input: Record<string, any>): Record<string, any> {
|
|
42
|
+
if (!input || typeof input !== 'object') {
|
|
43
|
+
return input;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const copy: Record<string, any> = { ...input };
|
|
47
|
+
|
|
48
|
+
for (const field of McpAuditService.REDACTED_FIELDS) {
|
|
49
|
+
if (typeof copy[field] === 'string') {
|
|
50
|
+
copy[field] = `<redacted: ${copy[field].length} chars>`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return copy;
|
|
55
|
+
}
|
|
56
|
+
|
|
24
57
|
async record(data: AuditRecord): Promise<void> {
|
|
25
|
-
const sanitized = JSON.stringify(data.input).slice(0, 1000);
|
|
58
|
+
const sanitized = JSON.stringify(this.redact(data.input)).slice(0, 1000);
|
|
26
59
|
try {
|
|
27
60
|
await this.prisma.mcp_tool_call_log.create({
|
|
28
61
|
data: {
|
|
29
62
|
user_id: data.userId || null,
|
|
63
|
+
// Sem isto a auditoria nao distingue uma acao feita pelo Claude
|
|
64
|
+
// Desktop de uma feita pelo Claude Code com chave fixa.
|
|
65
|
+
client_id: data.clientId ?? null,
|
|
30
66
|
tool_name: data.toolName,
|
|
31
67
|
input: sanitized,
|
|
32
68
|
success: data.success,
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, jest } from '@jest/globals';
|
|
2
|
+
import { McpPermissionService } from './mcp-permission.service';
|
|
3
|
+
|
|
4
|
+
const DENIED = ['core.users.assign-role', 'core.settings.set-many'];
|
|
5
|
+
|
|
6
|
+
const makeService = (denied: string[] = DENIED) => {
|
|
7
|
+
const prisma = { route: { findMany: jest.fn<any>() } };
|
|
8
|
+
const setting = {
|
|
9
|
+
getSettingValues: jest.fn<any>().mockResolvedValue({
|
|
10
|
+
'mcp-connector-denied-tools': JSON.stringify(denied),
|
|
11
|
+
}),
|
|
12
|
+
};
|
|
13
|
+
return {
|
|
14
|
+
service: new McpPermissionService(prisma as any, setting as any),
|
|
15
|
+
prisma,
|
|
16
|
+
setting,
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
describe('McpPermissionService', () => {
|
|
21
|
+
// restoreAllMocks, e nao so clearAllMocks: o teste de TTL abaixo troca
|
|
22
|
+
// `Date.now`, e um spy que nao volta vaza para as outras suites do mesmo
|
|
23
|
+
// processo (jest --runInBand) — falha intermitente em teste alheio.
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
jest.clearAllMocks();
|
|
26
|
+
jest.restoreAllMocks();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('devolve as tools concedidas ao usuário', async () => {
|
|
30
|
+
const { service, prisma } = makeService();
|
|
31
|
+
prisma.route.findMany.mockResolvedValue([
|
|
32
|
+
{ tool_name: 'core.users.list' },
|
|
33
|
+
{ tool_name: 'core.system.info' },
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const names = await service.getAllowedToolNames(7);
|
|
37
|
+
|
|
38
|
+
expect(names).toEqual(new Set(['core.users.list', 'core.system.info']));
|
|
39
|
+
expect(prisma.route.findMany).toHaveBeenCalledWith(
|
|
40
|
+
expect.objectContaining({
|
|
41
|
+
where: expect.objectContaining({
|
|
42
|
+
type: 'MCP',
|
|
43
|
+
tool_name: { not: null },
|
|
44
|
+
}),
|
|
45
|
+
}),
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('descarta tool_name nulo vindo do banco', async () => {
|
|
50
|
+
const { service, prisma } = makeService();
|
|
51
|
+
prisma.route.findMany.mockResolvedValue([
|
|
52
|
+
{ tool_name: 'core.system.info' },
|
|
53
|
+
{ tool_name: null },
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
await expect(service.getAllowedToolNames(7)).resolves.toEqual(
|
|
57
|
+
new Set(['core.system.info']),
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Sem a guarda, `user_id: undefined` faz o Prisma descartar o filtro e a
|
|
62
|
+
// consulta devolveria toda rota ligada a qualquer papel.
|
|
63
|
+
it('nega tudo sem usuário, sem consultar o banco', async () => {
|
|
64
|
+
const { service, prisma } = makeService();
|
|
65
|
+
|
|
66
|
+
await expect(service.getAllowedToolNames(undefined as any)).resolves.toEqual(
|
|
67
|
+
new Set(),
|
|
68
|
+
);
|
|
69
|
+
await expect(service.canCall(0, 'core.system.info')).resolves.toBe(false);
|
|
70
|
+
expect(prisma.route.findMany).not.toHaveBeenCalled();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('reusa o cache dentro do TTL e consulta de novo depois que expira', async () => {
|
|
74
|
+
const { service, prisma } = makeService();
|
|
75
|
+
prisma.route.findMany.mockResolvedValue([{ tool_name: 'core.system.info' }]);
|
|
76
|
+
const now = jest.spyOn(Date, 'now').mockReturnValue(1_000);
|
|
77
|
+
|
|
78
|
+
await service.getAllowedToolNames(7);
|
|
79
|
+
await service.getAllowedToolNames(7);
|
|
80
|
+
expect(prisma.route.findMany).toHaveBeenCalledTimes(1);
|
|
81
|
+
|
|
82
|
+
now.mockReturnValue(1_000 + 30_001);
|
|
83
|
+
await service.getAllowedToolNames(7);
|
|
84
|
+
expect(prisma.route.findMany).toHaveBeenCalledTimes(2);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('não vaza o cache de um usuário para outro', async () => {
|
|
88
|
+
const { service, prisma } = makeService();
|
|
89
|
+
prisma.route.findMany
|
|
90
|
+
.mockResolvedValueOnce([{ tool_name: 'core.users.list' }])
|
|
91
|
+
.mockResolvedValueOnce([{ tool_name: 'core.system.info' }]);
|
|
92
|
+
|
|
93
|
+
await expect(service.getAllowedToolNames(7)).resolves.toEqual(
|
|
94
|
+
new Set(['core.users.list']),
|
|
95
|
+
);
|
|
96
|
+
await expect(service.getAllowedToolNames(8)).resolves.toEqual(
|
|
97
|
+
new Set(['core.system.info']),
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('canCall', () => {
|
|
102
|
+
it('autoriza tool concedida e nega a que não está na lista', async () => {
|
|
103
|
+
const { service, prisma } = makeService();
|
|
104
|
+
prisma.route.findMany.mockResolvedValue([
|
|
105
|
+
{ tool_name: 'core.system.info' },
|
|
106
|
+
]);
|
|
107
|
+
|
|
108
|
+
await expect(service.canCall(7, 'core.system.info')).resolves.toBe(true);
|
|
109
|
+
await expect(service.canCall(7, 'core.users.delete')).resolves.toBe(false);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* O teto do conector: um token OAuth externo herda os papeis INTEIROS de quem
|
|
115
|
+
* autorizou, entao para um admin todas as tools ficariam ao alcance de um
|
|
116
|
+
* prompt. O caminho interno (chave hedhog_mcp_, JWT de login) nao e afetado.
|
|
117
|
+
*/
|
|
118
|
+
describe('teto do cliente OAuth externo', () => {
|
|
119
|
+
it('remove as tools negadas quando a chamada vem de um conector', async () => {
|
|
120
|
+
const { service, prisma } = makeService();
|
|
121
|
+
prisma.route.findMany.mockResolvedValue([
|
|
122
|
+
{ tool_name: 'core.users.list' },
|
|
123
|
+
{ tool_name: 'core.users.assign-role' },
|
|
124
|
+
{ tool_name: 'core.settings.set-many' },
|
|
125
|
+
{ tool_name: 'operations.tasks.create' },
|
|
126
|
+
]);
|
|
127
|
+
|
|
128
|
+
const viaConector = await service.getAllowedToolNames(7, true);
|
|
129
|
+
|
|
130
|
+
expect(viaConector.has('core.users.assign-role')).toBe(false);
|
|
131
|
+
expect(viaConector.has('core.settings.set-many')).toBe(false);
|
|
132
|
+
// leitura do mesmo dominio continua liberada
|
|
133
|
+
expect(viaConector.has('core.users.list')).toBe(true);
|
|
134
|
+
expect(viaConector.has('operations.tasks.create')).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('nao remove nada no caminho interno', async () => {
|
|
138
|
+
const { service, prisma } = makeService();
|
|
139
|
+
prisma.route.findMany.mockResolvedValue([
|
|
140
|
+
{ tool_name: 'core.users.assign-role' },
|
|
141
|
+
{ tool_name: 'core.users.list' },
|
|
142
|
+
]);
|
|
143
|
+
|
|
144
|
+
const interno = await service.getAllowedToolNames(7, false);
|
|
145
|
+
|
|
146
|
+
expect(interno.has('core.users.assign-role')).toBe(true);
|
|
147
|
+
expect(interno.has('core.users.list')).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Sem chave composta, o mesmo usuario usando os dois caminhos receberia o
|
|
151
|
+
// conjunto errado — o primeiro que passasse pelo cache venceria.
|
|
152
|
+
it('nao mistura o cache entre conector e caminho interno', async () => {
|
|
153
|
+
const { service, prisma } = makeService();
|
|
154
|
+
prisma.route.findMany.mockResolvedValue([
|
|
155
|
+
{ tool_name: 'core.users.assign-role' },
|
|
156
|
+
]);
|
|
157
|
+
|
|
158
|
+
const viaConector = await service.getAllowedToolNames(7, true);
|
|
159
|
+
const interno = await service.getAllowedToolNames(7, false);
|
|
160
|
+
|
|
161
|
+
expect(viaConector.has('core.users.assign-role')).toBe(false);
|
|
162
|
+
expect(interno.has('core.users.assign-role')).toBe(true);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('canCall respeita a origem', async () => {
|
|
166
|
+
const { service, prisma } = makeService();
|
|
167
|
+
prisma.route.findMany.mockResolvedValue([
|
|
168
|
+
{ tool_name: 'core.users.assign-role' },
|
|
169
|
+
]);
|
|
170
|
+
|
|
171
|
+
await expect(service.canCall(7, 'core.users.assign-role', true)).resolves.toBe(false);
|
|
172
|
+
await expect(service.canCall(7, 'core.users.assign-role', false)).resolves.toBe(true);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Setting apagada por engano nao pode virar permissao.
|
|
176
|
+
it('cai no padrao embutido quando a setting falha ou vem vazia', async () => {
|
|
177
|
+
for (const quebrada of [
|
|
178
|
+
{ getSettingValues: jest.fn<any>().mockRejectedValue(new Error('db down')) },
|
|
179
|
+
{ getSettingValues: jest.fn<any>().mockResolvedValue({ 'mcp-connector-denied-tools': '[]' }) },
|
|
180
|
+
{ getSettingValues: jest.fn<any>().mockResolvedValue({}) },
|
|
181
|
+
]) {
|
|
182
|
+
const prisma = { route: { findMany: jest.fn<any>() } };
|
|
183
|
+
prisma.route.findMany.mockResolvedValue([
|
|
184
|
+
{ tool_name: 'core.users.assign-role' },
|
|
185
|
+
{ tool_name: 'operations.tasks.create' },
|
|
186
|
+
]);
|
|
187
|
+
const service = new McpPermissionService(prisma as any, quebrada as any);
|
|
188
|
+
|
|
189
|
+
const names = await service.getAllowedToolNames(7, true);
|
|
190
|
+
|
|
191
|
+
expect(names.has('core.users.assign-role')).toBe(false);
|
|
192
|
+
expect(names.has('operations.tasks.create')).toBe(true);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
});
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { PrismaService } from '@hed-hog/api-prisma';
|
|
2
|
+
import { forwardRef, Inject, Injectable } from '@nestjs/common';
|
|
3
|
+
import { SettingService } from '../setting/setting.service';
|
|
4
|
+
|
|
5
|
+
type CacheEntry = { expiresAt: number; names: Set<string> };
|
|
6
|
+
|
|
7
|
+
/** Setting com as tools que nenhum cliente OAuth externo pode chamar. */
|
|
8
|
+
const DENIED_TOOLS_SETTING = 'mcp-connector-denied-tools';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Quais tools MCP um usuário pode ver e chamar.
|
|
12
|
+
*
|
|
13
|
+
* Existe como service — e não inline no guard — porque a mesma resposta é usada
|
|
14
|
+
* em dois lugares que precisam concordar: o `tools/list`, que decide o que o
|
|
15
|
+
* cliente enxerga, e o `tools/call`, que decide o que ele executa. Duplicar a
|
|
16
|
+
* consulta é o caminho conhecido para os dois divergirem: tool que aparece na
|
|
17
|
+
* lista e devolve 403, ou — pior — tool que some da lista mas continua
|
|
18
|
+
* chamável.
|
|
19
|
+
*
|
|
20
|
+
* A fonte da verdade é a tabela `route` com `type = 'MCP'`, populada pelos
|
|
21
|
+
* arquivos `route.yaml` das libraries. Tool que existe em código mas não tem
|
|
22
|
+
* rota semeada não é concedida a ninguém.
|
|
23
|
+
*/
|
|
24
|
+
@Injectable()
|
|
25
|
+
export class McpPermissionService {
|
|
26
|
+
/**
|
|
27
|
+
* Curto de propósito: o preço de errar é uma mudança de papel demorar até
|
|
28
|
+
* meio minuto para valer, e o ganho é não repetir a consulta a cada uma das
|
|
29
|
+
* centenas de tools de um `tools/list`. O cache é por processo, e a API roda
|
|
30
|
+
* com várias réplicas — o limite real de propagação é sempre o TTL, nunca a
|
|
31
|
+
* réplica que respondeu.
|
|
32
|
+
*/
|
|
33
|
+
private static readonly CACHE_TTL_MS = 30_000;
|
|
34
|
+
|
|
35
|
+
/** Teto de usuários em cache antes de podar o que já expirou. */
|
|
36
|
+
private static readonly CACHE_MAX_ENTRIES = 500;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Usado quando a setting nao pode ser lida. Escrita no nucleo de seguranca:
|
|
40
|
+
* usuarios, papeis, rotas, telas, settings e revogacao de sessao. Ler esses
|
|
41
|
+
* dominios continua liberado — o que se nega e alterar.
|
|
42
|
+
*/
|
|
43
|
+
private static readonly DEFAULT_DENIED_TOOLS = [
|
|
44
|
+
'core.roles.create', 'core.roles.delete', 'core.roles.menus.update',
|
|
45
|
+
'core.roles.routes.update', 'core.roles.screens.update', 'core.roles.update',
|
|
46
|
+
'core.roles.users.update',
|
|
47
|
+
'core.routes.create', 'core.routes.delete', 'core.routes.roles.update',
|
|
48
|
+
'core.routes.screens.update', 'core.routes.update',
|
|
49
|
+
'core.screens.create', 'core.screens.delete', 'core.screens.roles.update',
|
|
50
|
+
'core.screens.routes.update', 'core.screens.update',
|
|
51
|
+
'core.sessions.revoke', 'core.sessions.revoke-all', 'core.sessions.revoke-all-other',
|
|
52
|
+
'core.settings.delete', 'core.settings.set', 'core.settings.set-many',
|
|
53
|
+
'core.settings.update-from-slug',
|
|
54
|
+
'core.users.assign-role', 'core.users.create', 'core.users.delete',
|
|
55
|
+
'core.users.remove-role', 'core.users.reset-password', 'core.users.update',
|
|
56
|
+
'core.users.verify-identifier',
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
private readonly cache = new Map<string, CacheEntry>();
|
|
60
|
+
|
|
61
|
+
constructor(
|
|
62
|
+
private readonly prisma: PrismaService,
|
|
63
|
+
@Inject(forwardRef(() => SettingService))
|
|
64
|
+
private readonly setting: SettingService,
|
|
65
|
+
) {}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* `viaConnector` marca a chamada como vinda de um cliente OAuth externo.
|
|
69
|
+
*
|
|
70
|
+
* Um token de conector herda os papeis INTEIROS de quem autorizou — para um
|
|
71
|
+
* admin, todas as tools do sistema ao alcance de um prompt. Como o conteudo
|
|
72
|
+
* que o agente le pode vir de fora (um documento, um chamado, um e-mail), o
|
|
73
|
+
* papel sozinho nao e uma fronteira suficiente: e preciso um teto que valha
|
|
74
|
+
* mesmo para quem pode tudo.
|
|
75
|
+
*
|
|
76
|
+
* A negativa NAO se aplica ao caminho interno (chave `hedhog_mcp_`, JWT de
|
|
77
|
+
* login, mcp-chat): ali quem chama e o proprio operador, com a tela na frente.
|
|
78
|
+
*/
|
|
79
|
+
async getAllowedToolNames(
|
|
80
|
+
userId: number,
|
|
81
|
+
viaConnector = false,
|
|
82
|
+
): Promise<Set<string>> {
|
|
83
|
+
// Sem usuário não há concessão. A guarda não é teórica: `user_id: undefined`
|
|
84
|
+
// faz o Prisma *descartar* o filtro, e `role_user: { some: {} }` casaria com
|
|
85
|
+
// qualquer rota ligada a qualquer papel — liberando tudo em vez de nada.
|
|
86
|
+
if (!userId) return new Set();
|
|
87
|
+
|
|
88
|
+
// A chave inclui a origem: o mesmo usuario tem conjuntos diferentes pelo
|
|
89
|
+
// conector e pelo caminho interno, e uma chave so por id serviria o conjunto
|
|
90
|
+
// errado para quem usa os dois.
|
|
91
|
+
const cacheKey = viaConnector ? `c:${userId}` : `i:${userId}`;
|
|
92
|
+
|
|
93
|
+
const cached = this.cache.get(cacheKey);
|
|
94
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
95
|
+
return cached.names;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const rows = await this.prisma.route.findMany({
|
|
99
|
+
where: {
|
|
100
|
+
type: 'MCP' as any,
|
|
101
|
+
tool_name: { not: null },
|
|
102
|
+
role_route: {
|
|
103
|
+
some: {
|
|
104
|
+
role: {
|
|
105
|
+
role_user: {
|
|
106
|
+
some: { user_id: userId },
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
select: { tool_name: true },
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const names = new Set(
|
|
116
|
+
rows
|
|
117
|
+
.map((row) => row.tool_name)
|
|
118
|
+
.filter((name): name is string => Boolean(name)),
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
if (viaConnector) {
|
|
122
|
+
for (const denied of await this.getDeniedTools()) {
|
|
123
|
+
names.delete(denied);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
this.remember(cacheKey, names);
|
|
128
|
+
|
|
129
|
+
return names;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async canCall(
|
|
133
|
+
userId: number,
|
|
134
|
+
toolName: string,
|
|
135
|
+
viaConnector = false,
|
|
136
|
+
): Promise<boolean> {
|
|
137
|
+
const allowed = await this.getAllowedToolNames(userId, viaConnector);
|
|
138
|
+
return allowed.has(toolName);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* A lista vem de setting, e nao de constante, porque a fronteira do que um
|
|
143
|
+
* agente externo pode fazer muda com o uso — e mudar isso nao deve exigir
|
|
144
|
+
* deploy. O `getSettingValues` ja e cacheado por versao, entao ler aqui e
|
|
145
|
+
* barato.
|
|
146
|
+
*
|
|
147
|
+
* Falha de leitura NAO abre a porta: sem conseguir a lista, o servico assume
|
|
148
|
+
* o padrao embutido. Uma setting apagada por engano nao pode virar permissao.
|
|
149
|
+
*/
|
|
150
|
+
private async getDeniedTools(): Promise<string[]> {
|
|
151
|
+
try {
|
|
152
|
+
const values = await this.setting.getSettingValues([DENIED_TOOLS_SETTING]);
|
|
153
|
+
const raw = values[DENIED_TOOLS_SETTING];
|
|
154
|
+
const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
155
|
+
|
|
156
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
157
|
+
return parsed.map((t) => String(t));
|
|
158
|
+
}
|
|
159
|
+
} catch {
|
|
160
|
+
// cai no padrao abaixo
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return McpPermissionService.DEFAULT_DENIED_TOOLS;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private remember(cacheKey: string, names: Set<string>): void {
|
|
167
|
+
if (this.cache.size >= McpPermissionService.CACHE_MAX_ENTRIES) {
|
|
168
|
+
const now = Date.now();
|
|
169
|
+
for (const [key, entry] of this.cache) {
|
|
170
|
+
if (entry.expiresAt <= now) this.cache.delete(key);
|
|
171
|
+
}
|
|
172
|
+
// Todas ainda válidas: o cache inteiro sai. Esvaziar custa uma consulta
|
|
173
|
+
// por usuário ativo; deixar crescer sem teto custa memória para sempre.
|
|
174
|
+
if (this.cache.size >= McpPermissionService.CACHE_MAX_ENTRIES) {
|
|
175
|
+
this.cache.clear();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.cache.set(cacheKey, {
|
|
180
|
+
expiresAt: Date.now() + McpPermissionService.CACHE_TTL_MS,
|
|
181
|
+
names,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -32,11 +32,19 @@ const makeDeps = () => {
|
|
|
32
32
|
const audit = {
|
|
33
33
|
record: jest.fn<any>().mockResolvedValue(undefined),
|
|
34
34
|
};
|
|
35
|
-
|
|
35
|
+
const permissions = {
|
|
36
|
+
getAllowedToolNames: jest.fn<any>().mockResolvedValue(new Set<string>()),
|
|
37
|
+
canCall: jest.fn<any>().mockResolvedValue(true),
|
|
38
|
+
};
|
|
39
|
+
return { registry, audit, permissions };
|
|
36
40
|
};
|
|
37
41
|
|
|
38
42
|
const makeService = (deps = makeDeps()) => ({
|
|
39
|
-
service: new McpServerService(
|
|
43
|
+
service: new McpServerService(
|
|
44
|
+
deps.registry as any,
|
|
45
|
+
deps.audit as any,
|
|
46
|
+
deps.permissions as any,
|
|
47
|
+
),
|
|
40
48
|
deps,
|
|
41
49
|
});
|
|
42
50
|
|
|
@@ -50,14 +58,21 @@ const context: McpContext = {
|
|
|
50
58
|
sessionId: 'sess-1',
|
|
51
59
|
locale: 'pt-BR',
|
|
52
60
|
toolName: '',
|
|
61
|
+
clientId: null,
|
|
53
62
|
};
|
|
54
63
|
|
|
64
|
+
/** Mesmo usuario, mas a chamada vem de um cliente OAuth externo. */
|
|
65
|
+
const connectorContext: McpContext = { ...context, clientId: 'claude-connector' };
|
|
66
|
+
|
|
55
67
|
describe('McpServerService', () => {
|
|
56
68
|
afterEach(() => jest.clearAllMocks());
|
|
57
69
|
|
|
58
70
|
describe('buildServer / ListTools handler', () => {
|
|
59
71
|
it('lista as ferramentas registradas mapeando definition para o schema MCP', async () => {
|
|
60
72
|
const { service, deps } = makeService();
|
|
73
|
+
deps.permissions.getAllowedToolNames.mockResolvedValue(
|
|
74
|
+
new Set(['tool-a', 'tool-b']),
|
|
75
|
+
);
|
|
61
76
|
deps.registry.getAll.mockReturnValue([
|
|
62
77
|
{
|
|
63
78
|
definition: { name: 'tool-a', description: 'desc a', inputSchema: { type: 'object', properties: { x: {} } } },
|
|
@@ -77,6 +92,55 @@ describe('McpServerService', () => {
|
|
|
77
92
|
{ name: 'tool-a', description: 'desc a', inputSchema: { type: 'object', properties: { x: {} } } },
|
|
78
93
|
{ name: 'tool-b', description: 'desc b', inputSchema: { type: 'object', properties: {} } },
|
|
79
94
|
]);
|
|
95
|
+
expect(deps.permissions.getAllowedToolNames).toHaveBeenCalledWith(
|
|
96
|
+
context.userId,
|
|
97
|
+
false,
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('omite da lista as ferramentas que o usuário não pode chamar', async () => {
|
|
102
|
+
const { service, deps } = makeService();
|
|
103
|
+
deps.permissions.getAllowedToolNames.mockResolvedValue(new Set(['tool-a']));
|
|
104
|
+
deps.registry.getAll.mockReturnValue([
|
|
105
|
+
{ definition: { name: 'tool-a', description: 'desc a' }, handler: jest.fn() },
|
|
106
|
+
{ definition: { name: 'tool-b', description: 'desc b' }, handler: jest.fn() },
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
(service as any).buildServer(context);
|
|
110
|
+
const listHandler = getRegisteredHandler(ListToolsRequestSchema);
|
|
111
|
+
const result = await listHandler();
|
|
112
|
+
|
|
113
|
+
expect(result.tools.map((t: any) => t.name)).toEqual(['tool-a']);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('sinaliza a origem para o filtro quando a chamada vem de um conector', async () => {
|
|
117
|
+
const { service, deps } = makeService();
|
|
118
|
+
deps.permissions.getAllowedToolNames.mockResolvedValue(new Set(['tool-a']));
|
|
119
|
+
deps.registry.getAll.mockReturnValue([
|
|
120
|
+
{ definition: { name: 'tool-a', description: 'desc a' }, handler: jest.fn() },
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
(service as any).buildServer(connectorContext);
|
|
124
|
+
const listHandler = getRegisteredHandler(ListToolsRequestSchema);
|
|
125
|
+
await listHandler();
|
|
126
|
+
|
|
127
|
+
expect(deps.permissions.getAllowedToolNames).toHaveBeenCalledWith(
|
|
128
|
+
connectorContext.userId,
|
|
129
|
+
true,
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('devolve lista vazia quando o usuário não tem nenhuma tool concedida', async () => {
|
|
134
|
+
const { service, deps } = makeService();
|
|
135
|
+
deps.permissions.getAllowedToolNames.mockResolvedValue(new Set<string>());
|
|
136
|
+
deps.registry.getAll.mockReturnValue([
|
|
137
|
+
{ definition: { name: 'tool-a', description: 'desc a' }, handler: jest.fn() },
|
|
138
|
+
]);
|
|
139
|
+
|
|
140
|
+
(service as any).buildServer(context);
|
|
141
|
+
const listHandler = getRegisteredHandler(ListToolsRequestSchema);
|
|
142
|
+
|
|
143
|
+
await expect(listHandler()).resolves.toEqual({ tools: [] });
|
|
80
144
|
});
|
|
81
145
|
});
|
|
82
146
|
|
|
@@ -123,6 +187,7 @@ describe('McpServerService', () => {
|
|
|
123
187
|
expect(deps.audit.record).toHaveBeenCalledWith(
|
|
124
188
|
expect.objectContaining({
|
|
125
189
|
userId: context.userId,
|
|
190
|
+
clientId: null,
|
|
126
191
|
toolName: 'tool-a',
|
|
127
192
|
input: { a: 1 },
|
|
128
193
|
success: true,
|
|
@@ -144,6 +209,23 @@ describe('McpServerService', () => {
|
|
|
144
209
|
expect(handler).toHaveBeenCalledWith({}, expect.anything());
|
|
145
210
|
});
|
|
146
211
|
|
|
212
|
+
// A auditoria precisa responder "quem pediu isso": sem o client, uma acao
|
|
213
|
+
// feita pelo Claude Desktop e indistinguivel de uma feita pelo Claude Code.
|
|
214
|
+
it('registra na auditoria o client que originou a chamada', async () => {
|
|
215
|
+
const { service, deps } = makeService();
|
|
216
|
+
const handler = jest.fn<any>().mockResolvedValue({});
|
|
217
|
+
deps.registry.getAll.mockReturnValue([]);
|
|
218
|
+
deps.registry.get.mockReturnValue({ definition: { name: 'tool-a' }, handler });
|
|
219
|
+
|
|
220
|
+
(service as any).buildServer(connectorContext);
|
|
221
|
+
const callHandler = getRegisteredHandler(CallToolRequestSchema);
|
|
222
|
+
await callHandler({ params: { name: 'tool-a', arguments: {} } });
|
|
223
|
+
|
|
224
|
+
expect(deps.audit.record).toHaveBeenCalledWith(
|
|
225
|
+
expect.objectContaining({ clientId: 'claude-connector' }),
|
|
226
|
+
);
|
|
227
|
+
});
|
|
228
|
+
|
|
147
229
|
it('captura exceção do handler, audita success:false com o erro e retorna isError', async () => {
|
|
148
230
|
const { service, deps } = makeService();
|
|
149
231
|
const handler = jest.fn<any>().mockRejectedValue(new Error('boom'));
|