@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
|
@@ -24,6 +24,36 @@ type GeoIpResult = {
|
|
|
24
24
|
export class SessionService {
|
|
25
25
|
private readonly logger = new Logger(SessionService.name);
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Janela em que o refresh token ANTERIOR continua sendo aceito depois de uma
|
|
29
|
+
* rotacao.
|
|
30
|
+
*
|
|
31
|
+
* Sem ela a rotacao e um handoff sem tolerancia: se a resposta do
|
|
32
|
+
* `/auth/refresh` se perde no caminho de volta — rede caindo, aba suspensa,
|
|
33
|
+
* pod reciclado no meio de um rollout — o servidor ja girou e o cliente fica
|
|
34
|
+
* com um token que nao vale mais. Uma sessao valida de 30 dias morre por um
|
|
35
|
+
* soluco de rede, e o unico rastro e um 401 solto. A janela tambem absorve
|
|
36
|
+
* duas abas renovando ao mesmo tempo.
|
|
37
|
+
*
|
|
38
|
+
* Curta de proposito: ela existe para cobrir a corrida e a resposta perdida,
|
|
39
|
+
* nao para prolongar a vida do token.
|
|
40
|
+
*/
|
|
41
|
+
private static readonly REFRESH_GRACE_MS = 30_000;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Sessao aberta por um cliente OAuth externo vive menos que a de login: o
|
|
45
|
+
* refresh token esta com um terceiro. Vale na criacao E na renovacao — sem
|
|
46
|
+
* reaplicar aqui, a primeira renovacao devolvia a sessao aos 30 dias globais e
|
|
47
|
+
* o limite virava decoracao.
|
|
48
|
+
*/
|
|
49
|
+
static readonly CONNECTOR_SESSION_TTL_MINUTES = 7 * 24 * 60;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Tentativas de rotacao por chamada. A segunda cobre o caso de outra
|
|
53
|
+
* requisicao ter girado a sessao entre a leitura e o compare-and-swap.
|
|
54
|
+
*/
|
|
55
|
+
private static readonly REFRESH_ROTATION_ATTEMPTS = 2;
|
|
56
|
+
|
|
27
57
|
constructor(
|
|
28
58
|
private prisma: PrismaService,
|
|
29
59
|
@Inject(forwardRef(() => SecurityService))
|
|
@@ -40,7 +70,19 @@ export class SessionService {
|
|
|
40
70
|
private readonly paginationService: PaginationService,
|
|
41
71
|
) { }
|
|
42
72
|
|
|
43
|
-
|
|
73
|
+
/**
|
|
74
|
+
* `oauth` marca a sessao como pertencente a um cliente OAuth externo. Vem
|
|
75
|
+
* preenchido so pela troca do authorization code quando o cliente pediu um
|
|
76
|
+
* `resource`; o login normal continua chamando sem ele e nada muda.
|
|
77
|
+
*/
|
|
78
|
+
async create(
|
|
79
|
+
locale: string,
|
|
80
|
+
userId: number,
|
|
81
|
+
ipAddress: string,
|
|
82
|
+
userAgent: string,
|
|
83
|
+
browserId?: string | null,
|
|
84
|
+
oauth?: { audience: string; clientId: string; ttlMinutes?: number },
|
|
85
|
+
) {
|
|
44
86
|
if (!userId) {
|
|
45
87
|
throw new BadRequestException(getLocaleText('session.userIdRequired', locale, 'User ID is required to create a session.'));
|
|
46
88
|
}
|
|
@@ -61,18 +103,34 @@ export class SessionService {
|
|
|
61
103
|
const hash = this.security.hashWithPepper(token)
|
|
62
104
|
const maxSessions = Number(settings['max-concurrent-sessions']) || 0;
|
|
63
105
|
|
|
64
|
-
|
|
106
|
+
// E pela mesma razao a sessao de conector nao DISPARA o despejo ao nascer.
|
|
107
|
+
// `createImpersonation` ja se isenta assim; aqui o efeito seria o usuario
|
|
108
|
+
// perder o celular por ter autorizado um app.
|
|
109
|
+
if (maxSessions > 0 && !oauth) {
|
|
65
110
|
await this.enforceSessionLimit(userId, maxSessions, false, browserId);
|
|
66
111
|
}
|
|
67
112
|
|
|
113
|
+
// Sessao de conector vive menos que a de login. Nao e simetria estetica: o
|
|
114
|
+
// refresh token esta com um terceiro, e 30 dias de janela para um segredo que
|
|
115
|
+
// saiu do nosso dominio e generoso demais.
|
|
116
|
+
//
|
|
117
|
+
// `||` e nao `??` em toda a cadeia: `Number(undefined)` e NaN, que passa
|
|
118
|
+
// direto por `??` e produziria um expires_at invalido.
|
|
119
|
+
const ttlMinutes =
|
|
120
|
+
oauth?.ttlMinutes ||
|
|
121
|
+
Number(settings['refresh-token-expiration-minutes']) ||
|
|
122
|
+
43200;
|
|
123
|
+
|
|
68
124
|
const session = await this.prisma.user_session.create({
|
|
69
125
|
data: {
|
|
70
126
|
user_id: userId,
|
|
71
127
|
ip_address: ipAddress,
|
|
72
128
|
user_agent: userAgent,
|
|
73
|
-
expires_at: new Date(Date.now() +
|
|
129
|
+
expires_at: new Date(Date.now() + ttlMinutes * 60 * 1000),
|
|
74
130
|
hash,
|
|
75
131
|
browser_id: browserId ?? null,
|
|
132
|
+
audience: oauth?.audience ?? null,
|
|
133
|
+
oauth_client_id: oauth?.clientId ?? null,
|
|
76
134
|
},
|
|
77
135
|
});
|
|
78
136
|
|
|
@@ -150,104 +208,221 @@ export class SessionService {
|
|
|
150
208
|
}));
|
|
151
209
|
}
|
|
152
210
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
211
|
+
/**
|
|
212
|
+
* Anexa `oauth_client: { client_id, name }` as sessoes abertas por um cliente
|
|
213
|
+
* OAuth externo. Mesmo padrao de `attachImpersonators`, e pela mesma razao:
|
|
214
|
+
* `oauth_client_id` e VARCHAR puro, sem FK.
|
|
215
|
+
*
|
|
216
|
+
* Existe porque sem o nome a tela de seguranca do usuario fica ILEGIVEL para
|
|
217
|
+
* esse caso: um conector fala com a API a partir da nuvem do fornecedor, entao
|
|
218
|
+
* a linha aparece com user agent que o ua-parser nao reconhece
|
|
219
|
+
* (`python-httpx/0.28.1`), sem dispositivo, e geolocalizada no pais dele. Para
|
|
220
|
+
* quem esta no Brasil, e indistinguivel de uma conta invadida.
|
|
221
|
+
*/
|
|
222
|
+
private async attachOAuthClients<T extends { oauth_client_id?: string | null }>(rows: T[]) {
|
|
223
|
+
const ids = Array.from(
|
|
224
|
+
new Set(
|
|
225
|
+
rows
|
|
226
|
+
.map((row) => row.oauth_client_id)
|
|
227
|
+
.filter((id): id is string => typeof id === 'string' && id.length > 0),
|
|
228
|
+
),
|
|
229
|
+
);
|
|
164
230
|
|
|
165
|
-
if (!
|
|
166
|
-
|
|
167
|
-
throw new UnauthorizedException(getLocaleText('accessDenied', locale, 'Access denied.'));
|
|
231
|
+
if (!ids.length) {
|
|
232
|
+
return rows.map((row) => ({ ...row, oauth_client: null }));
|
|
168
233
|
}
|
|
169
234
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
235
|
+
const clients = await this.prisma.oauth_app_client.findMany({
|
|
236
|
+
where: { client_id: { in: ids } },
|
|
237
|
+
select: { client_id: true, name: true },
|
|
238
|
+
});
|
|
239
|
+
const byId = new Map(clients.map((client) => [client.client_id, client]));
|
|
174
240
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
241
|
+
return rows.map((row) => ({
|
|
242
|
+
...row,
|
|
243
|
+
oauth_client: row.oauth_client_id
|
|
244
|
+
? // Client removido do registro ainda tem sessao viva: cai no proprio
|
|
245
|
+
// slug, que e melhor que sumir com a informacao.
|
|
246
|
+
(byId.get(row.oauth_client_id) ?? {
|
|
247
|
+
client_id: row.oauth_client_id,
|
|
248
|
+
name: row.oauth_client_id,
|
|
249
|
+
})
|
|
250
|
+
: null,
|
|
251
|
+
}));
|
|
252
|
+
}
|
|
179
253
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
254
|
+
/**
|
|
255
|
+
* Gira o refresh token PRESERVANDO a identidade da sessao.
|
|
256
|
+
*
|
|
257
|
+
* A versao anterior revogava a linha e criava outra, com `id` novo. Como
|
|
258
|
+
* `TokenService.verify` valida a sessao no banco a cada request e recusa
|
|
259
|
+
* qualquer access token cuja sessao esteja revogada, o instante do refresh
|
|
260
|
+
* matava todos os access tokens em voo — na hora, e nao no `exp`. Numa tela
|
|
261
|
+
* que dispara ~10 chamadas em paralelo isso virava reacao em cadeia: cada 401
|
|
262
|
+
* disparava outro refresh, cada refresh matava os tokens dos outros. Nos logs
|
|
263
|
+
* de producao de 24/08 foram doze sessoes giradas em 18 segundos para o mesmo
|
|
264
|
+
* usuario, terminando em `Refresh rejected` e logout.
|
|
265
|
+
*
|
|
266
|
+
* Com o `id` estavel, o access token que ja saiu continua valido ate o proprio
|
|
267
|
+
* `exp`, e a rotacao deixa de ser um evento observavel pelo resto do app. De
|
|
268
|
+
* quebra a tabela para de crescer uma linha a cada 15 minutos por dispositivo.
|
|
269
|
+
*/
|
|
270
|
+
async refresh(locale: string, refreshToken: string, ipAddress: string, userAgent: string, browserId?: string | null) {
|
|
271
|
+
if (!refreshToken) {
|
|
186
272
|
throw new UnauthorizedException(getLocaleText('accessDenied', locale, 'Access denied.'));
|
|
187
273
|
}
|
|
188
274
|
|
|
189
|
-
const
|
|
190
|
-
id: rawSession.id,
|
|
191
|
-
user_id: rawSession.user_id,
|
|
192
|
-
ip_address: rawSession.ip_address,
|
|
193
|
-
user_agent: rawSession.user_agent,
|
|
194
|
-
browser_id: rawSession.browser_id,
|
|
195
|
-
};
|
|
275
|
+
const hash = this.security.hashWithPepper(refreshToken);
|
|
196
276
|
|
|
197
277
|
const settings = await this.setting.getSettingValues([
|
|
198
278
|
'refresh-token-expiration-minutes',
|
|
199
279
|
'max-concurrent-sessions',
|
|
200
280
|
]);
|
|
201
|
-
|
|
202
281
|
const maxSessions = Number(settings['max-concurrent-sessions']) || 0;
|
|
203
|
-
|
|
204
|
-
await this.enforceSessionLimit(session.user_id, maxSessions, true, browserId);
|
|
205
|
-
}
|
|
282
|
+
const ttlMinutes = Number(settings['refresh-token-expiration-minutes']) || 43200;
|
|
206
283
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
284
|
+
for (let attempt = 1; attempt <= SessionService.REFRESH_ROTATION_ATTEMPTS; attempt++) {
|
|
285
|
+
const rawSession = await this.prisma.user_session.findFirst({
|
|
286
|
+
where: this.refreshTokenWhere(hash),
|
|
287
|
+
select: { id: true, user_id: true, ip_address: true, user_agent: true, revoked_at: true, expires_at: true, browser_id: true, impersonator_user_id: true, hash: true, audience: true, oauth_client_id: true },
|
|
288
|
+
});
|
|
212
289
|
|
|
213
|
-
|
|
214
|
-
|
|
290
|
+
if (!rawSession) {
|
|
291
|
+
this.logger.warn(`[SessionRefresh] Refresh rejected: hash prefix ${hash.slice(0, 8)} not found in DB`);
|
|
292
|
+
throw new UnauthorizedException(getLocaleText('accessDenied', locale, 'Access denied.'));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (rawSession.revoked_at !== null) {
|
|
296
|
+
this.logger.warn(`[SessionRefresh] Refresh rejected: sessionId=${rawSession.id} userId=${rawSession.user_id} revoked_at=${rawSession.revoked_at.toISOString()} hash prefix ${hash.slice(0, 8)}`);
|
|
297
|
+
throw new UnauthorizedException(getLocaleText('accessDenied', locale, 'Access denied.'));
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (rawSession.expires_at <= new Date()) {
|
|
301
|
+
this.logger.warn(`[SessionRefresh] Refresh rejected: sessionId=${rawSession.id} userId=${rawSession.user_id} expired expires_at=${rawSession.expires_at.toISOString()} hash prefix ${hash.slice(0, 8)}`);
|
|
302
|
+
throw new UnauthorizedException(getLocaleText('accessDenied', locale, 'Access denied.'));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Simulacao de acesso e nao renovavel. `createImpersonation` ja descarta o
|
|
306
|
+
// token opaco, entao chegar aqui significa que alguem obteve o segredo por
|
|
307
|
+
// outro caminho — e renovar transformaria a janela de 30 minutos numa sessao
|
|
308
|
+
// normal de 30 dias, sem a marca de simulado.
|
|
309
|
+
if (rawSession.impersonator_user_id !== null) {
|
|
310
|
+
this.logger.warn(`[SessionRefresh] Refresh rejected: sessionId=${rawSession.id} userId=${rawSession.user_id} is an impersonation session`);
|
|
311
|
+
throw new UnauthorizedException(getLocaleText('accessDenied', locale, 'Access denied.'));
|
|
312
|
+
}
|
|
215
313
|
|
|
216
|
-
|
|
217
|
-
const
|
|
314
|
+
const nextRefreshToken = await this.token.createOpaqueToken();
|
|
315
|
+
const nextHash = this.security.hashWithPepper(nextRefreshToken);
|
|
316
|
+
const now = Date.now();
|
|
317
|
+
// Sessao de conector nao volta aos 30 dias globais so por ter sido
|
|
318
|
+
// renovada — o TTL curto e a propriedade que a distingue.
|
|
319
|
+
const effectiveTtl = rawSession.audience
|
|
320
|
+
? Math.min(ttlMinutes, SessionService.CONNECTOR_SESSION_TTL_MINUTES)
|
|
321
|
+
: ttlMinutes;
|
|
322
|
+
const expiresAt = new Date(now + effectiveTtl * 60 * 1000);
|
|
323
|
+
const nextIpAddress = ipAddress?.trim() || rawSession.ip_address || 'unknown';
|
|
324
|
+
const nextUserAgent = userAgent?.trim() || rawSession.user_agent || 'unknown';
|
|
325
|
+
|
|
326
|
+
// Compare-and-swap pelo hash corrente, na MESMA linha. Se outra requisicao
|
|
327
|
+
// girou primeiro, `count` volta 0 e a proxima volta le o hash novo — em vez
|
|
328
|
+
// de devolver 401 para o perdedor da corrida, como antes.
|
|
329
|
+
const updateResult = await this.prisma.user_session.updateMany({
|
|
218
330
|
where: {
|
|
219
|
-
id:
|
|
331
|
+
id: rawSession.id,
|
|
220
332
|
revoked_at: null,
|
|
333
|
+
hash: rawSession.hash,
|
|
221
334
|
},
|
|
222
335
|
data: {
|
|
223
|
-
|
|
336
|
+
hash: nextHash,
|
|
337
|
+
previous_hash: rawSession.hash,
|
|
338
|
+
previous_hash_expires_at: new Date(now + SessionService.REFRESH_GRACE_MS),
|
|
339
|
+
expires_at: expiresAt,
|
|
340
|
+
ip_address: nextIpAddress,
|
|
341
|
+
user_agent: nextUserAgent,
|
|
342
|
+
browser_id: rawSession.browser_id ?? browserId ?? null,
|
|
343
|
+
updated_at: new Date(),
|
|
224
344
|
},
|
|
225
345
|
});
|
|
226
346
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
347
|
+
if (updateResult.count === 0) {
|
|
348
|
+
this.logger.debug(`[SessionRefresh] Rotation lost the CAS sessionId=${rawSession.id} userId=${rawSession.user_id} attempt=${attempt}`);
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Depois da rotacao, nunca antes. Rodando antes, o limite podia revogar a
|
|
353
|
+
// propria sessao que estava sendo renovada e o CAS falhava sozinho. E
|
|
354
|
+
// `keepSessionId` garante que renovar nunca despeja quem esta renovando.
|
|
355
|
+
if (maxSessions > 0) {
|
|
356
|
+
await this.enforceSessionLimit(rawSession.user_id, maxSessions, true, browserId, rawSession.id);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
this.logger.debug(`[SessionRefresh] Rotation successful userId=${rawSession.user_id} sessionId=${rawSession.id} durationMs=${Date.now() - now}`);
|
|
360
|
+
|
|
361
|
+
return {
|
|
362
|
+
token: nextRefreshToken,
|
|
363
|
+
session: {
|
|
364
|
+
id: rawSession.id,
|
|
365
|
+
user_id: rawSession.user_id,
|
|
230
366
|
ip_address: nextIpAddress,
|
|
231
367
|
user_agent: nextUserAgent,
|
|
368
|
+
browser_id: rawSession.browser_id ?? browserId ?? null,
|
|
232
369
|
expires_at: expiresAt,
|
|
233
|
-
|
|
234
|
-
|
|
370
|
+
// Quem renova precisa saber que esta renovando uma sessao de conector:
|
|
371
|
+
// e dai que sai o `aud` do proximo access token. Sem isso a rotacao
|
|
372
|
+
// devolveria um token de sessao comum e desfaria o vinculo.
|
|
373
|
+
audience: rawSession.audience ?? null,
|
|
374
|
+
oauth_client_id: rawSession.oauth_client_id ?? null,
|
|
235
375
|
},
|
|
236
|
-
}
|
|
376
|
+
};
|
|
377
|
+
}
|
|
237
378
|
|
|
238
|
-
|
|
239
|
-
|
|
379
|
+
this.logger.warn(`[SessionRefresh] Rotation gave up after ${SessionService.REFRESH_ROTATION_ATTEMPTS} attempts: hash prefix ${hash.slice(0, 8)}`);
|
|
380
|
+
throw new UnauthorizedException(getLocaleText('accessDenied', locale, 'Access denied.'));
|
|
381
|
+
}
|
|
240
382
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
383
|
+
/**
|
|
384
|
+
* Casa o refresh token apresentado com a sessao: pelo hash corrente, ou pelo
|
|
385
|
+
* anterior enquanto a janela de graca estiver aberta.
|
|
386
|
+
*
|
|
387
|
+
* O limite pela janela e o que impede um token antigo qualquer de ressuscitar
|
|
388
|
+
* uma sessao — so o imediatamente anterior, e so por
|
|
389
|
+
* `REFRESH_GRACE_MS`, continua servindo.
|
|
390
|
+
*/
|
|
391
|
+
/**
|
|
392
|
+
* Le a sessao de um refresh token SEM rotacionar nada.
|
|
393
|
+
*
|
|
394
|
+
* Existe porque `refresh()` encontra e gira na mesma operacao: quem precisa
|
|
395
|
+
* decidir se aceita a renovacao (o client confere? o resource confere? a sessao
|
|
396
|
+
* e de conector?) so podia fazer isso depois do compare-and-swap ja commitado —
|
|
397
|
+
* e uma recusa deixava o cliente com um token morto em 30 segundos, sem nunca
|
|
398
|
+
* receber o substituto. Validar antes e a diferenca entre negar um pedido e
|
|
399
|
+
* destruir a sessao.
|
|
400
|
+
*/
|
|
401
|
+
async peekByRefreshToken(refreshToken: string) {
|
|
402
|
+
if (!refreshToken) return null;
|
|
245
403
|
|
|
246
|
-
|
|
404
|
+
const hash = this.security.hashWithPepper(refreshToken);
|
|
405
|
+
|
|
406
|
+
return this.prisma.user_session.findFirst({
|
|
407
|
+
where: this.refreshTokenWhere(hash),
|
|
408
|
+
select: {
|
|
409
|
+
id: true,
|
|
410
|
+
user_id: true,
|
|
411
|
+
revoked_at: true,
|
|
412
|
+
expires_at: true,
|
|
413
|
+
audience: true,
|
|
414
|
+
oauth_client_id: true,
|
|
415
|
+
impersonator_user_id: true,
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
}
|
|
247
419
|
|
|
420
|
+
private refreshTokenWhere(hash: string) {
|
|
248
421
|
return {
|
|
249
|
-
|
|
250
|
-
|
|
422
|
+
OR: [
|
|
423
|
+
{ hash },
|
|
424
|
+
{ previous_hash: hash, previous_hash_expires_at: { gt: new Date() } },
|
|
425
|
+
],
|
|
251
426
|
};
|
|
252
427
|
}
|
|
253
428
|
|
|
@@ -259,21 +434,20 @@ export class SessionService {
|
|
|
259
434
|
}
|
|
260
435
|
|
|
261
436
|
const hash = this.security.hashWithPepper(refreshToken);
|
|
437
|
+
// Aceita tambem o hash anterior dentro da janela de graca: sair da conta com
|
|
438
|
+
// um token que acabou de girar tem de derrubar a sessao de verdade, e nao
|
|
439
|
+
// devolver sucesso deixando-a viva.
|
|
440
|
+
const where = { revoked_at: null, ...this.refreshTokenWhere(hash) };
|
|
441
|
+
|
|
262
442
|
const session = await this.prisma.user_session.findFirst({
|
|
263
|
-
where
|
|
264
|
-
revoked_at: null,
|
|
265
|
-
hash,
|
|
266
|
-
},
|
|
443
|
+
where,
|
|
267
444
|
select: {
|
|
268
445
|
user_id: true,
|
|
269
446
|
},
|
|
270
447
|
});
|
|
271
448
|
|
|
272
449
|
const result = await this.prisma.user_session.updateMany({
|
|
273
|
-
where
|
|
274
|
-
revoked_at: null,
|
|
275
|
-
hash,
|
|
276
|
-
},
|
|
450
|
+
where,
|
|
277
451
|
data: {
|
|
278
452
|
revoked_at: new Date(),
|
|
279
453
|
},
|
|
@@ -322,7 +496,7 @@ export class SessionService {
|
|
|
322
496
|
);
|
|
323
497
|
|
|
324
498
|
return {
|
|
325
|
-
data: await this.attachImpersonators(itemsWithLocation),
|
|
499
|
+
data: await this.attachOAuthClients(await this.attachImpersonators(itemsWithLocation)),
|
|
326
500
|
total: paginate.total || 0,
|
|
327
501
|
lastPage: Math.ceil((paginate.total || 0) / (paginate.pageSize || 1)),
|
|
328
502
|
page: paginate.page ?? 1,
|
|
@@ -373,7 +547,7 @@ export class SessionService {
|
|
|
373
547
|
);
|
|
374
548
|
|
|
375
549
|
return {
|
|
376
|
-
data: await this.attachImpersonators(itemsWithLocation),
|
|
550
|
+
data: await this.attachOAuthClients(await this.attachImpersonators(itemsWithLocation)),
|
|
377
551
|
total: paginate.total || 0,
|
|
378
552
|
lastPage: Math.ceil((paginate.total || 0) / (paginate.pageSize || 1)),
|
|
379
553
|
page: paginate.page ?? 1,
|
|
@@ -469,8 +643,11 @@ export class SessionService {
|
|
|
469
643
|
* @param isRotation - When true, the calling flow is replacing an existing session (refresh),
|
|
470
644
|
* not adding a new one, so no extra slot needs to be freed.
|
|
471
645
|
* @param currentBrowserId - The browser_id of the session being created/refreshed.
|
|
646
|
+
* @param keepSessionId - Session that must survive: its whole browser slot is
|
|
647
|
+
* excluded from eviction. Passed by the refresh flow, so renewing a live
|
|
648
|
+
* session can never revoke the very session being renewed.
|
|
472
649
|
*/
|
|
473
|
-
private async enforceSessionLimit(userId: number, maxSessions: number, isRotation = false, currentBrowserId?: string | null): Promise<void> {
|
|
650
|
+
private async enforceSessionLimit(userId: number, maxSessions: number, isRotation = false, currentBrowserId?: string | null, keepSessionId?: number): Promise<void> {
|
|
474
651
|
const activeSessions = await this.prisma.user_session.findMany({
|
|
475
652
|
where: {
|
|
476
653
|
user_id: userId,
|
|
@@ -479,6 +656,11 @@ export class SessionService {
|
|
|
479
656
|
// Simulacao de acesso nao consome slot: ela nasce com browser_id nulo e
|
|
480
657
|
// seria contada como slot proprio, despejando uma sessao real do alvo.
|
|
481
658
|
impersonator_user_id: null,
|
|
659
|
+
// Sessao de cliente OAuth externo, pelo mesmo motivo: um cliente MCP nao
|
|
660
|
+
// manda X-Browser-ID, entao cada conexao viraria um slot proprio e
|
|
661
|
+
// derrubaria um dispositivo de verdade do usuario — que so queria ligar o
|
|
662
|
+
// Claude. Conector nao e navegador.
|
|
663
|
+
audience: null,
|
|
482
664
|
},
|
|
483
665
|
orderBy: { created_at: 'asc' },
|
|
484
666
|
select: { id: true, browser_id: true }
|
|
@@ -499,6 +681,16 @@ export class SessionService {
|
|
|
499
681
|
const slots = Array.from(slotMap.values());
|
|
500
682
|
const currentSlotCount = slots.length;
|
|
501
683
|
|
|
684
|
+
// O slot de quem esta renovando nunca entra na fila de despejo: renovar uma
|
|
685
|
+
// sessao viva nao pode derrubar a propria sessao. Sem isto, um usuario com
|
|
686
|
+
// mais slots que o limite era deslogado no proximo refresh — a rotacao
|
|
687
|
+
// revogava a si mesma e o compare-and-swap logo em seguida nao achava a
|
|
688
|
+
// linha.
|
|
689
|
+
const protectedSlot = typeof keepSessionId === 'number'
|
|
690
|
+
? slots.find((slot) => slot.ids.includes(keepSessionId))
|
|
691
|
+
: undefined;
|
|
692
|
+
const evictable = slots.filter((slot) => slot !== protectedSlot);
|
|
693
|
+
|
|
502
694
|
// A new browser slot is created only when:
|
|
503
695
|
// - it's not a rotation (rotation keeps the same slot), AND
|
|
504
696
|
// - the current browser doesn't already have an active slot
|
|
@@ -510,10 +702,15 @@ export class SessionService {
|
|
|
510
702
|
|
|
511
703
|
if (slotsToRevoke > 0) {
|
|
512
704
|
const sessionIdsToRevoke: number[] = [];
|
|
513
|
-
for (let i = 0; i < slotsToRevoke; i++) {
|
|
514
|
-
sessionIdsToRevoke.push(...
|
|
705
|
+
for (let i = 0; i < Math.min(slotsToRevoke, evictable.length); i++) {
|
|
706
|
+
sessionIdsToRevoke.push(...evictable[i].ids);
|
|
515
707
|
}
|
|
516
|
-
|
|
708
|
+
|
|
709
|
+
if (sessionIdsToRevoke.length === 0) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
this.logger.warn(`[SessionLimit] Revoking ${sessionIdsToRevoke.length} session(s) in the oldest browser slot(s) for userId=${userId}: [${sessionIdsToRevoke.join(',')}]`);
|
|
517
714
|
await this.prisma.user_session.updateMany({
|
|
518
715
|
where: { id: { in: sessionIdsToRevoke } },
|
|
519
716
|
data: { revoked_at: new Date() }
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { NotFoundException } from '@nestjs/common';
|
|
2
|
+
import { FaviconController } from './favicon.controller';
|
|
3
|
+
|
|
4
|
+
const makeRes = () => {
|
|
5
|
+
const res: any = { headers: {} as Record<string, string> };
|
|
6
|
+
res.setHeader = jest.fn((k: string, v: string) => (res.headers[k] = v));
|
|
7
|
+
res.send = jest.fn((body: Buffer) => (res.body = body));
|
|
8
|
+
return res;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const makeController = (settings: Record<string, string>) => {
|
|
12
|
+
const setting = { getSettingValues: jest.fn().mockResolvedValue(settings) };
|
|
13
|
+
const brandAsset = {
|
|
14
|
+
resolveAssetUrl: jest.fn(async (value: string) =>
|
|
15
|
+
value.startsWith('/') ? `https://app.example.com${value}` : value,
|
|
16
|
+
),
|
|
17
|
+
};
|
|
18
|
+
return new FaviconController(setting as any, brandAsset as any);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const svg = '<svg xmlns="http://www.w3.org/2000/svg"/>';
|
|
22
|
+
|
|
23
|
+
describe('FaviconController', () => {
|
|
24
|
+
const originalFetch = globalThis.fetch;
|
|
25
|
+
let fetchMock: jest.Mock;
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
fetchMock = jest.fn().mockResolvedValue(
|
|
29
|
+
new Response(svg, { headers: { 'content-type': 'image/svg+xml' } }),
|
|
30
|
+
);
|
|
31
|
+
globalThis.fetch = fetchMock as any;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
globalThis.fetch = originalFetch;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('serves the Branding icon with the origin content type', async () => {
|
|
39
|
+
const controller = makeController({ 'icon-url': '/logo.svg' });
|
|
40
|
+
const res = makeRes();
|
|
41
|
+
|
|
42
|
+
await controller.favicon(res);
|
|
43
|
+
|
|
44
|
+
expect(fetchMock.mock.calls[0][0]).toBe('https://app.example.com/logo.svg');
|
|
45
|
+
expect(res.headers['Content-Type']).toBe('image/svg+xml');
|
|
46
|
+
expect(res.body.toString()).toBe(svg);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('falls back to image-url and caches the download', async () => {
|
|
50
|
+
const controller = makeController({ 'icon-url': '', 'image-url': '/brand.svg' });
|
|
51
|
+
|
|
52
|
+
await controller.favicon(makeRes());
|
|
53
|
+
await controller.favicon(makeRes());
|
|
54
|
+
|
|
55
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
56
|
+
expect(fetchMock.mock.calls[0][0]).toBe('https://app.example.com/brand.svg');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('decodes a data URI without fetching', async () => {
|
|
60
|
+
const png = Buffer.from([0x89, 0x50, 0x4e, 0x47]);
|
|
61
|
+
const controller = makeController({
|
|
62
|
+
'icon-url': `data:image/png;base64,${png.toString('base64')}`,
|
|
63
|
+
});
|
|
64
|
+
const res = makeRes();
|
|
65
|
+
|
|
66
|
+
await controller.favicon(res);
|
|
67
|
+
|
|
68
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
69
|
+
expect(res.headers['Content-Type']).toBe('image/png');
|
|
70
|
+
expect(Buffer.compare(res.body, png)).toBe(0);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('answers 404 when the source is not an image', async () => {
|
|
74
|
+
fetchMock.mockResolvedValue(
|
|
75
|
+
new Response('<html/>', { headers: { 'content-type': 'text/html' } }),
|
|
76
|
+
);
|
|
77
|
+
const controller = makeController({ 'icon-url': '/logo.svg' });
|
|
78
|
+
|
|
79
|
+
await expect(controller.favicon(makeRes())).rejects.toBeInstanceOf(
|
|
80
|
+
NotFoundException,
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('answers 404 when nothing is configured', async () => {
|
|
85
|
+
const controller = makeController({});
|
|
86
|
+
|
|
87
|
+
await expect(controller.favicon(makeRes())).rejects.toBeInstanceOf(
|
|
88
|
+
NotFoundException,
|
|
89
|
+
);
|
|
90
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
91
|
+
});
|
|
92
|
+
});
|