@owox/backend 0.35.0 → 0.36.0
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/src/common/exceptions/concurrency-limit-exceeded.exception.d.ts +1 -1
- package/dist/src/common/exceptions/concurrency-limit-exceeded.exception.js +2 -2
- package/dist/src/common/markdown/markdown-parser.service.d.ts +2 -0
- package/dist/src/common/markdown/markdown-parser.service.js +15 -8
- package/dist/src/common/validators/max-byte-length.validator.d.ts +2 -0
- package/dist/src/common/validators/max-byte-length.validator.js +29 -0
- package/dist/src/config/env-validation.config.d.ts +12 -0
- package/dist/src/config/env-validation.config.js +7 -0
- package/dist/src/data-marts/ai-insights/agent/types.d.ts +6 -6
- package/dist/src/data-marts/calculated-fields/calculated-field-validator.service.js +22 -30
- package/dist/src/data-marts/calculated-fields/calculated-field.utils.d.ts +1 -0
- package/dist/src/data-marts/calculated-fields/calculated-field.utils.js +21 -0
- package/dist/src/data-marts/calculated-fields/formula-analyzer.d.ts +1 -0
- package/dist/src/data-marts/calculated-fields/formula-analyzer.js +2 -0
- package/dist/src/data-marts/calculated-fields/formula-violations.d.ts +7 -0
- package/dist/src/data-marts/calculated-fields/formula-violations.js +82 -1
- package/dist/src/data-marts/calculated-fields/join-grain.d.ts +32 -0
- package/dist/src/data-marts/calculated-fields/join-grain.js +107 -0
- package/dist/src/data-marts/calculated-fields/set-quantifier.d.ts +8 -0
- package/dist/src/data-marts/calculated-fields/set-quantifier.js +12 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/connector-message.schema.d.ts +66 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/connector-message.schema.js +13 -1
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-credentials-update.schema.d.ts +3 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-credentials-update.schema.js +1 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-error.schema.d.ts +3 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-error.schema.js +1 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-log.schema.d.ts +12 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-log.schema.js +4 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-requested-date.schema.d.ts +3 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-requested-date.schema.js +1 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-state-update.schema.d.ts +16 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-state-update.schema.js +16 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-status.schema.d.ts +3 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-status.schema.js +1 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-warning.schema.d.ts +3 -0
- package/dist/src/data-marts/connector-types/connector-message/schemas/types/message-warning.schema.js +1 -0
- package/dist/src/data-marts/connector-types/connector-message/services/connector-event.translator.d.ts +10 -0
- package/dist/src/data-marts/connector-types/connector-message/services/connector-event.translator.js +138 -0
- package/dist/src/data-marts/connector-types/connector-message/services/connector-message-parser.service.d.ts +1 -3
- package/dist/src/data-marts/connector-types/connector-message/services/connector-message-parser.service.js +30 -34
- package/dist/src/data-marts/connector-types/connector-message/services/connector-output-capture.service.js +10 -12
- package/dist/src/data-marts/connector-types/connector-message/services/connector-state.service.js +3 -1
- package/dist/src/data-marts/connector-types/enums/connector-message-type-enum.d.ts +1 -0
- package/dist/src/data-marts/connector-types/enums/connector-message-type-enum.js +1 -0
- package/dist/src/data-marts/controllers/connector-definition.controller.d.ts +30 -0
- package/dist/src/data-marts/controllers/connector-definition.controller.js +252 -0
- package/dist/src/data-marts/controllers/data-mart-preview.controller.d.ts +10 -0
- package/dist/src/data-marts/controllers/data-mart-preview.controller.js +58 -0
- package/dist/src/data-marts/controllers/data-mart.controller.d.ts +5 -1
- package/dist/src/data-marts/controllers/data-mart.controller.js +25 -4
- package/dist/src/data-marts/controllers/insight-template.controller.js +4 -4
- package/dist/src/data-marts/controllers/insight.controller.js +5 -5
- package/dist/src/data-marts/controllers/project-data-mart-runs.controller.js +1 -1
- package/dist/src/data-marts/controllers/spec/connector-definition.api.d.ts +12 -0
- package/dist/src/data-marts/controllers/spec/connector-definition.api.js +179 -0
- package/dist/src/data-marts/controllers/spec/data-mart.api.d.ts +1 -0
- package/dist/src/data-marts/controllers/spec/data-mart.api.js +5 -0
- package/dist/src/data-marts/controllers/spec/report-openapi.d.ts +18 -0
- package/dist/src/data-marts/controllers/spec/report-openapi.js +3 -0
- package/dist/src/data-marts/data-marts.module.js +20 -2
- package/dist/src/data-marts/data-storage-types/blending/metric-sleeve.planner.js +3 -12
- package/dist/src/data-marts/data-storage-types/data-mart-schema.utils.d.ts +1 -0
- package/dist/src/data-marts/data-storage-types/data-mart-schema.utils.js +16 -0
- package/dist/src/data-marts/dto/domain/blendable-schema.dto.d.ts +10 -0
- package/dist/src/data-marts/dto/domain/blendable-schema.dto.js +71 -1
- package/dist/src/data-marts/dto/domain/create-data-mart.command.d.ts +3 -1
- package/dist/src/data-marts/dto/domain/create-data-mart.command.js +3 -1
- package/dist/src/data-marts/dto/domain/create-report.command.d.ts +3 -1
- package/dist/src/data-marts/dto/domain/create-report.command.js +3 -1
- package/dist/src/data-marts/dto/domain/data-mart-list-item.dto.d.ts +3 -1
- package/dist/src/data-marts/dto/domain/data-mart-list-item.dto.js +3 -1
- package/dist/src/data-marts/dto/domain/data-mart.dto.d.ts +4 -1
- package/dist/src/data-marts/dto/domain/data-mart.dto.js +5 -1
- package/dist/src/data-marts/dto/domain/model-canvas.dto.d.ts +4 -0
- package/dist/src/data-marts/dto/domain/report-like-read-plan.d.ts +2 -0
- package/dist/src/data-marts/dto/domain/report.dto.d.ts +3 -1
- package/dist/src/data-marts/dto/domain/report.dto.js +3 -1
- package/dist/src/data-marts/dto/domain/update-data-mart-icon.command.d.ts +9 -0
- package/dist/src/data-marts/dto/domain/update-data-mart-icon.command.js +19 -0
- package/dist/src/data-marts/dto/domain/update-report.command.d.ts +3 -1
- package/dist/src/data-marts/dto/domain/update-report.command.js +3 -1
- package/dist/src/data-marts/dto/presentation/create-data-mart-request-api.dto.d.ts +2 -0
- package/dist/src/data-marts/dto/presentation/create-data-mart-request-api.dto.js +13 -0
- package/dist/src/data-marts/dto/presentation/create-report-request-api.dto.d.ts +2 -0
- package/dist/src/data-marts/dto/presentation/create-report-request-api.dto.js +10 -0
- package/dist/src/data-marts/dto/presentation/custom-connector-response.dto.d.ts +46 -0
- package/dist/src/data-marts/dto/presentation/custom-connector-response.dto.js +216 -0
- package/dist/src/data-marts/dto/presentation/custom-connector.dto.d.ts +27 -0
- package/dist/src/data-marts/dto/presentation/custom-connector.dto.js +159 -0
- package/dist/src/data-marts/dto/presentation/data-mart-list-item-response-api.dto.d.ts +2 -0
- package/dist/src/data-marts/dto/presentation/data-mart-list-item-response-api.dto.js +10 -0
- package/dist/src/data-marts/dto/presentation/data-mart-response-api.dto.d.ts +2 -0
- package/dist/src/data-marts/dto/presentation/data-mart-response-api.dto.js +10 -0
- package/dist/src/data-marts/dto/presentation/model-canvas-response-api.dto.d.ts +4 -0
- package/dist/src/data-marts/dto/presentation/model-canvas-response-api.dto.js +20 -0
- package/dist/src/data-marts/dto/presentation/preview-data-mart-request-api.dto.d.ts +7 -0
- package/dist/src/data-marts/dto/presentation/preview-data-mart-request-api.dto.js +56 -0
- package/dist/src/data-marts/dto/presentation/preview-data-mart-response-api.dto.d.ts +12 -0
- package/dist/src/data-marts/dto/presentation/preview-data-mart-response-api.dto.js +64 -0
- package/dist/src/data-marts/dto/presentation/report-response-api.dto.d.ts +2 -0
- package/dist/src/data-marts/dto/presentation/report-response-api.dto.js +6 -0
- package/dist/src/data-marts/dto/presentation/run-data-mart-request-api.dto.js +67 -0
- package/dist/src/data-marts/dto/presentation/update-data-mart-description-api.dto.js +3 -0
- package/dist/src/data-marts/dto/presentation/update-data-mart-icon-api.dto.d.ts +4 -0
- package/dist/src/data-marts/dto/presentation/update-data-mart-icon-api.dto.js +30 -0
- package/dist/src/data-marts/dto/presentation/update-report-request-api.dto.d.ts +2 -0
- package/dist/src/data-marts/dto/presentation/update-report-request-api.dto.js +10 -0
- package/dist/src/data-marts/dto/schemas/auto-aggregation-opt-out.schema.d.ts +15 -0
- package/dist/src/data-marts/dto/schemas/auto-aggregation-opt-out.schema.js +29 -0
- package/dist/src/data-marts/dto/schemas/data-mart-run/data-mart-run.schema.d.ts +9 -0
- package/dist/src/data-marts/dto/schemas/data-mart-table-definitions/connector-definition.schema.d.ts +15 -0
- package/dist/src/data-marts/dto/schemas/data-mart-table-definitions/connector-definition.schema.js +1 -0
- package/dist/src/data-marts/dto/schemas/data-mart-table-definitions/data-mart-definition.schema.d.ts +7 -0
- package/dist/src/data-marts/dto/schemas/data-quality/data-quality-run.schema.d.ts +20 -0
- package/dist/src/data-marts/entities/connector-definition-version.entity.d.ts +16 -0
- package/dist/src/data-marts/entities/connector-definition-version.entity.js +78 -0
- package/dist/src/data-marts/entities/connector-definition.entity.d.ts +14 -0
- package/dist/src/data-marts/entities/connector-definition.entity.js +82 -0
- package/dist/src/data-marts/entities/data-mart.entity.d.ts +2 -0
- package/dist/src/data-marts/entities/data-mart.entity.js +5 -0
- package/dist/src/data-marts/entities/report.entity.d.ts +2 -0
- package/dist/src/data-marts/entities/report.entity.js +11 -0
- package/dist/src/data-marts/enums/data-mart-icon.enum.d.ts +75 -0
- package/dist/src/data-marts/enums/data-mart-icon.enum.js +80 -0
- package/dist/src/data-marts/errors/connector-credential-boundary.error.d.ts +3 -0
- package/dist/src/data-marts/errors/connector-credential-boundary.error.js +14 -0
- package/dist/src/data-marts/facades/mcp-data-marts.facade.d.ts +2 -0
- package/dist/src/data-marts/facades/mcp-data-marts.facade.impl.d.ts +7 -1
- package/dist/src/data-marts/facades/mcp-data-marts.facade.impl.js +70 -5
- package/dist/src/data-marts/mappers/connector-definition.mapper.d.ts +14 -0
- package/dist/src/data-marts/mappers/connector-definition.mapper.js +57 -0
- package/dist/src/data-marts/mappers/data-mart.mapper.d.ts +9 -6
- package/dist/src/data-marts/mappers/data-mart.mapper.js +44 -19
- package/dist/src/data-marts/mappers/insight-template.mapper.d.ts +1 -1
- package/dist/src/data-marts/mappers/insight-template.mapper.js +2 -2
- package/dist/src/data-marts/mappers/insight.mapper.d.ts +1 -1
- package/dist/src/data-marts/mappers/insight.mapper.js +2 -2
- package/dist/src/data-marts/mappers/model-canvas.mapper.d.ts +10 -2
- package/dist/src/data-marts/mappers/model-canvas.mapper.js +9 -3
- package/dist/src/data-marts/mappers/report.mapper.js +4 -3
- package/dist/src/data-marts/services/auto-collapse.resolver.d.ts +1 -1
- package/dist/src/data-marts/services/auto-collapse.resolver.js +4 -0
- package/dist/src/data-marts/services/blendable-schema.service.d.ts +2 -0
- package/dist/src/data-marts/services/blendable-schema.service.js +59 -0
- package/dist/src/data-marts/services/connector/connector-credential-injector.service.d.ts +1 -1
- package/dist/src/data-marts/services/connector/connector-credential-injector.service.js +15 -1
- package/dist/src/data-marts/services/connector/connector-definition.service.d.ts +59 -0
- package/dist/src/data-marts/services/connector/connector-definition.service.js +491 -0
- package/dist/src/data-marts/services/connector/connector-executor.service.d.ts +9 -1
- package/dist/src/data-marts/services/connector/connector-executor.service.js +173 -63
- package/dist/src/data-marts/services/connector/connector-fields-preview.service.js +1 -1
- package/dist/src/data-marts/services/connector/connector-message.utils.js +2 -2
- package/dist/src/data-marts/services/connector/connector-preview-credentials.service.js +1 -1
- package/dist/src/data-marts/services/connector/connector-preview-support.d.ts +1 -1
- package/dist/src/data-marts/services/connector/connector-preview-support.js +14 -21
- package/dist/src/data-marts/services/connector/connector-process-spawner.service.d.ts +11 -2
- package/dist/src/data-marts/services/connector/connector-process-spawner.service.js +88 -60
- package/dist/src/data-marts/services/connector/connector-secret.service.d.ts +6 -3
- package/dist/src/data-marts/services/connector/connector-secret.service.js +77 -12
- package/dist/src/data-marts/services/connector/connector-source-config.service.js +1 -1
- package/dist/src/data-marts/services/connector/connector-source-credentials.service.d.ts +6 -2
- package/dist/src/data-marts/services/connector/connector-source-credentials.service.js +18 -16
- package/dist/src/data-marts/services/connector/connector-specification.mapper.d.ts +47 -0
- package/dist/src/data-marts/services/connector/connector-specification.mapper.js +46 -0
- package/dist/src/data-marts/services/connector/connector-test.service.d.ts +43 -0
- package/dist/src/data-marts/services/connector/connector-test.service.js +343 -0
- package/dist/src/data-marts/services/connector/connector.service.d.ts +8 -2
- package/dist/src/data-marts/services/connector/connector.service.js +65 -54
- package/dist/src/data-marts/services/connector/declarative-manifest-schemas.d.ts +4 -0
- package/dist/src/data-marts/services/connector/declarative-manifest-schemas.js +48 -0
- package/dist/src/data-marts/services/connector/run-log-flusher.d.ts +21 -0
- package/dist/src/data-marts/services/connector/run-log-flusher.js +67 -0
- package/dist/src/data-marts/services/data-mart.service.js +2 -0
- package/dist/src/data-marts/services/report-sql-composer.service.js +15 -1
- package/dist/src/data-marts/services/report.service.d.ts +1 -0
- package/dist/src/data-marts/services/report.service.js +13 -0
- package/dist/src/data-marts/services/scheduled-trigger.service.d.ts +1 -0
- package/dist/src/data-marts/services/scheduled-trigger.service.js +13 -0
- package/dist/src/data-marts/use-cases/create-data-mart.service.js +1 -0
- package/dist/src/data-marts/use-cases/create-report.service.js +2 -0
- package/dist/src/data-marts/use-cases/get-model-canvas-data-marts.service.d.ts +5 -1
- package/dist/src/data-marts/use-cases/get-model-canvas-data-marts.service.js +16 -3
- package/dist/src/data-marts/use-cases/list-project-scheduled-triggers.service.js +1 -1
- package/dist/src/data-marts/use-cases/preview-data-mart.service.d.ts +59 -0
- package/dist/src/data-marts/use-cases/preview-data-mart.service.js +293 -0
- package/dist/src/data-marts/use-cases/stream-http-data.service.js +1 -0
- package/dist/src/data-marts/use-cases/update-data-mart-definition.service.d.ts +1 -1
- package/dist/src/data-marts/use-cases/update-data-mart-definition.service.js +8 -6
- package/dist/src/data-marts/use-cases/update-data-mart-icon.service.d.ts +12 -0
- package/dist/src/data-marts/use-cases/update-data-mart-icon.service.js +46 -0
- package/dist/src/data-marts/use-cases/update-data-mart-schema.service.js +14 -1
- package/dist/src/data-marts/use-cases/update-report.service.js +9 -1
- package/dist/src/ee/ee.module.js +5 -8
- package/dist/src/ee/mcp/auth/mcp-auth-context.d.ts +0 -4
- package/dist/src/ee/mcp/auth/mcp-auth.middleware.d.ts +26 -0
- package/dist/src/ee/mcp/auth/mcp-auth.middleware.js +184 -0
- package/dist/src/ee/mcp/http-headers.util.d.ts +2 -0
- package/dist/src/ee/mcp/http-headers.util.js +8 -0
- package/dist/src/ee/mcp/observability/mcp-bus-wiring.js +4 -4
- package/dist/src/ee/mcp/observability/mcp-call-instrumentation.d.ts +2 -4
- package/dist/src/ee/mcp/observability/mcp-call-instrumentation.js +6 -6
- package/dist/src/ee/mcp/sdk/mcp-sdk-server.factory.d.ts +1 -1
- package/dist/src/ee/mcp/sdk/mcp-sdk-server.factory.js +5 -5
- package/dist/src/ee/mcp/tools/add-destination.tool.d.ts +20 -14
- package/dist/src/ee/mcp/tools/add-destination.tool.js +10 -10
- package/dist/src/ee/mcp/tools/add-report.tool.d.ts +88 -228
- package/dist/src/ee/mcp/tools/add-report.tool.js +28 -28
- package/dist/src/ee/mcp/tools/create-report-run-schedule.tool.d.ts +2 -12
- package/dist/src/ee/mcp/tools/create-report-run-schedule.tool.js +13 -13
- package/dist/src/ee/mcp/tools/data-mart-catalog.tool.d.ts +15 -81
- package/dist/src/ee/mcp/tools/data-mart-catalog.tool.js +11 -11
- package/dist/src/ee/mcp/tools/data-mart-details.tool.d.ts +19 -111
- package/dist/src/ee/mcp/tools/data-mart-details.tool.js +64 -48
- package/dist/src/ee/mcp/tools/delete-report-run-schedule.tool.d.ts +2 -6
- package/dist/src/ee/mcp/tools/delete-report-run-schedule.tool.js +7 -7
- package/dist/src/ee/mcp/tools/delete-report.tool.d.ts +2 -6
- package/dist/src/ee/mcp/tools/delete-report.tool.js +4 -4
- package/dist/src/ee/mcp/tools/get-data-mart-reports.tool.d.ts +30 -195
- package/dist/src/ee/mcp/tools/get-data-mart-reports.tool.js +22 -22
- package/dist/src/ee/mcp/tools/get-report-output-schema.tool.d.ts +3 -21
- package/dist/src/ee/mcp/tools/get-report-output-schema.tool.js +10 -10
- package/dist/src/ee/mcp/tools/get-report-run-status.tool.d.ts +15 -11
- package/dist/src/ee/mcp/tools/get-report-run-status.tool.js +14 -14
- package/dist/src/ee/mcp/tools/list-destinations.tool.d.ts +12 -20
- package/dist/src/ee/mcp/tools/list-destinations.tool.js +10 -10
- package/dist/src/ee/mcp/tools/list-report-run-schedules.tool.d.ts +5 -61
- package/dist/src/ee/mcp/tools/list-report-run-schedules.tool.js +14 -14
- package/dist/src/ee/mcp/tools/mcp-getting-started.util.d.ts +4 -52
- package/dist/src/ee/mcp/tools/mcp-getting-started.util.js +13 -13
- package/dist/src/ee/mcp/tools/mcp-tool.definition.d.ts +2 -2
- package/dist/src/ee/mcp/tools/project-context.tool.d.ts +3 -17
- package/dist/src/ee/mcp/tools/project-context.tool.js +10 -10
- package/dist/src/ee/mcp/tools/query-data-mart.input.d.ts +111 -152
- package/dist/src/ee/mcp/tools/query-data-mart.input.js +39 -39
- package/dist/src/ee/mcp/tools/query-data-mart.tool.d.ts +60 -130
- package/dist/src/ee/mcp/tools/query-data-mart.tool.js +35 -35
- package/dist/src/ee/mcp/tools/report-output-controls-output.d.ts +17 -60
- package/dist/src/ee/mcp/tools/report-output-controls-output.js +20 -20
- package/dist/src/ee/mcp/tools/report-run-outcome.d.ts +6 -42
- package/dist/src/ee/mcp/tools/report-run-outcome.js +20 -20
- package/dist/src/ee/mcp/tools/run-report.tool.d.ts +2 -6
- package/dist/src/ee/mcp/tools/run-report.tool.js +5 -5
- package/dist/src/ee/mcp/tools/search-data-marts.tool.d.ts +7 -79
- package/dist/src/ee/mcp/tools/search-data-marts.tool.js +11 -11
- package/dist/src/ee/mcp/tools/search-reports.tool.d.ts +15 -61
- package/dist/src/ee/mcp/tools/search-reports.tool.js +15 -15
- package/dist/src/ee/mcp/tools/summarize-data-catalog.tool.d.ts +7 -79
- package/dist/src/ee/mcp/tools/summarize-data-catalog.tool.js +15 -15
- package/dist/src/ee/mcp/tools/update-report-run-schedule.tool.d.ts +2 -12
- package/dist/src/ee/mcp/tools/update-report-run-schedule.tool.js +13 -13
- package/dist/src/ee/mcp/tools/update-report.tool.d.ts +105 -414
- package/dist/src/ee/mcp/tools/update-report.tool.js +20 -20
- package/dist/src/ee/mcp/transport/mcp-http-entry.service.d.ts +30 -0
- package/dist/src/ee/mcp/transport/mcp-http-entry.service.js +193 -0
- package/dist/src/idp/guards/idp.guard.js +2 -8
- package/dist/src/idp/oauth/controllers/oauth-authorization.controller.d.ts +4 -0
- package/dist/src/idp/oauth/controllers/oauth-authorization.controller.js +77 -1
- package/dist/src/idp/oauth/controllers/oauth-metadata.controller.d.ts +2 -1
- package/dist/src/idp/oauth/controllers/oauth-metadata.controller.js +5 -8
- package/dist/src/idp/oauth/controllers/oauth-token.controller.js +14 -1
- package/dist/src/idp/oauth/oauth-request.validator.d.ts +8 -0
- package/dist/src/idp/oauth/oauth-request.validator.js +27 -0
- package/dist/src/idp/utils/is-authentication-error.d.ts +1 -0
- package/dist/src/idp/utils/is-authentication-error.js +9 -0
- package/dist/src/idp/utils/role-hierarchy.d.ts +3 -0
- package/dist/src/idp/utils/role-hierarchy.js +14 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +3 -1
- package/dist/src/migrations/1788048000000-create-connector-definition-tables.d.ts +6 -0
- package/dist/src/migrations/1788048000000-create-connector-definition-tables.js +116 -0
- package/dist/src/migrations/1790156789783-add-auto-aggregation-opt-out-to-report.d.ts +8 -0
- package/dist/src/migrations/1790156789783-add-auto-aggregation-opt-out-to-report.js +30 -0
- package/dist/src/migrations/1790247861000-add-icon-to-data-mart.d.ts +8 -0
- package/dist/src/migrations/1790247861000-add-icon-to-data-mart.js +31 -0
- package/package.json +10 -6
- package/dist/src/ee/mcp/auth/mcp-auth.exception-filter.d.ts +0 -14
- package/dist/src/ee/mcp/auth/mcp-auth.exception-filter.js +0 -84
- package/dist/src/ee/mcp/auth/mcp-auth.guard.d.ts +0 -14
- package/dist/src/ee/mcp/auth/mcp-auth.guard.js +0 -99
- package/dist/src/ee/mcp/controllers/mcp-transport.controller.d.ts +0 -17
- package/dist/src/ee/mcp/controllers/mcp-transport.controller.js +0 -134
- package/dist/src/ee/mcp/sdk/mcp-streamable-http-transport.handler.d.ts +0 -16
- package/dist/src/ee/mcp/sdk/mcp-streamable-http-transport.handler.js +0 -133
|
@@ -14,7 +14,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.UpdateReportTool = exports.updateReportInputSchema = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
|
-
const
|
|
17
|
+
const zod_v4_1 = require("zod-v4");
|
|
18
18
|
const mcp_reports_facade_1 = require("../../../data-marts/facades/mcp-reports.facade");
|
|
19
19
|
const mcp_destination_type_1 = require("../../../data-marts/facades/mcp-destination-type");
|
|
20
20
|
const mcp_tool_definition_1 = require("./mcp-tool.definition");
|
|
@@ -27,56 +27,56 @@ const EMAIL_FAMILY_DESTINATION_TYPES = new Set(['email', 'slack', 'teams', 'goog
|
|
|
27
27
|
function isEmailFamily(type) {
|
|
28
28
|
return EMAIL_FAMILY_DESTINATION_TYPES.has(type);
|
|
29
29
|
}
|
|
30
|
-
const baseInputSchema =
|
|
30
|
+
const baseInputSchema = zod_v4_1.z
|
|
31
31
|
.object({
|
|
32
|
-
report_id:
|
|
33
|
-
fields:
|
|
34
|
-
.array(
|
|
32
|
+
report_id: zod_v4_1.z.string().min(1),
|
|
33
|
+
fields: zod_v4_1.z
|
|
34
|
+
.array(zod_v4_1.z.string().min(1))
|
|
35
35
|
.min(1)
|
|
36
36
|
.optional()
|
|
37
37
|
.describe("Replacement column selection, e.g. ['field_name_1', 'field_name_2'], or ['*'] for every field; omit to keep current. At least one change parameter is required."),
|
|
38
|
-
filters:
|
|
38
|
+
filters: zod_v4_1.z
|
|
39
39
|
.array((0, query_data_mart_input_1.makeMcpFilterSchema)())
|
|
40
40
|
.optional()
|
|
41
41
|
.describe('Replacement row filters applied on every report run — same shape and operator vocabulary as query_data_mart\'s "filters". Replaces only the current row filters MCP can express (stored slices are untouched); rules created in the OWOX UI that MCP cannot express — post-aggregation (HAVING) constraints, regex, calendar presets such as today or last month — are kept automatically and listed as ui_only_filters. Copy the filters to keep from get_data_mart_reports; pass [] to remove every expressible row filter; omit to keep current.'),
|
|
42
|
-
slices:
|
|
42
|
+
slices: zod_v4_1.z
|
|
43
43
|
.array((0, query_data_mart_input_1.makeMcpFilterSchema)())
|
|
44
44
|
.optional()
|
|
45
45
|
.describe('Replacement pre-join filters (blended data marts only), same as query_data_mart\'s "slices". Replaces only the current slices MCP can express (stored row filters and UI-only slices are untouched); pass [] to remove every expressible slice; omit to keep current.'),
|
|
46
|
-
aggregations:
|
|
46
|
+
aggregations: zod_v4_1.z
|
|
47
47
|
.array((0, query_data_mart_input_1.makeMcpReportAggregationSchema)())
|
|
48
48
|
.optional()
|
|
49
49
|
.describe('Replacement aggregations, same as query_data_mart\'s "aggregations" plus the report-only STRING_AGG and ANY_VALUE. Each aggregated field must also appear in the report\'s column selection. Replaces ALL current aggregations — copy the ones to keep from get_data_mart_reports; pass [] to remove them; omit to keep current.'),
|
|
50
|
-
date_buckets:
|
|
50
|
+
date_buckets: zod_v4_1.z
|
|
51
51
|
.array((0, query_data_mart_input_1.makeMcpDateBucketSchema)())
|
|
52
52
|
.optional()
|
|
53
53
|
.describe('Replacement date buckets (DAY/WEEK/MONTH/QUARTER/YEAR), same as query_data_mart\'s "date_buckets". Replaces ALL current buckets; pass [] to remove them; omit to keep current.'),
|
|
54
|
-
sort:
|
|
54
|
+
sort: zod_v4_1.z
|
|
55
55
|
.array((0, query_data_mart_input_1.makeMcpSortSchema)())
|
|
56
56
|
.optional()
|
|
57
57
|
.describe('Replacement sort order, same as query_data_mart\'s "sort". Replaces the current order; pass [] to remove it; omit to keep current.'),
|
|
58
|
-
limit:
|
|
58
|
+
limit: zod_v4_1.z
|
|
59
59
|
.number()
|
|
60
60
|
.int()
|
|
61
61
|
.min(1)
|
|
62
62
|
.nullable()
|
|
63
63
|
.optional()
|
|
64
64
|
.describe('New max rows per report run; pass null to remove the cap; omit to keep current.'),
|
|
65
|
-
name:
|
|
65
|
+
name: zod_v4_1.z
|
|
66
66
|
.string()
|
|
67
67
|
.trim()
|
|
68
68
|
.min(1)
|
|
69
69
|
.optional()
|
|
70
70
|
.describe('New report name; omit to keep current. At least one change parameter is required.'),
|
|
71
|
-
message:
|
|
71
|
+
message: zod_v4_1.z
|
|
72
72
|
.object({
|
|
73
|
-
subject:
|
|
73
|
+
subject: zod_v4_1.z
|
|
74
74
|
.string()
|
|
75
75
|
.trim()
|
|
76
76
|
.min(1)
|
|
77
77
|
.optional()
|
|
78
78
|
.describe('New message subject or heading; omit to keep the current one.'),
|
|
79
|
-
body:
|
|
79
|
+
body: zod_v4_1.z
|
|
80
80
|
.string()
|
|
81
81
|
.trim()
|
|
82
82
|
.min(1)
|
|
@@ -86,7 +86,7 @@ const baseInputSchema = zod_1.z
|
|
|
86
86
|
.strict()
|
|
87
87
|
.optional()
|
|
88
88
|
.describe('Message changes. Applies only to reports with an email, slack, teams, or google_chat destination; rejected for other types. Provide at least one of subject/body inside. The send condition and recipients are not editable here.'),
|
|
89
|
-
run_immediately:
|
|
89
|
+
run_immediately: zod_v4_1.z
|
|
90
90
|
.boolean()
|
|
91
91
|
.optional()
|
|
92
92
|
.describe('Whether to run the report after the update (one billed Report Run). Omit for the default: a Google Sheets report re-runs when what it exports actually changed (fields or any output control differ from the stored definition), so the sheet reflects the change; it does not run for a name-only or message-only change or for re-sent identical controls. Email, Slack, Microsoft Teams, and Google Chat reports are NOT re-sent by default, because a run delivers the message to every configured recipient or channel — set true only when the user explicitly wants it sent now. Set false to update a Google Sheets report without refreshing it. Looker Studio is pull-based: omit or set false; true is rejected.'),
|
|
@@ -116,10 +116,10 @@ let UpdateReportTool = class UpdateReportTool {
|
|
|
116
116
|
description = 'Update an existing report: rename it, replace which data mart fields it exports, replace its output controls — filters/slices, aggregations, date_buckets, sort, limit — using the same vocabulary as query_data_mart ([] removes a control, null removes the limit), and/or — for reports with an email, slack, teams, or google_chat destination — change the message subject or body. Use it whenever the user asks to change a report that already exists — including one you created earlier in this conversation ("add a filter", "sort by revenue", "rename it") — instead of creating another report with add_report. Provide at least one change; anything not provided stays unchanged. Returns the report as it is after the update, and by default re-runs a Google Sheets report when the export changed (run.status="queued" — poll get_report_run_status), so the sheet shows the new definition; email, Slack, Teams, and Google Chat reports are re-sent only with run_immediately=true.';
|
|
117
117
|
zodSchema = baseInputSchema.shape;
|
|
118
118
|
outputSchema = {
|
|
119
|
-
report_id:
|
|
120
|
-
status:
|
|
121
|
-
destination_type:
|
|
122
|
-
name:
|
|
119
|
+
report_id: zod_v4_1.z.string().describe('Id of the updated report'),
|
|
120
|
+
status: zod_v4_1.z.literal('updated').describe("Always 'updated' on success"),
|
|
121
|
+
destination_type: zod_v4_1.z.enum(mcp_destination_type_1.MCP_DESTINATION_TYPES),
|
|
122
|
+
name: zod_v4_1.z.string().describe('Report name after the update'),
|
|
123
123
|
...report_output_controls_output_1.reportOutputControlsOutputShape,
|
|
124
124
|
...report_output_controls_output_1.reportSheetInfoOutputShape,
|
|
125
125
|
run: report_run_outcome_1.reportRunOutcomeSchema.describe('Outcome of the refresh run queued after the update. The update is saved for every status.'),
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { OnModuleDestroy, OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { HttpAdapterHost } from '@nestjs/core';
|
|
3
|
+
import { GracefulShutdownService } from '../../../common/scheduler/services/graceful-shutdown.service';
|
|
4
|
+
import { ClsContextService } from '../../../common/logger/cls-context.service';
|
|
5
|
+
import { McpAuthMiddleware } from '../auth/mcp-auth.middleware';
|
|
6
|
+
import { McpInstructionsService } from '../instructions/mcp-instructions.service';
|
|
7
|
+
import { McpSdkServerFactory } from '../sdk/mcp-sdk-server.factory';
|
|
8
|
+
export declare const MCP_REQUEST_SOCKET_TIMEOUT_MS: number;
|
|
9
|
+
export declare class McpHttpEntryService implements OnModuleInit, OnModuleDestroy {
|
|
10
|
+
private readonly adapterHost;
|
|
11
|
+
private readonly authMiddleware;
|
|
12
|
+
private readonly serverFactory;
|
|
13
|
+
private readonly instructionsService;
|
|
14
|
+
private readonly clsContextService;
|
|
15
|
+
private readonly gracefulShutdownService;
|
|
16
|
+
private readonly logger;
|
|
17
|
+
private handler?;
|
|
18
|
+
private handlerClosePromise?;
|
|
19
|
+
constructor(adapterHost: HttpAdapterHost, authMiddleware: McpAuthMiddleware, serverFactory: McpSdkServerFactory, instructionsService: McpInstructionsService, clsContextService: ClsContextService, gracefulShutdownService: GracefulShutdownService);
|
|
20
|
+
onModuleInit(): void;
|
|
21
|
+
onModuleDestroy(): Promise<void>;
|
|
22
|
+
closeTransport(): Promise<void>;
|
|
23
|
+
private handleRequest;
|
|
24
|
+
private isLongLivedSubscription;
|
|
25
|
+
private onTransportError;
|
|
26
|
+
private getRequestedSessionId;
|
|
27
|
+
private isExpectedStandaloneSseRejection;
|
|
28
|
+
private getJsonRpcSummary;
|
|
29
|
+
private toLoggableJsonRpcId;
|
|
30
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var McpHttpEntryService_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.McpHttpEntryService = exports.MCP_REQUEST_SOCKET_TIMEOUT_MS = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const core_1 = require("@nestjs/core");
|
|
16
|
+
const node_crypto_1 = require("node:crypto");
|
|
17
|
+
const server_1 = require("@modelcontextprotocol/server");
|
|
18
|
+
const node_1 = require("@modelcontextprotocol/node");
|
|
19
|
+
const graceful_shutdown_service_1 = require("../../../common/scheduler/services/graceful-shutdown.service");
|
|
20
|
+
const cls_context_service_1 = require("../../../common/logger/cls-context.service");
|
|
21
|
+
const mcp_auth_middleware_1 = require("../auth/mcp-auth.middleware");
|
|
22
|
+
const mcp_auth_middleware_2 = require("../auth/mcp-auth.middleware");
|
|
23
|
+
const http_headers_util_1 = require("../http-headers.util");
|
|
24
|
+
const mcp_instructions_service_1 = require("../instructions/mcp-instructions.service");
|
|
25
|
+
const mcp_log_context_1 = require("../observability/mcp-log-context");
|
|
26
|
+
const mcp_sdk_server_factory_1 = require("../sdk/mcp-sdk-server.factory");
|
|
27
|
+
exports.MCP_REQUEST_SOCKET_TIMEOUT_MS = 4 * 60_000;
|
|
28
|
+
const REQUIRED_MODERN_PROTOCOL_VERSIONS = new Set(['2026-07-28']);
|
|
29
|
+
let McpHttpEntryService = McpHttpEntryService_1 = class McpHttpEntryService {
|
|
30
|
+
adapterHost;
|
|
31
|
+
authMiddleware;
|
|
32
|
+
serverFactory;
|
|
33
|
+
instructionsService;
|
|
34
|
+
clsContextService;
|
|
35
|
+
gracefulShutdownService;
|
|
36
|
+
logger = new common_1.Logger(McpHttpEntryService_1.name);
|
|
37
|
+
handler;
|
|
38
|
+
handlerClosePromise;
|
|
39
|
+
constructor(adapterHost, authMiddleware, serverFactory, instructionsService, clsContextService, gracefulShutdownService) {
|
|
40
|
+
this.adapterHost = adapterHost;
|
|
41
|
+
this.authMiddleware = authMiddleware;
|
|
42
|
+
this.serverFactory = serverFactory;
|
|
43
|
+
this.instructionsService = instructionsService;
|
|
44
|
+
this.clsContextService = clsContextService;
|
|
45
|
+
this.gracefulShutdownService = gracefulShutdownService;
|
|
46
|
+
}
|
|
47
|
+
onModuleInit() {
|
|
48
|
+
if (this.handler) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const express = this.adapterHost.httpAdapter.getInstance();
|
|
52
|
+
this.handler = (0, server_1.createMcpHandler)(({ authInfo }) => this.serverFactory.create((0, mcp_auth_middleware_1.toMcpAuthContext)(authInfo), this.instructionsService.getInstructions()), { onerror: error => this.onTransportError(error) });
|
|
53
|
+
const nodeHandler = (0, node_1.toNodeHandler)(this.handler, {
|
|
54
|
+
onerror: error => this.onTransportError(error),
|
|
55
|
+
});
|
|
56
|
+
express.all('/mcp', this.authMiddleware.handle, (request, response) => this.handleRequest(request, response, nodeHandler));
|
|
57
|
+
}
|
|
58
|
+
async onModuleDestroy() {
|
|
59
|
+
await this.gracefulShutdownService.initiateShutdown();
|
|
60
|
+
await this.closeTransport();
|
|
61
|
+
}
|
|
62
|
+
async closeTransport() {
|
|
63
|
+
const handler = this.handler;
|
|
64
|
+
if (!handler) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this.handlerClosePromise ??= Promise.resolve().then(() => handler.close());
|
|
68
|
+
await this.handlerClosePromise;
|
|
69
|
+
}
|
|
70
|
+
async handleRequest(request, response, nodeHandler) {
|
|
71
|
+
if (typeof request.setTimeout === 'function') {
|
|
72
|
+
request.setTimeout(exports.MCP_REQUEST_SOCKET_TIMEOUT_MS);
|
|
73
|
+
}
|
|
74
|
+
const requestId = (0, node_crypto_1.randomUUID)();
|
|
75
|
+
const requestSessionId = this.getRequestedSessionId(request);
|
|
76
|
+
const mcpContext = (0, mcp_auth_middleware_1.toMcpAuthContext)(request.auth);
|
|
77
|
+
const processId = this.isLongLivedSubscription(request.body) ? undefined : `mcp-${requestId}`;
|
|
78
|
+
if (processId) {
|
|
79
|
+
this.gracefulShutdownService.registerActiveProcess(processId);
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
await this.clsContextService.runWithContext(mcp_log_context_1.MCP_LOG_CONTEXT_KEY, {
|
|
83
|
+
projectId: mcpContext.projectId,
|
|
84
|
+
userId: mcpContext.userId,
|
|
85
|
+
clientId: mcpContext.clientId,
|
|
86
|
+
sessionId: requestSessionId,
|
|
87
|
+
requestId,
|
|
88
|
+
protocolVersion: (0, http_headers_util_1.firstHeaderValue)(request, 'mcp-protocol-version'),
|
|
89
|
+
userAgent: (0, http_headers_util_1.firstHeaderValue)(request, 'user-agent'),
|
|
90
|
+
clientVendor: (0, http_headers_util_1.firstHeaderValue)(request, 'x-anthropic-client'),
|
|
91
|
+
traceparent: (0, http_headers_util_1.firstHeaderValue)(request, 'traceparent'),
|
|
92
|
+
}, async () => {
|
|
93
|
+
const startedAt = Date.now();
|
|
94
|
+
const rpc = this.getJsonRpcSummary(request.body);
|
|
95
|
+
this.logger.debug('MCP request received', {
|
|
96
|
+
method: request.method,
|
|
97
|
+
url: request.originalUrl ?? request.url,
|
|
98
|
+
requestSessionId,
|
|
99
|
+
accept: request.headers?.accept,
|
|
100
|
+
contentType: request.headers?.['content-type'],
|
|
101
|
+
rpc,
|
|
102
|
+
projectId: mcpContext.projectId,
|
|
103
|
+
clientId: mcpContext.clientId,
|
|
104
|
+
});
|
|
105
|
+
if (typeof response.once === 'function') {
|
|
106
|
+
response.once('finish', () => {
|
|
107
|
+
const metadata = {
|
|
108
|
+
statusCode: response.statusCode,
|
|
109
|
+
durationMs: Date.now() - startedAt,
|
|
110
|
+
contentType: response.getHeader('content-type'),
|
|
111
|
+
requestSessionId,
|
|
112
|
+
responseSessionId: response.getHeader('mcp-session-id'),
|
|
113
|
+
rpc,
|
|
114
|
+
projectId: mcpContext.projectId,
|
|
115
|
+
userId: mcpContext.userId,
|
|
116
|
+
clientId: mcpContext.clientId,
|
|
117
|
+
requestId,
|
|
118
|
+
};
|
|
119
|
+
if (response.statusCode >= 400 &&
|
|
120
|
+
!this.isExpectedStandaloneSseRejection(request, response)) {
|
|
121
|
+
this.logger.warn('MCP response finished with error status', metadata);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
this.logger.debug('MCP response finished', metadata);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
await nodeHandler(request, response, request.body);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
if (processId) {
|
|
132
|
+
this.gracefulShutdownService.unregisterActiveProcess(processId);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
isLongLivedSubscription(body) {
|
|
137
|
+
return (!Array.isArray(body) &&
|
|
138
|
+
body !== null &&
|
|
139
|
+
typeof body === 'object' &&
|
|
140
|
+
body.method === 'subscriptions/listen');
|
|
141
|
+
}
|
|
142
|
+
onTransportError(error) {
|
|
143
|
+
const isVersionRejection = server_1.UnsupportedProtocolVersionError.isInstance(error);
|
|
144
|
+
const logContext = this.clsContextService.get(mcp_log_context_1.MCP_LOG_CONTEXT_KEY);
|
|
145
|
+
const metadata = {
|
|
146
|
+
message: error.message,
|
|
147
|
+
requestedProtocolVersion: isVersionRejection ? error.requested : undefined,
|
|
148
|
+
supportedProtocolVersions: isVersionRejection ? error.supported : undefined,
|
|
149
|
+
...logContext,
|
|
150
|
+
};
|
|
151
|
+
if (isVersionRejection && REQUIRED_MODERN_PROTOCOL_VERSIONS.has(error.requested)) {
|
|
152
|
+
this.logger.error('MCP rejected a protocol version it is expected to support', metadata);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.logger.warn('MCP SDK transport error', metadata);
|
|
156
|
+
}
|
|
157
|
+
getRequestedSessionId(request) {
|
|
158
|
+
return (0, http_headers_util_1.firstHeaderValue)(request, 'mcp-session-id');
|
|
159
|
+
}
|
|
160
|
+
isExpectedStandaloneSseRejection(request, response) {
|
|
161
|
+
return request.method === 'GET' && response.statusCode === 405;
|
|
162
|
+
}
|
|
163
|
+
getJsonRpcSummary(body) {
|
|
164
|
+
if (Array.isArray(body)) {
|
|
165
|
+
return body.map(item => this.getJsonRpcSummary(item));
|
|
166
|
+
}
|
|
167
|
+
if (!body || typeof body !== 'object') {
|
|
168
|
+
return typeof body;
|
|
169
|
+
}
|
|
170
|
+
const message = body;
|
|
171
|
+
return {
|
|
172
|
+
id: this.toLoggableJsonRpcId(message.id),
|
|
173
|
+
method: typeof message.method === 'string' ? message.method : undefined,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
toLoggableJsonRpcId(id) {
|
|
177
|
+
if (typeof id === 'string' || typeof id === 'number' || id === null || id === undefined) {
|
|
178
|
+
return id;
|
|
179
|
+
}
|
|
180
|
+
return '<non-scalar>';
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
exports.McpHttpEntryService = McpHttpEntryService;
|
|
184
|
+
exports.McpHttpEntryService = McpHttpEntryService = McpHttpEntryService_1 = __decorate([
|
|
185
|
+
(0, common_1.Injectable)(),
|
|
186
|
+
__metadata("design:paramtypes", [core_1.HttpAdapterHost,
|
|
187
|
+
mcp_auth_middleware_2.McpAuthMiddleware,
|
|
188
|
+
mcp_sdk_server_factory_1.McpSdkServerFactory,
|
|
189
|
+
mcp_instructions_service_1.McpInstructionsService,
|
|
190
|
+
cls_context_service_1.ClsContextService,
|
|
191
|
+
graceful_shutdown_service_1.GracefulShutdownService])
|
|
192
|
+
], McpHttpEntryService);
|
|
193
|
+
//# sourceMappingURL=mcp-http-entry.service.js.map
|
|
@@ -23,6 +23,7 @@ const reject_plugin_auth_decorator_1 = require("../decorators/reject-plugin-auth
|
|
|
23
23
|
const require_plugin_auth_decorator_1 = require("../decorators/require-plugin-auth.decorator");
|
|
24
24
|
const view_only_safe_decorator_1 = require("../decorators/view-only-safe.decorator");
|
|
25
25
|
const plugin_runtime_authorizer_port_1 = require("../ports/plugin-runtime-authorizer.port");
|
|
26
|
+
const role_hierarchy_1 = require("../utils/role-hierarchy");
|
|
26
27
|
exports.AUTH_CONTEXT = 'AuthContext';
|
|
27
28
|
const STATE_CHANGING_METHODS = ['POST', 'PUT', 'PATCH', 'DELETE'];
|
|
28
29
|
let IdpGuard = class IdpGuard {
|
|
@@ -191,14 +192,7 @@ let IdpGuard = class IdpGuard {
|
|
|
191
192
|
if (!request.idpContext?.roles) {
|
|
192
193
|
throw new idp_protocol_1.AuthorizationError('Access denied: No roles information available');
|
|
193
194
|
}
|
|
194
|
-
|
|
195
|
-
viewer: ['viewer', 'editor', 'admin'],
|
|
196
|
-
editor: ['editor', 'admin'],
|
|
197
|
-
admin: ['admin'],
|
|
198
|
-
};
|
|
199
|
-
const acceptableRoles = roleHierarchy[requiredRole];
|
|
200
|
-
const hasRequiredRole = request.idpContext.roles.some(userRole => acceptableRoles.includes(userRole));
|
|
201
|
-
if (!hasRequiredRole) {
|
|
195
|
+
if (!(0, role_hierarchy_1.satisfiesRole)(request.idpContext.roles, requiredRole)) {
|
|
202
196
|
const displayName = IdpGuard_1.ROLE_DISPLAY_NAMES[requiredRole] ?? requiredRole;
|
|
203
197
|
throw new idp_protocol_1.AuthorizationError(`Access denied. Required role: ${displayName}`);
|
|
204
198
|
}
|
|
@@ -15,6 +15,10 @@ export declare class OAuthAuthorizationController {
|
|
|
15
15
|
private readonly logger;
|
|
16
16
|
constructor(validator: OAuthRequestValidator, projectMemberResolver: OAuthProjectMemberResolver, idpProviderService: IdpProviderService, oauthIdp: OAuthIdpPort, clientRegistry: OAuthClientRegistry, projectSelectionService: OAuthProjectSelectionService);
|
|
17
17
|
authorize(query: Record<string, unknown>, request: Request, response: Response): Promise<void>;
|
|
18
|
+
private completeAuthorization;
|
|
19
|
+
private redirectAuthorizationError;
|
|
20
|
+
private toAuthorizationErrorContext;
|
|
21
|
+
private mapAuthorizationError;
|
|
18
22
|
private resolveProjectHostMember;
|
|
19
23
|
private resolveSharedProjectMember;
|
|
20
24
|
private resolveAuthorizationContext;
|
|
@@ -15,6 +15,7 @@ var OAuthAuthorizationController_1;
|
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.OAuthAuthorizationController = void 0;
|
|
17
17
|
const common_1 = require("@nestjs/common");
|
|
18
|
+
const internal_helpers_1 = require("@owox/internal-helpers");
|
|
18
19
|
const idp_protocol_1 = require("@owox/idp-protocol");
|
|
19
20
|
const idp_provider_service_1 = require("../../services/idp-provider.service");
|
|
20
21
|
const oauth_client_registry_1 = require("../oauth-client.registry");
|
|
@@ -39,7 +40,29 @@ let OAuthAuthorizationController = OAuthAuthorizationController_1 = class OAuthA
|
|
|
39
40
|
this.projectSelectionService = projectSelectionService;
|
|
40
41
|
}
|
|
41
42
|
async authorize(query, request, response) {
|
|
42
|
-
|
|
43
|
+
let validated;
|
|
44
|
+
try {
|
|
45
|
+
validated = await this.validator.validateAuthorizationRequest(query);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
const errorContext = await this.validator.resolveAuthorizationErrorContext(query);
|
|
49
|
+
if (!errorContext) {
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
this.redirectAuthorizationError(errorContext, response, error);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
await this.completeAuthorization(query, request, response, validated);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (response.headersSent) {
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
this.redirectAuthorizationError(this.toAuthorizationErrorContext(validated), response, error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async completeAuthorization(query, request, response, validated) {
|
|
43
66
|
const authorizationRequest = validated.request;
|
|
44
67
|
const resourceContext = validated.resourceContext;
|
|
45
68
|
const provider = this.idpProviderService.getProvider(request);
|
|
@@ -63,8 +86,61 @@ let OAuthAuthorizationController = OAuthAuthorizationController_1 = class OAuthA
|
|
|
63
86
|
const redirectUrl = new URL(authorizationRequest.redirectUri);
|
|
64
87
|
redirectUrl.searchParams.set('code', authorizationCode.code);
|
|
65
88
|
redirectUrl.searchParams.set('state', authorizationRequest.state);
|
|
89
|
+
if (resourceContext.kind === 'project') {
|
|
90
|
+
redirectUrl.searchParams.set('iss', resourceContext.publicBaseUrl);
|
|
91
|
+
}
|
|
92
|
+
response.redirect(redirectUrl.toString());
|
|
93
|
+
}
|
|
94
|
+
redirectAuthorizationError(context, response, cause) {
|
|
95
|
+
const oauthError = this.mapAuthorizationError(cause);
|
|
96
|
+
const redirectUrl = new URL(context.redirectUri);
|
|
97
|
+
redirectUrl.searchParams.set('error', oauthError.error);
|
|
98
|
+
redirectUrl.searchParams.set('error_description', oauthError.description);
|
|
99
|
+
if (context.state) {
|
|
100
|
+
redirectUrl.searchParams.set('state', context.state);
|
|
101
|
+
}
|
|
102
|
+
if (context.resourceContext.kind === 'project') {
|
|
103
|
+
redirectUrl.searchParams.set('iss', context.resourceContext.publicBaseUrl);
|
|
104
|
+
}
|
|
105
|
+
const metadata = {
|
|
106
|
+
clientId: context.clientId,
|
|
107
|
+
error: oauthError.error,
|
|
108
|
+
issuer: context.resourceContext.publicBaseUrl,
|
|
109
|
+
};
|
|
110
|
+
if (oauthError.error === 'server_error') {
|
|
111
|
+
this.logger.error('OAuth authorization failed after request validation', (0, internal_helpers_1.castError)(cause).stack, metadata);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
this.logger.warn('OAuth authorization rejected after request validation', metadata);
|
|
115
|
+
}
|
|
66
116
|
response.redirect(redirectUrl.toString());
|
|
67
117
|
}
|
|
118
|
+
toAuthorizationErrorContext(validated) {
|
|
119
|
+
return {
|
|
120
|
+
clientId: validated.request.clientId,
|
|
121
|
+
redirectUri: validated.request.redirectUri,
|
|
122
|
+
state: validated.request.state,
|
|
123
|
+
resourceContext: validated.resourceContext,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
mapAuthorizationError(cause) {
|
|
127
|
+
if (cause instanceof idp_protocol_1.AuthorizationError) {
|
|
128
|
+
return {
|
|
129
|
+
error: 'access_denied',
|
|
130
|
+
description: 'The authorization request was denied.',
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (cause instanceof common_1.BadRequestException) {
|
|
134
|
+
return {
|
|
135
|
+
error: 'invalid_request',
|
|
136
|
+
description: 'The authorization request could not be completed.',
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
error: 'server_error',
|
|
141
|
+
description: 'The authorization server encountered an unexpected condition.',
|
|
142
|
+
};
|
|
143
|
+
}
|
|
68
144
|
resolveProjectHostMember(provider, context, projects, selectedProjectId, projectId) {
|
|
69
145
|
if (selectedProjectId && selectedProjectId !== projectId) {
|
|
70
146
|
throw new common_1.BadRequestException('selected project conflicts with MCP resource');
|
|
@@ -6,6 +6,7 @@ export declare class OAuthMetadataController {
|
|
|
6
6
|
private readonly resourceResolver;
|
|
7
7
|
constructor(config: OAuthConfigService, resourceResolver: McpResourceResolverService);
|
|
8
8
|
getAuthorizationServerMetadata(request?: Request): {
|
|
9
|
+
authorization_response_iss_parameter_supported?: boolean | undefined;
|
|
9
10
|
issuer: string;
|
|
10
11
|
authorization_endpoint: string;
|
|
11
12
|
token_endpoint: string;
|
|
@@ -20,6 +21,7 @@ export declare class OAuthMetadataController {
|
|
|
20
21
|
getOpenIdConfigurationMetadata(request?: Request): {
|
|
21
22
|
subject_types_supported: string[];
|
|
22
23
|
id_token_signing_alg_values_supported: string[];
|
|
24
|
+
authorization_response_iss_parameter_supported?: boolean | undefined;
|
|
23
25
|
issuer: string;
|
|
24
26
|
authorization_endpoint: string;
|
|
25
27
|
token_endpoint: string;
|
|
@@ -32,5 +34,4 @@ export declare class OAuthMetadataController {
|
|
|
32
34
|
token_endpoint_auth_methods_supported: string[];
|
|
33
35
|
};
|
|
34
36
|
private getBaseMetadata;
|
|
35
|
-
private resolveIssuer;
|
|
36
37
|
}
|
|
@@ -44,7 +44,8 @@ let OAuthMetadataController = class OAuthMetadataController {
|
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
46
|
getBaseMetadata(request) {
|
|
47
|
-
const
|
|
47
|
+
const resourceContext = request ? this.resourceResolver.tryResolveRequest(request) : null;
|
|
48
|
+
const issuer = resourceContext?.publicBaseUrl ?? this.config.issuer;
|
|
48
49
|
return {
|
|
49
50
|
issuer,
|
|
50
51
|
authorization_endpoint: this.config.authorizationEndpoint,
|
|
@@ -56,15 +57,11 @@ let OAuthMetadataController = class OAuthMetadataController {
|
|
|
56
57
|
code_challenge_methods_supported: ['S256'],
|
|
57
58
|
scopes_supported: this.config.scopes,
|
|
58
59
|
token_endpoint_auth_methods_supported: ['none'],
|
|
60
|
+
...(resourceContext?.kind === 'project'
|
|
61
|
+
? { authorization_response_iss_parameter_supported: true }
|
|
62
|
+
: {}),
|
|
59
63
|
};
|
|
60
64
|
}
|
|
61
|
-
resolveIssuer(request) {
|
|
62
|
-
if (!request) {
|
|
63
|
-
return this.config.issuer;
|
|
64
|
-
}
|
|
65
|
-
const resourceContext = this.resourceResolver.tryResolveRequest(request);
|
|
66
|
-
return resourceContext?.publicBaseUrl ?? this.config.issuer;
|
|
67
|
-
}
|
|
68
65
|
};
|
|
69
66
|
exports.OAuthMetadataController = OAuthMetadataController;
|
|
70
67
|
__decorate([
|
|
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.OAuthTokenController = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const mcp_resource_resolver_service_1 = require("../../../mcp-resource/mcp-resource-resolver.service");
|
|
18
|
+
const is_authentication_error_1 = require("../../utils/is-authentication-error");
|
|
18
19
|
const oauth_client_registry_1 = require("../oauth-client.registry");
|
|
19
20
|
const oauth_idp_port_1 = require("../oauth-idp.port");
|
|
20
21
|
const oauth_request_validator_1 = require("../oauth-request.validator");
|
|
@@ -33,7 +34,19 @@ let OAuthTokenController = class OAuthTokenController {
|
|
|
33
34
|
const requestResource = this.resourceResolver.tryResolveRequest(request)?.resource;
|
|
34
35
|
const validated = await this.validator.validateTokenRequest(body, requestResource);
|
|
35
36
|
const tokenRequest = validated.request;
|
|
36
|
-
|
|
37
|
+
let result;
|
|
38
|
+
try {
|
|
39
|
+
result = await this.oauthIdp.exchangeToken(tokenRequest);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if ((0, is_authentication_error_1.isAuthenticationError)(error)) {
|
|
43
|
+
throw new common_1.HttpException({
|
|
44
|
+
error: 'invalid_grant',
|
|
45
|
+
error_description: 'The provided authorization grant or refresh token is invalid or expired.',
|
|
46
|
+
}, common_1.HttpStatus.BAD_REQUEST);
|
|
47
|
+
}
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
37
50
|
await this.clientRegistry.markSuccessfulTokenExchange(tokenRequest.clientId);
|
|
38
51
|
return result;
|
|
39
52
|
}
|
|
@@ -8,6 +8,12 @@ export interface ValidatedOAuthAuthorizationRequest {
|
|
|
8
8
|
request: OAuthAuthorizationRequest;
|
|
9
9
|
resourceContext: McpResourceContext;
|
|
10
10
|
}
|
|
11
|
+
export interface OAuthAuthorizationErrorContext {
|
|
12
|
+
clientId: string;
|
|
13
|
+
redirectUri: string;
|
|
14
|
+
state?: string;
|
|
15
|
+
resourceContext: McpResourceContext;
|
|
16
|
+
}
|
|
11
17
|
export interface ValidatedOAuthTokenRequest {
|
|
12
18
|
request: OAuthTokenExchangeRequest;
|
|
13
19
|
resourceContext: McpResourceContext;
|
|
@@ -18,10 +24,12 @@ export declare class OAuthRequestValidator {
|
|
|
18
24
|
private readonly resourceResolver;
|
|
19
25
|
constructor(config: OAuthConfigService, clientRegistry: OAuthClientRegistry, resourceResolver: McpResourceResolverService);
|
|
20
26
|
validateAuthorizationRequest(input: OAuthInput): Promise<ValidatedOAuthAuthorizationRequest>;
|
|
27
|
+
resolveAuthorizationErrorContext(input: OAuthInput): Promise<OAuthAuthorizationErrorContext | null>;
|
|
21
28
|
validateTokenRequest(input: OAuthInput, requestResource?: string): Promise<ValidatedOAuthTokenRequest>;
|
|
22
29
|
private getClient;
|
|
23
30
|
private parseScopes;
|
|
24
31
|
private requiredString;
|
|
32
|
+
private optionalString;
|
|
25
33
|
private resolveClientResource;
|
|
26
34
|
private assertMatchingResource;
|
|
27
35
|
private validateResource;
|
|
@@ -48,6 +48,30 @@ let OAuthRequestValidator = class OAuthRequestValidator {
|
|
|
48
48
|
resourceContext,
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
|
+
async resolveAuthorizationErrorContext(input) {
|
|
52
|
+
const clientId = this.optionalString(input.client_id);
|
|
53
|
+
const redirectUri = this.optionalString(input.redirect_uri);
|
|
54
|
+
if (!clientId || !redirectUri) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const client = await this.clientRegistry.get(clientId);
|
|
58
|
+
if (!client || !client.redirectUris.includes(redirectUri) || !client.resource) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
let resourceContext;
|
|
62
|
+
try {
|
|
63
|
+
resourceContext = this.resourceResolver.resolveResource(client.resource);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
clientId,
|
|
70
|
+
redirectUri,
|
|
71
|
+
state: this.optionalString(input.state),
|
|
72
|
+
resourceContext,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
51
75
|
async validateTokenRequest(input, requestResource) {
|
|
52
76
|
const grantType = this.requiredString(input.grant_type, 'grant_type');
|
|
53
77
|
const clientId = this.requiredString(input.client_id, 'client_id');
|
|
@@ -106,6 +130,9 @@ let OAuthRequestValidator = class OAuthRequestValidator {
|
|
|
106
130
|
}
|
|
107
131
|
return value.trim();
|
|
108
132
|
}
|
|
133
|
+
optionalString(value) {
|
|
134
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
135
|
+
}
|
|
109
136
|
resolveClientResource(client, clientResource, requestResource) {
|
|
110
137
|
if (!client.resource) {
|
|
111
138
|
throw new common_1.BadRequestException('client is not bound to an MCP resource');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isAuthenticationError(err: unknown): err is Error;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAuthenticationError = isAuthenticationError;
|
|
4
|
+
function isAuthenticationError(err) {
|
|
5
|
+
if (!(err instanceof Error))
|
|
6
|
+
return false;
|
|
7
|
+
return err.name === 'AuthenticationException';
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=is-authentication-error.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ROLE_HIERARCHY = void 0;
|
|
4
|
+
exports.satisfiesRole = satisfiesRole;
|
|
5
|
+
exports.ROLE_HIERARCHY = {
|
|
6
|
+
viewer: ['viewer', 'editor', 'admin'],
|
|
7
|
+
editor: ['editor', 'admin'],
|
|
8
|
+
admin: ['admin'],
|
|
9
|
+
};
|
|
10
|
+
function satisfiesRole(roles, requiredRole) {
|
|
11
|
+
const acceptableRoles = exports.ROLE_HIERARCHY[requiredRole];
|
|
12
|
+
return roles.some(role => acceptableRoles.includes(role));
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=role-hierarchy.js.map
|