@hed-hog/core 0.0.399 → 0.0.401
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 +6 -4
- package/dist/ai/ai.controller.d.ts.map +1 -1
- package/dist/ai/ai.service.d.ts +121 -6
- package/dist/ai/ai.service.d.ts.map +1 -1
- package/dist/ai/ai.service.js +355 -160
- 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/ai-instruction/ai-prompt-resolver.service.d.ts +12 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.d.ts.map +1 -1
- package/dist/ai-instruction/ai-prompt-resolver.service.js +26 -0
- package/dist/ai-instruction/ai-prompt-resolver.service.js.map +1 -1
- 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 +9 -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/document-kit/document-kit.module.d.ts +3 -0
- package/dist/document-kit/document-kit.module.d.ts.map +1 -0
- package/dist/document-kit/document-kit.module.js +24 -0
- package/dist/document-kit/document-kit.module.js.map +1 -0
- package/dist/document-kit/document-kit.registry.d.ts +55 -0
- package/dist/document-kit/document-kit.registry.d.ts.map +1 -0
- package/dist/document-kit/document-kit.registry.js +91 -0
- package/dist/document-kit/document-kit.registry.js.map +1 -0
- package/dist/document-kit/document-kit.service.d.ts +49 -0
- package/dist/document-kit/document-kit.service.d.ts.map +1 -0
- package/dist/document-kit/document-kit.service.js +135 -0
- package/dist/document-kit/document-kit.service.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 +197 -7
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +438 -78
- 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 +78 -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 +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -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 +28 -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/ai.testers.d.ts.map +1 -1
- package/dist/integration-profile/testers/ai.testers.js +46 -8
- package/dist/integration-profile/testers/ai.testers.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 +7 -1
- package/dist/mcp/mcp.module.js.map +1 -1
- package/dist/mcp/tools/core-access-log.mcp-tools.d.ts +17 -0
- package/dist/mcp/tools/core-access-log.mcp-tools.d.ts.map +1 -0
- package/dist/mcp/tools/core-access-log.mcp-tools.js +74 -0
- package/dist/mcp/tools/core-access-log.mcp-tools.js.map +1 -0
- 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 +187 -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-token-broker.service.d.ts +50 -1
- package/dist/oauth/oauth-token-broker.service.d.ts.map +1 -1
- package/dist/oauth/oauth-token-broker.service.js +105 -3
- package/dist/oauth/oauth-token-broker.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 +6 -0
- package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.js +36 -4
- 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/pdf/document/charts/chart-bar.d.ts +24 -0
- package/dist/pdf/document/charts/chart-bar.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-bar.js +117 -0
- package/dist/pdf/document/charts/chart-bar.js.map +1 -0
- package/dist/pdf/document/charts/chart-donut.d.ts +16 -0
- package/dist/pdf/document/charts/chart-donut.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-donut.js +89 -0
- package/dist/pdf/document/charts/chart-donut.js.map +1 -0
- package/dist/pdf/document/charts/chart-gauge.d.ts +15 -0
- package/dist/pdf/document/charts/chart-gauge.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-gauge.js +60 -0
- package/dist/pdf/document/charts/chart-gauge.js.map +1 -0
- package/dist/pdf/document/charts/chart-line.d.ts +29 -0
- package/dist/pdf/document/charts/chart-line.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-line.js +89 -0
- package/dist/pdf/document/charts/chart-line.js.map +1 -0
- package/dist/pdf/document/charts/chart-primitives.d.ts +64 -0
- package/dist/pdf/document/charts/chart-primitives.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-primitives.js +110 -0
- package/dist/pdf/document/charts/chart-primitives.js.map +1 -0
- package/dist/pdf/document/charts/chart-radar.d.ts +13 -0
- package/dist/pdf/document/charts/chart-radar.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-radar.js +83 -0
- package/dist/pdf/document/charts/chart-radar.js.map +1 -0
- package/dist/pdf/document/charts/chart-scale.d.ts +39 -0
- package/dist/pdf/document/charts/chart-scale.d.ts.map +1 -0
- package/dist/pdf/document/charts/chart-scale.js +118 -0
- package/dist/pdf/document/charts/chart-scale.js.map +1 -0
- package/dist/pdf/document/charts/index.d.ts +8 -0
- package/dist/pdf/document/charts/index.d.ts.map +1 -0
- package/dist/pdf/document/charts/index.js +24 -0
- package/dist/pdf/document/charts/index.js.map +1 -0
- package/dist/pdf/document/index.d.ts +8 -0
- package/dist/pdf/document/index.d.ts.map +1 -0
- package/dist/pdf/document/index.js +24 -0
- package/dist/pdf/document/index.js.map +1 -0
- package/dist/pdf/document/pdf-document.chrome.d.ts +20 -0
- package/dist/pdf/document/pdf-document.chrome.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.chrome.js +36 -0
- package/dist/pdf/document/pdf-document.chrome.js.map +1 -0
- package/dist/pdf/document/pdf-document.css.d.ts +20 -0
- package/dist/pdf/document/pdf-document.css.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.css.js +239 -0
- package/dist/pdf/document/pdf-document.css.js.map +1 -0
- package/dist/pdf/document/pdf-document.renderer.d.ts +10 -0
- package/dist/pdf/document/pdf-document.renderer.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.renderer.js +153 -0
- package/dist/pdf/document/pdf-document.renderer.js.map +1 -0
- package/dist/pdf/document/pdf-document.service.d.ts +27 -0
- package/dist/pdf/document/pdf-document.service.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.service.js +81 -0
- package/dist/pdf/document/pdf-document.service.js.map +1 -0
- package/dist/pdf/document/pdf-document.theme.d.ts +41 -0
- package/dist/pdf/document/pdf-document.theme.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.theme.js +105 -0
- package/dist/pdf/document/pdf-document.theme.js.map +1 -0
- package/dist/pdf/document/pdf-document.types.d.ts +108 -0
- package/dist/pdf/document/pdf-document.types.d.ts.map +1 -0
- package/dist/pdf/document/pdf-document.types.js +18 -0
- package/dist/pdf/document/pdf-document.types.js.map +1 -0
- package/dist/pdf/pdf.module.d.ts.map +1 -1
- package/dist/pdf/pdf.module.js +3 -2
- package/dist/pdf/pdf.module.js.map +1 -1
- package/dist/pdf/pdf.service.d.ts +69 -1
- package/dist/pdf/pdf.service.d.ts.map +1 -1
- package/dist/pdf/pdf.service.js +164 -63
- package/dist/pdf/pdf.service.js.map +1 -1
- package/dist/pdf/templates/commercial-proposal.template.d.ts +96 -0
- package/dist/pdf/templates/commercial-proposal.template.d.ts.map +1 -0
- package/dist/pdf/templates/commercial-proposal.template.js +276 -0
- package/dist/pdf/templates/commercial-proposal.template.js.map +1 -0
- 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/favicon.controller.d.ts +26 -0
- package/dist/setting/favicon.controller.d.ts.map +1 -0
- package/dist/setting/favicon.controller.js +130 -0
- package/dist/setting/favicon.controller.js.map +1 -0
- package/dist/setting/setting.controller.d.ts +5 -0
- package/dist/setting/setting.controller.d.ts.map +1 -1
- package/dist/setting/setting.module.d.ts.map +1 -1
- package/dist/setting/setting.module.js +2 -1
- package/dist/setting/setting.module.js.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 +71 -7
- 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 +12 -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 +148 -0
- package/hedhog/data/setting_group.yaml +189 -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 +237 -37
- package/hedhog/frontend/messages/pt.json +237 -37
- 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 +5 -3
- package/src/ai/ai-agent.sort.ts +21 -0
- package/src/ai/ai-attachment.fragments.spec.ts +56 -3
- package/src/ai/ai.service.responses.spec.ts +429 -0
- package/src/ai/ai.service.spec.ts +173 -1
- package/src/ai/ai.service.ts +473 -220
- package/src/ai-instruction/ai-instruction.service.ts +32 -28
- package/src/ai-instruction/ai-instruction.sort.ts +32 -0
- package/src/ai-instruction/ai-prompt-resolver.service.spec.ts +44 -0
- package/src/ai-instruction/ai-prompt-resolver.service.ts +29 -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 +9 -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/document-kit/document-kit.module.ts +12 -0
- package/src/document-kit/document-kit.registry.ts +125 -0
- package/src/document-kit/document-kit.service.spec.ts +156 -0
- package/src/document-kit/document-kit.service.ts +173 -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 +262 -1
- package/src/file/file.service.ts +505 -87
- 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 +86 -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 +23 -1
- package/src/integration-profile/integration-profile.secrets.ts +28 -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/ai.testers.ts +70 -5
- package/src/integration-profile/testers/index.ts +2 -0
- package/src/integration-profile/testers/remaining.testers.spec.ts +144 -1
- package/src/integration-profile/testers/shipping.testers.ts +94 -0
- package/src/integration-profile/testers/tester-coverage.spec.ts +10 -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 +7 -1
- package/src/mcp/tools/core-access-log.mcp-tools.ts +66 -0
- 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 +201 -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-token-broker.service.spec.ts +108 -0
- package/src/oauth/oauth-token-broker.service.ts +129 -2
- 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.spec.ts +133 -0
- package/src/oauth/providers/microsoft-entra-id.provider.ts +37 -3
- package/src/observability/monitored-cron.spec.ts +164 -31
- package/src/observability/monitored-cron.ts +154 -62
- package/src/pdf/document/charts/chart-bar.ts +217 -0
- package/src/pdf/document/charts/chart-donut.ts +163 -0
- package/src/pdf/document/charts/chart-gauge.ts +94 -0
- package/src/pdf/document/charts/chart-line.ts +159 -0
- package/src/pdf/document/charts/chart-primitives.ts +188 -0
- package/src/pdf/document/charts/chart-radar.ts +136 -0
- package/src/pdf/document/charts/chart-scale.spec.ts +93 -0
- package/src/pdf/document/charts/chart-scale.ts +141 -0
- package/src/pdf/document/charts/charts.spec.ts +157 -0
- package/src/pdf/document/charts/index.ts +7 -0
- package/src/pdf/document/index.ts +7 -0
- package/src/pdf/document/pdf-document.chrome.ts +38 -0
- package/src/pdf/document/pdf-document.css.ts +238 -0
- package/src/pdf/document/pdf-document.renderer.spec.ts +129 -0
- package/src/pdf/document/pdf-document.renderer.ts +215 -0
- package/src/pdf/document/pdf-document.service.ts +77 -0
- package/src/pdf/document/pdf-document.theme.ts +146 -0
- package/src/pdf/document/pdf-document.types.ts +97 -0
- package/src/pdf/pdf.module.ts +3 -2
- package/src/pdf/pdf.service.spec.ts +131 -0
- package/src/pdf/pdf.service.ts +245 -82
- package/src/pdf/templates/commercial-proposal.template.spec.ts +177 -0
- package/src/pdf/templates/commercial-proposal.template.ts +400 -0
- 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/favicon.controller.spec.ts +92 -0
- package/src/setting/favicon.controller.ts +135 -0
- package/src/setting/setting.module.ts +2 -1
- 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 +185 -0
- package/src/whatsapp-sender/whatsapp-sender.service.ts +90 -7
- 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
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
import { Prisma, PrismaService } from '@hed-hog/api-prisma';
|
|
2
|
+
import {
|
|
3
|
+
BadRequestException,
|
|
4
|
+
forwardRef,
|
|
5
|
+
Inject,
|
|
6
|
+
Injectable,
|
|
7
|
+
Logger,
|
|
8
|
+
NotFoundException,
|
|
9
|
+
} from '@nestjs/common';
|
|
10
|
+
import { JwtService } from '@nestjs/jwt';
|
|
11
|
+
import { createHash } from 'crypto';
|
|
12
|
+
import { SettingService } from '../setting/setting.service';
|
|
13
|
+
import { FileService } from './file.service';
|
|
14
|
+
import { findMimetypeConflict, MIMETYPE_SNIFF_BYTES } from './mimetype-sniff.util';
|
|
15
|
+
|
|
16
|
+
/** Tamanho, hash e cabeçalho — o suficiente para validar sem carregar o arquivo. */
|
|
17
|
+
export interface UploadedContentDigest {
|
|
18
|
+
bytes: number;
|
|
19
|
+
sha256: string;
|
|
20
|
+
header: Buffer;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Upload cujo binário não viaja dentro da chamada.
|
|
25
|
+
*
|
|
26
|
+
* O cliente abre um ticket, manda os bytes por fora (um PUT assinado, ou em partes quando
|
|
27
|
+
* não consegue falar HTTP) e só então usa o `fileId` na tool que precisa do arquivo. O
|
|
28
|
+
* ticket é o que amarra esse vaivém a um usuário, a um nome, a um mimetype e a um
|
|
29
|
+
* tamanho declarados — sem ele o endpoint de upload seria uma porta aberta, já que ele
|
|
30
|
+
* responde sem sessão, autenticado apenas pelo token.
|
|
31
|
+
*
|
|
32
|
+
* Por que não uma URL pré-assinada do próprio bucket: nenhum dos cinco providers
|
|
33
|
+
* (`s3`, `spaces`, `gcs`, `abs`, `local`) tem presign de escrita hoje — `getSignedUrl` só
|
|
34
|
+
* aparece com `GetObjectCommand` —, o provider `local` do dev não teria caminho nenhum, e
|
|
35
|
+
* validar o mimetype pelo conteúdo só seria possível depois do objeto já estar no bucket.
|
|
36
|
+
* O PUT assinado da própria API resolve os cinco de uma vez e mantém a validação antes da
|
|
37
|
+
* gravação. Os bytes ainda passam pela API, mas o objetivo era tirá-los da conversa.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
export type UploadTicketMode = 'signed_url' | 'chunked';
|
|
41
|
+
|
|
42
|
+
export interface CreateUploadTicketParams {
|
|
43
|
+
userId: number;
|
|
44
|
+
fileName: string;
|
|
45
|
+
mimeType: string;
|
|
46
|
+
sizeBytes: number;
|
|
47
|
+
destination?: string;
|
|
48
|
+
isPrivate?: boolean;
|
|
49
|
+
sha256?: string;
|
|
50
|
+
idempotencyKey?: string;
|
|
51
|
+
mode: UploadTicketMode;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const DEFAULT_UPLOAD_TTL_SECONDS = 900;
|
|
55
|
+
const DEFAULT_CHUNK_BYTES = 65536;
|
|
56
|
+
/** Onde caem os uploads que ainda não têm dono no domínio (o título, a tarefa, a página). */
|
|
57
|
+
const DEFAULT_DESTINATION = 'mcp/uploads';
|
|
58
|
+
|
|
59
|
+
@Injectable()
|
|
60
|
+
export class FileUploadTicketService {
|
|
61
|
+
private readonly logger = new Logger(FileUploadTicketService.name);
|
|
62
|
+
|
|
63
|
+
constructor(
|
|
64
|
+
private readonly prismaService: PrismaService,
|
|
65
|
+
private readonly jwtService: JwtService,
|
|
66
|
+
@Inject(forwardRef(() => SettingService))
|
|
67
|
+
private readonly settingService: SettingService,
|
|
68
|
+
@Inject(forwardRef(() => FileService))
|
|
69
|
+
private readonly fileService: FileService,
|
|
70
|
+
) {}
|
|
71
|
+
|
|
72
|
+
private async limits() {
|
|
73
|
+
const settings = await this.settingService.getSettingValues([
|
|
74
|
+
'storage-max-size',
|
|
75
|
+
'storage-upload-url-ttl',
|
|
76
|
+
'mcp-upload-chunk-bytes',
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
maxBytes: Number(settings['storage-max-size']) || 10485760,
|
|
81
|
+
ttlSeconds:
|
|
82
|
+
Number(settings['storage-upload-url-ttl']) || DEFAULT_UPLOAD_TTL_SECONDS,
|
|
83
|
+
chunkBytes: Number(settings['mcp-upload-chunk-bytes']) || DEFAULT_CHUNK_BYTES,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Abre o ticket. Repetir a mesma `idempotencyKey` devolve o ticket anterior em vez de
|
|
89
|
+
* abrir outro — o retry de um cliente que não viu a resposta não deve render dois
|
|
90
|
+
* uploads nem dois arquivos.
|
|
91
|
+
*/
|
|
92
|
+
async create(params: CreateUploadTicketParams) {
|
|
93
|
+
const { maxBytes, ttlSeconds, chunkBytes } = await this.limits();
|
|
94
|
+
|
|
95
|
+
if (!params.fileName?.trim()) {
|
|
96
|
+
throw new BadRequestException(`fileName is required`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!params.mimeType?.trim()) {
|
|
100
|
+
throw new BadRequestException(`mimeType is required`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (!Number.isInteger(params.sizeBytes) || params.sizeBytes <= 0) {
|
|
104
|
+
throw new BadRequestException(`sizeBytes must be a positive integer`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (params.sizeBytes > maxBytes) {
|
|
108
|
+
throw new BadRequestException(
|
|
109
|
+
`File too large: ${params.sizeBytes} bytes. The storage-max-size setting allows ${maxBytes}.`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Barra o tipo já na abertura: deixar para o fim faria o cliente subir o arquivo
|
|
114
|
+
// inteiro para só então descobrir que ele nunca seria aceito.
|
|
115
|
+
if (!(await this.fileService.acceptMimetypes(params.mimeType))) {
|
|
116
|
+
throw new BadRequestException(`Invalid file type: ${params.mimeType}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (params.sha256 && !/^[0-9a-f]{64}$/i.test(params.sha256)) {
|
|
120
|
+
throw new BadRequestException(`sha256 must be 64 hexadecimal characters`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (params.idempotencyKey) {
|
|
124
|
+
const existing = await this.prismaService.file_upload_ticket.findFirst({
|
|
125
|
+
where: {
|
|
126
|
+
user_id: params.userId,
|
|
127
|
+
idempotency_key: params.idempotencyKey,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
if (existing) {
|
|
132
|
+
return { ticket: existing, chunkBytes, reused: true };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Tipado como Unchecked de propósito: extrair o literal para uma variável faz o
|
|
137
|
+
// TypeScript perder a união discriminada do Prisma, e `user_id` (escalar, e não a
|
|
138
|
+
// relação `user`) passa a bater na variante Checked, onde ele é `never`.
|
|
139
|
+
const data: Prisma.file_upload_ticketUncheckedCreateInput = {
|
|
140
|
+
user_id: params.userId,
|
|
141
|
+
filename: params.fileName.trim().slice(0, 255),
|
|
142
|
+
mimetype: params.mimeType.trim(),
|
|
143
|
+
size_bytes: params.sizeBytes,
|
|
144
|
+
destination: (params.destination || DEFAULT_DESTINATION).slice(0, 255),
|
|
145
|
+
is_private: params.isPrivate ?? false,
|
|
146
|
+
sha256: params.sha256 ? params.sha256.toLowerCase() : null,
|
|
147
|
+
mode: params.mode,
|
|
148
|
+
status: 'pending' as const,
|
|
149
|
+
idempotency_key: params.idempotencyKey || null,
|
|
150
|
+
expires_at: new Date(Date.now() + ttlSeconds * 1000),
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
const ticket = await this.prismaService.file_upload_ticket.create({ data });
|
|
155
|
+
return { ticket, chunkBytes, reused: false };
|
|
156
|
+
} catch (error: any) {
|
|
157
|
+
// A unicidade de (user_id, idempotency_key) é um índice PARCIAL, e o Prisma não
|
|
158
|
+
// modela índice parcial — ele não aparece no schema e o cliente não o conhece.
|
|
159
|
+
// A garantia continua sendo do Postgres, mas a violação chega aqui como P2002 cru
|
|
160
|
+
// em vez de ser evitada pelo `findFirst` acima, que perde a corrida por milissegundos.
|
|
161
|
+
if (error?.code === 'P2002' && params.idempotencyKey) {
|
|
162
|
+
const existing = await this.prismaService.file_upload_ticket.findFirst({
|
|
163
|
+
where: {
|
|
164
|
+
user_id: params.userId,
|
|
165
|
+
idempotency_key: params.idempotencyKey,
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
if (existing) {
|
|
170
|
+
return { ticket: existing, chunkBytes, reused: true };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Token do PUT assinado. Carrega só o id do ticket: tudo o mais (usuário, tamanho,
|
|
180
|
+
* tipo, validade) é lido da linha, que é a fonte da verdade e pode ser invalidada.
|
|
181
|
+
*/
|
|
182
|
+
signUploadToken(ticketId: number, ttlSeconds: number): string {
|
|
183
|
+
return this.jwtService.sign(
|
|
184
|
+
{ t: 'file-upload', ticketId },
|
|
185
|
+
{
|
|
186
|
+
secret: process.env.JWT_SECRET,
|
|
187
|
+
expiresIn: `${Math.max(1, Math.floor(ttlSeconds))}s`,
|
|
188
|
+
},
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async buildUploadUrl(ticketId: number, req?: any) {
|
|
193
|
+
const { ttlSeconds } = await this.limits();
|
|
194
|
+
const token = this.signUploadToken(ticketId, ttlSeconds);
|
|
195
|
+
const origin = await this.fileService.resolvePublicBaseUrl(
|
|
196
|
+
req ?? ({ protocol: 'https', get: () => '' } as any),
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
return `${origin}/file/upload/${encodeURIComponent(token)}`;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Lê o ticket do token, sem consumi-lo. */
|
|
203
|
+
async resolveTicketFromToken(token: string) {
|
|
204
|
+
let payload: any;
|
|
205
|
+
|
|
206
|
+
try {
|
|
207
|
+
payload = this.jwtService.verify(token, { secret: process.env.JWT_SECRET });
|
|
208
|
+
} catch {
|
|
209
|
+
throw new BadRequestException(`Invalid or expired upload token`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (payload?.t !== 'file-upload' || !payload?.ticketId) {
|
|
213
|
+
throw new BadRequestException(`Token is not an upload token`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const ticket = await this.prismaService.file_upload_ticket.findUnique({
|
|
217
|
+
where: { id: Number(payload.ticketId) },
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
if (!ticket) {
|
|
221
|
+
throw new NotFoundException(`Upload ticket not found`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return ticket;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Marca o ticket como consumido, e só devolve `true` para quem venceu a corrida.
|
|
229
|
+
*
|
|
230
|
+
* O `updateMany` condicional é o que dá uso único sem abrir transação: dois PUTs
|
|
231
|
+
* simultâneos com o mesmo token entram aqui juntos, o Postgres serializa o UPDATE e o
|
|
232
|
+
* segundo enxerga `count: 0` porque o status já não é `pending`.
|
|
233
|
+
*/
|
|
234
|
+
async claim(ticketId: number): Promise<boolean> {
|
|
235
|
+
const claimed = await this.prismaService.file_upload_ticket.updateMany({
|
|
236
|
+
where: {
|
|
237
|
+
id: ticketId,
|
|
238
|
+
status: 'pending',
|
|
239
|
+
expires_at: { gt: new Date() },
|
|
240
|
+
},
|
|
241
|
+
data: { status: 'completed', consumed_at: new Date() },
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
return claimed.count === 1;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async markFailed(ticketId: number) {
|
|
248
|
+
await this.prismaService.file_upload_ticket
|
|
249
|
+
.update({ where: { id: ticketId }, data: { status: 'failed' } })
|
|
250
|
+
.catch((error: any) =>
|
|
251
|
+
this.logger.warn(`Failed to mark upload ticket ${ticketId}: ${error.message}`),
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async attachFile(ticketId: number, fileId: number) {
|
|
256
|
+
await this.prismaService.file_upload_ticket.update({
|
|
257
|
+
where: { id: ticketId },
|
|
258
|
+
data: { file_id: fileId },
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* O que basta saber sobre o conteúdo para conferi-lo contra o ticket.
|
|
264
|
+
*
|
|
265
|
+
* Separado do buffer de propósito: o PUT assinado escreve direto no disco e nunca tem o
|
|
266
|
+
* arquivo inteiro em memória, então ele produz estes três valores durante o stream. O
|
|
267
|
+
* modo em partes, que monta o buffer de qualquer forma, deriva os mesmos com
|
|
268
|
+
* `describeUploadedBuffer`.
|
|
269
|
+
*/
|
|
270
|
+
static describeUploadedBuffer(buffer: Buffer): UploadedContentDigest {
|
|
271
|
+
return {
|
|
272
|
+
bytes: buffer.length,
|
|
273
|
+
sha256: createHash('sha256').update(buffer).digest('hex'),
|
|
274
|
+
header: buffer.subarray(0, MIMETYPE_SNIFF_BYTES),
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Confere tamanho, integridade e o tipo real contra o declarado.
|
|
280
|
+
*
|
|
281
|
+
* Roda para os dois modos, no ponto em que os bytes já existem por inteiro — é aqui que
|
|
282
|
+
* um `.exe` declarado como `application/pdf` é recusado, coisa que a validação por
|
|
283
|
+
* header nunca pegaria, e que o `storage-accept-mimetype` sozinho também não pega
|
|
284
|
+
* porque ele só olha a string que o cliente mandou.
|
|
285
|
+
*/
|
|
286
|
+
async assertContentMatchesTicket(ticket: any, digest: UploadedContentDigest) {
|
|
287
|
+
const { maxBytes } = await this.limits();
|
|
288
|
+
|
|
289
|
+
if (digest.bytes === 0) {
|
|
290
|
+
throw new BadRequestException(`Uploaded content is empty`);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (digest.bytes > maxBytes) {
|
|
294
|
+
throw new BadRequestException(
|
|
295
|
+
`File too large: ${digest.bytes} bytes. The storage-max-size setting allows ${maxBytes}.`,
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (digest.bytes !== ticket.size_bytes) {
|
|
300
|
+
throw new BadRequestException(
|
|
301
|
+
`Uploaded ${digest.bytes} bytes but the ticket declared ${ticket.size_bytes}`,
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (ticket.sha256 && digest.sha256 !== ticket.sha256) {
|
|
306
|
+
throw new BadRequestException(
|
|
307
|
+
`sha256 mismatch: declared ${ticket.sha256}, uploaded content hashes to ${digest.sha256}`,
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const conflict = findMimetypeConflict(ticket.mimetype, digest.header);
|
|
312
|
+
|
|
313
|
+
if (conflict) {
|
|
314
|
+
throw new BadRequestException(
|
|
315
|
+
`Declared mimeType ${ticket.mimetype} but the content is ${conflict}`,
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// ── Modo em partes ─────────────────────────────────────────────────────────
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Grava uma parte. Reenviar o mesmo índice sobrescreve, para que o retry de uma parte
|
|
324
|
+
* perdida não duplique nem desalinhe a montagem.
|
|
325
|
+
*/
|
|
326
|
+
async appendChunk(
|
|
327
|
+
uploadId: number,
|
|
328
|
+
index: number,
|
|
329
|
+
chunkBase64: string,
|
|
330
|
+
userId: number,
|
|
331
|
+
) {
|
|
332
|
+
const ticket = await this.requireOwnPendingTicket(uploadId, userId);
|
|
333
|
+
|
|
334
|
+
if (ticket.mode !== 'chunked') {
|
|
335
|
+
throw new BadRequestException(
|
|
336
|
+
`Upload ${uploadId} was opened for direct upload; use the signed URL instead of append`,
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (!Number.isInteger(index) || index < 0) {
|
|
341
|
+
throw new BadRequestException(`index must be a non-negative integer`);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (!chunkBase64) {
|
|
345
|
+
throw new BadRequestException(`chunkBase64 is required`);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const { chunkBytes } = await this.limits();
|
|
349
|
+
const data = Buffer.from(chunkBase64, 'base64');
|
|
350
|
+
|
|
351
|
+
if (data.length === 0) {
|
|
352
|
+
throw new BadRequestException(`chunkBase64 decoded to zero bytes`);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (data.length > chunkBytes) {
|
|
356
|
+
throw new BadRequestException(
|
|
357
|
+
`Chunk ${index} has ${data.length} bytes, above the ${chunkBytes} allowed by the mcp-upload-chunk-bytes setting`,
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
await this.prismaService.file_upload_chunk.upsert({
|
|
362
|
+
where: { ticket_id_index: { ticket_id: uploadId, index } },
|
|
363
|
+
create: { ticket_id: uploadId, index, data },
|
|
364
|
+
update: { data },
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
const received = await this.prismaService.file_upload_chunk.count({
|
|
368
|
+
where: { ticket_id: uploadId },
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
const expected = Math.ceil(ticket.size_bytes / chunkBytes);
|
|
372
|
+
|
|
373
|
+
return {
|
|
374
|
+
uploadId,
|
|
375
|
+
index,
|
|
376
|
+
received,
|
|
377
|
+
expected,
|
|
378
|
+
remaining: Math.max(0, expected - received),
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
private async requireOwnPendingTicket(uploadId: number, userId: number) {
|
|
383
|
+
const ticket = await this.prismaService.file_upload_ticket.findUnique({
|
|
384
|
+
where: { id: uploadId },
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
if (!ticket) {
|
|
388
|
+
throw new NotFoundException(`Upload ticket not found: ${uploadId}`);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// O ticket é do usuário que o abriu, sem exceção para admin: ele não é um recurso
|
|
392
|
+
// administrável, é um passo intermediário de quem está subindo o arquivo.
|
|
393
|
+
if (ticket.user_id !== userId) {
|
|
394
|
+
throw new NotFoundException(`Upload ticket not found: ${uploadId}`);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (ticket.status !== 'pending') {
|
|
398
|
+
throw new BadRequestException(
|
|
399
|
+
`Upload ticket ${uploadId} is ${ticket.status} and cannot receive more content`,
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (ticket.expires_at.getTime() <= Date.now()) {
|
|
404
|
+
throw new BadRequestException(`Upload ticket ${uploadId} has expired`);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return ticket;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Fecha o upload e devolve o arquivo.
|
|
412
|
+
*
|
|
413
|
+
* Serve aos dois modos e é idempotente: um ticket que já gerou arquivo devolve o mesmo
|
|
414
|
+
* `fileId` em vez de erro, porque o retry de um `complete` cuja resposta se perdeu não
|
|
415
|
+
* pode render um segundo arquivo.
|
|
416
|
+
*/
|
|
417
|
+
async complete(uploadId: number, userId: number) {
|
|
418
|
+
const ticket = await this.prismaService.file_upload_ticket.findUnique({
|
|
419
|
+
where: { id: uploadId },
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
if (!ticket || ticket.user_id !== userId) {
|
|
423
|
+
throw new NotFoundException(`Upload ticket not found: ${uploadId}`);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (ticket.file_id) {
|
|
427
|
+
return this.fileService.get(ticket.file_id);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (ticket.mode === 'signed_url') {
|
|
431
|
+
throw new BadRequestException(
|
|
432
|
+
ticket.status === 'pending'
|
|
433
|
+
? `Upload ticket ${uploadId} has no content yet; PUT the file to the signed URL first`
|
|
434
|
+
: `Upload ticket ${uploadId} is ${ticket.status} and produced no file`,
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
await this.requireOwnPendingTicket(uploadId, userId);
|
|
439
|
+
|
|
440
|
+
// Reivindica antes de montar: dois `complete` simultâneos entrariam os dois no
|
|
441
|
+
// `uploadFromPath` e gerariam dois arquivos para o mesmo ticket.
|
|
442
|
+
if (!(await this.claim(uploadId))) {
|
|
443
|
+
const current = await this.prismaService.file_upload_ticket.findUnique({
|
|
444
|
+
where: { id: uploadId },
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
if (current?.file_id) {
|
|
448
|
+
return this.fileService.get(current.file_id);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
throw new BadRequestException(`Upload ticket ${uploadId} is already being completed`);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
try {
|
|
455
|
+
const chunks = await this.prismaService.file_upload_chunk.findMany({
|
|
456
|
+
where: { ticket_id: uploadId },
|
|
457
|
+
orderBy: { index: 'asc' },
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
if (chunks.length === 0) {
|
|
461
|
+
throw new BadRequestException(`Upload ticket ${uploadId} has no chunks`);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// Índice faltando significa parte perdida no caminho; montar assim geraria um
|
|
465
|
+
// arquivo silenciosamente corrompido, que é pior do que recusar.
|
|
466
|
+
chunks.forEach((chunk, position) => {
|
|
467
|
+
if (chunk.index !== position) {
|
|
468
|
+
throw new BadRequestException(
|
|
469
|
+
`Upload ticket ${uploadId} is missing chunk ${position}`,
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
const buffer = Buffer.concat(chunks.map((chunk) => Buffer.from(chunk.data)));
|
|
475
|
+
|
|
476
|
+
await this.assertContentMatchesTicket(
|
|
477
|
+
ticket,
|
|
478
|
+
FileUploadTicketService.describeUploadedBuffer(buffer),
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
const file = await this.fileService.upload(
|
|
482
|
+
ticket.destination,
|
|
483
|
+
{
|
|
484
|
+
fieldname: 'file',
|
|
485
|
+
originalname: ticket.filename,
|
|
486
|
+
encoding: '7bit',
|
|
487
|
+
mimetype: ticket.mimetype,
|
|
488
|
+
size: buffer.length,
|
|
489
|
+
destination: '',
|
|
490
|
+
filename: ticket.filename,
|
|
491
|
+
path: '',
|
|
492
|
+
buffer,
|
|
493
|
+
},
|
|
494
|
+
undefined,
|
|
495
|
+
{
|
|
496
|
+
isPrivate: ticket.is_private,
|
|
497
|
+
createdByUserId: ticket.user_id,
|
|
498
|
+
},
|
|
499
|
+
);
|
|
500
|
+
|
|
501
|
+
await this.attachFile(uploadId, file.id);
|
|
502
|
+
// As partes já cumpriram o papel e somam o arquivo inteiro no banco.
|
|
503
|
+
await this.prismaService.file_upload_chunk.deleteMany({
|
|
504
|
+
where: { ticket_id: uploadId },
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
return file;
|
|
508
|
+
} catch (error) {
|
|
509
|
+
await this.markFailed(uploadId);
|
|
510
|
+
throw error;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
@@ -31,6 +31,7 @@ import { join } from 'path';
|
|
|
31
31
|
import { DeleteDTO } from './dto/delete.dto';
|
|
32
32
|
import { UploadFileDTO } from './dto/upload.dto';
|
|
33
33
|
import { FileService } from './file.service';
|
|
34
|
+
import { FileUploadTicketService } from './file-upload-ticket.service';
|
|
34
35
|
|
|
35
36
|
// Teto duro do multipart, avaliado enquanto o corpo ainda está chegando. É
|
|
36
37
|
// diferente do setting `storage-max-size`, que só roda depois do arquivo inteiro
|
|
@@ -46,6 +47,8 @@ export class FileController {
|
|
|
46
47
|
constructor(
|
|
47
48
|
@Inject(forwardRef(() => FileService))
|
|
48
49
|
private readonly fileService: FileService,
|
|
50
|
+
@Inject(forwardRef(() => FileUploadTicketService))
|
|
51
|
+
private readonly uploadTickets: FileUploadTicketService,
|
|
49
52
|
) {}
|
|
50
53
|
|
|
51
54
|
private renderDownloadErrorHtml(locale: string, error: any): string {
|
|
@@ -123,6 +126,68 @@ export class FileController {
|
|
|
123
126
|
};
|
|
124
127
|
}
|
|
125
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Recebe o binário de um upload aberto por `core.files.create-upload-url`.
|
|
131
|
+
*
|
|
132
|
+
* É `@Public()` porque a autorização é o próprio token: ele é assinado, vale por
|
|
133
|
+
* minutos, aponta para um único ticket e só serve uma vez. Existe para tirar o arquivo
|
|
134
|
+
* do corpo da chamada MCP — base64 de um PDF de 131 KB já passa de 175 mil caracteres,
|
|
135
|
+
* acima do que o modelo consegue emitir.
|
|
136
|
+
*
|
|
137
|
+
* O corpo é o binário cru, sem multipart: `express.json` não o toca porque o
|
|
138
|
+
* content-type não é JSON, e o stream vai direto para um arquivo temporário com
|
|
139
|
+
* contador de bytes, que é o que impede um corpo sem `Content-Length` de encher a
|
|
140
|
+
* memória do pod.
|
|
141
|
+
*/
|
|
142
|
+
@Public()
|
|
143
|
+
@Put('upload/:token')
|
|
144
|
+
async uploadSigned(@Param('token') token: string, @Req() req: Request) {
|
|
145
|
+
const ticket = await this.uploadTickets.resolveTicketFromToken(token);
|
|
146
|
+
|
|
147
|
+
// Reivindica ANTES de gravar: dois PUTs simultâneos com o mesmo token subiriam os
|
|
148
|
+
// dois e deixariam um blob órfão no storage, além de dois registros para um ticket.
|
|
149
|
+
if (!(await this.uploadTickets.claim(ticket.id))) {
|
|
150
|
+
throw new BadRequestException(
|
|
151
|
+
`Upload token already used or expired for ticket ${ticket.id}`,
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const tempPath = join(tmpdir(), `hedhog-upload-${ticket.id}-${Date.now()}`);
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
// Uma passada só: grava, conta, hasheia e guarda o cabeçalho para o sniff.
|
|
159
|
+
const digest = await this.fileService.writeStreamToPath(
|
|
160
|
+
req as any,
|
|
161
|
+
tempPath,
|
|
162
|
+
ticket.size_bytes,
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
await this.uploadTickets.assertContentMatchesTicket(ticket, digest);
|
|
166
|
+
|
|
167
|
+
const file = await this.fileService.uploadFromPath(ticket.destination, tempPath, {
|
|
168
|
+
originalname: ticket.filename,
|
|
169
|
+
mimetype: ticket.mimetype,
|
|
170
|
+
size: digest.bytes,
|
|
171
|
+
isPrivate: ticket.is_private,
|
|
172
|
+
createdByUserId: ticket.user_id,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
await this.uploadTickets.attachFile(ticket.id, file.id);
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
uploadId: ticket.id,
|
|
179
|
+
fileId: file.id,
|
|
180
|
+
filename: file.filename,
|
|
181
|
+
size: file.size,
|
|
182
|
+
};
|
|
183
|
+
} catch (error) {
|
|
184
|
+
await this.uploadTickets.markFailed(ticket.id);
|
|
185
|
+
throw error;
|
|
186
|
+
} finally {
|
|
187
|
+
await rm(tempPath, { force: true }).catch(() => undefined);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
126
191
|
@Public()
|
|
127
192
|
@Get('download/:token')
|
|
128
193
|
async download(
|
package/src/file/file.module.ts
CHANGED
|
@@ -5,7 +5,9 @@ import { JwtModule } from '@nestjs/jwt';
|
|
|
5
5
|
import { SettingModule } from '../setting/setting.module';
|
|
6
6
|
import { FileController } from './file.controller';
|
|
7
7
|
import { FileService } from './file.service';
|
|
8
|
+
import { FileUploadTicketService } from './file-upload-ticket.service';
|
|
8
9
|
import { ImageOptimizationService } from './image-optimization.service';
|
|
10
|
+
import { McpFileSourceService } from './mcp-file-source.service';
|
|
9
11
|
|
|
10
12
|
@Module({
|
|
11
13
|
imports: [
|
|
@@ -16,8 +18,18 @@ import { ImageOptimizationService } from './image-optimization.service';
|
|
|
16
18
|
JwtModule,
|
|
17
19
|
),
|
|
18
20
|
],
|
|
19
|
-
providers: [
|
|
20
|
-
|
|
21
|
+
providers: [
|
|
22
|
+
FileService,
|
|
23
|
+
ImageOptimizationService,
|
|
24
|
+
FileUploadTicketService,
|
|
25
|
+
McpFileSourceService,
|
|
26
|
+
],
|
|
27
|
+
exports: [
|
|
28
|
+
FileService,
|
|
29
|
+
ImageOptimizationService,
|
|
30
|
+
FileUploadTicketService,
|
|
31
|
+
McpFileSourceService,
|
|
32
|
+
],
|
|
21
33
|
controllers: [FileController],
|
|
22
34
|
})
|
|
23
35
|
export class FileModule { }
|