@wildo-ai/saas-backend-lib 1.0.1
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/esm/__tests__/setup.d.ts +7 -0
- package/dist/esm/__tests__/setup.d.ts.map +1 -0
- package/dist/esm/__tests__/setup.js +14 -0
- package/dist/esm/__tests__/setup.js.map +1 -0
- package/dist/esm/__tests__/test-container.d.ts +39 -0
- package/dist/esm/__tests__/test-container.d.ts.map +1 -0
- package/dist/esm/__tests__/test-container.js +94 -0
- package/dist/esm/__tests__/test-container.js.map +1 -0
- package/dist/esm/applications/models/applications.backend.schemas.d.ts +11 -0
- package/dist/esm/applications/models/applications.backend.schemas.d.ts.map +1 -0
- package/dist/esm/applications/models/applications.backend.schemas.js +15 -0
- package/dist/esm/applications/models/applications.backend.schemas.js.map +1 -0
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.d.ts +12 -0
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.d.ts.map +1 -0
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.js +30 -0
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.js.map +1 -0
- package/dist/esm/base-classes/models/repositories.backend.schemas.d.ts +98 -0
- package/dist/esm/base-classes/models/repositories.backend.schemas.d.ts.map +1 -0
- package/dist/esm/base-classes/models/repositories.backend.schemas.js +11 -0
- package/dist/esm/base-classes/models/repositories.backend.schemas.js.map +1 -0
- package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.d.ts +31 -0
- package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.js +52 -0
- package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.js.map +1 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-custom-execution.service.d.ts +56 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-custom-execution.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-custom-execution.service.js +52 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-custom-execution.service.js.map +1 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-executor.backend.service.d.ts +33 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-executor.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-executor.backend.service.js +125 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-executor.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-resource-execution.backend.service.d.ts +20 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-resource-execution.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-resource-execution.backend.service.js +45 -0
- package/dist/esm/base-classes/services/batches/batches-cronjobs-resource-execution.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/controllers/abstract-controller.backend.service.d.ts +133 -0
- package/dist/esm/base-classes/services/controllers/abstract-controller.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/controllers/abstract-controller.backend.service.js +280 -0
- package/dist/esm/base-classes/services/controllers/abstract-controller.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.d.ts +147 -0
- package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.js +1320 -0
- package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/controllers/controllers-registry-handler.backend.service.d.ts +107 -0
- package/dist/esm/base-classes/services/controllers/controllers-registry-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/controllers/controllers-registry-handler.backend.service.js +369 -0
- package/dist/esm/base-classes/services/controllers/controllers-registry-handler.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/controllers/validate-field-handler.backend.service.d.ts +194 -0
- package/dist/esm/base-classes/services/controllers/validate-field-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/controllers/validate-field-handler.backend.service.js +417 -0
- package/dist/esm/base-classes/services/controllers/validate-field-handler.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/repositories/__tests__/mock-repositories-registry-handler.service.d.ts +9 -0
- package/dist/esm/base-classes/services/repositories/__tests__/mock-repositories-registry-handler.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/repositories/__tests__/mock-repositories-registry-handler.service.js +35 -0
- package/dist/esm/base-classes/services/repositories/__tests__/mock-repositories-registry-handler.service.js.map +1 -0
- package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.d.ts +107 -0
- package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.js +800 -0
- package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.d.ts +181 -0
- package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.js +529 -0
- package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.d.ts +245 -0
- package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.js +1509 -0
- package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/resource-operations-helper.backend.service.d.ts +134 -0
- package/dist/esm/base-classes/services/resource-operations-helper.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/resource-operations-helper.backend.service.js +388 -0
- package/dist/esm/base-classes/services/resource-operations-helper.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/services/__tests__/mock-services-registry-handler.service.d.ts +9 -0
- package/dist/esm/base-classes/services/services/__tests__/mock-services-registry-handler.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/services/__tests__/mock-services-registry-handler.service.js +26 -0
- package/dist/esm/base-classes/services/services/__tests__/mock-services-registry-handler.service.js.map +1 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.d.ts +144 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.js +49 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts +84 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js +156 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts +42 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts.map +1 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js +94 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js.map +1 -0
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts +593 -0
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js +4015 -0
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js.map +1 -0
- package/dist/esm/base-classes/utils/backend-type-utils.d.ts +43 -0
- package/dist/esm/base-classes/utils/backend-type-utils.d.ts.map +1 -0
- package/dist/esm/base-classes/utils/backend-type-utils.js +10 -0
- package/dist/esm/base-classes/utils/backend-type-utils.js.map +1 -0
- package/dist/esm/billing/services/back-office/abstract-billing.backend.service.d.ts +44 -0
- package/dist/esm/billing/services/back-office/abstract-billing.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/back-office/abstract-billing.backend.service.js +94 -0
- package/dist/esm/billing/services/back-office/abstract-billing.backend.service.js.map +1 -0
- package/dist/esm/billing/services/back-office/billing-feature-sync.backend.service.d.ts +102 -0
- package/dist/esm/billing/services/back-office/billing-feature-sync.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/back-office/billing-feature-sync.backend.service.js +405 -0
- package/dist/esm/billing/services/back-office/billing-feature-sync.backend.service.js.map +1 -0
- package/dist/esm/billing/services/back-office/billing-state.backend.service.d.ts +55 -0
- package/dist/esm/billing/services/back-office/billing-state.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/back-office/billing-state.backend.service.js +268 -0
- package/dist/esm/billing/services/back-office/billing-state.backend.service.js.map +1 -0
- package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.d.ts +83 -0
- package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.js +371 -0
- package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.js.map +1 -0
- package/dist/esm/billing/services/back-office/usage-metering.backend.service.d.ts +80 -0
- package/dist/esm/billing/services/back-office/usage-metering.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/back-office/usage-metering.backend.service.js +255 -0
- package/dist/esm/billing/services/back-office/usage-metering.backend.service.js.map +1 -0
- package/dist/esm/billing/services/billing.utils.d.ts +17 -0
- package/dist/esm/billing/services/billing.utils.d.ts.map +1 -0
- package/dist/esm/billing/services/billing.utils.js +25 -0
- package/dist/esm/billing/services/billing.utils.js.map +1 -0
- package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.d.ts +50 -0
- package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.js +290 -0
- package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.d.ts +92 -0
- package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.d.ts.map +1 -0
- package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.js +193 -0
- package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.js.map +1 -0
- package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.d.ts +66 -0
- package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.d.ts.map +1 -0
- package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.js +180 -0
- package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.js.map +1 -0
- package/dist/esm/billing/services/custom-impl/credit-pool.custom-ops.custom-impl.backend.service.d.ts +31 -0
- package/dist/esm/billing/services/custom-impl/credit-pool.custom-ops.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/custom-impl/credit-pool.custom-ops.custom-impl.backend.service.js +100 -0
- package/dist/esm/billing/services/custom-impl/credit-pool.custom-ops.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.d.ts +33 -0
- package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.js +200 -0
- package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.d.ts +58 -0
- package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.js +362 -0
- package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-adapter.backend.service.d.ts +19 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-adapter.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-adapter.backend.service.js +50 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-adapter.backend.service.js.map +1 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-capability-handler.backend.service.d.ts +21 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-capability-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-capability-handler.backend.service.js +32 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-capability-handler.backend.service.js.map +1 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.d.ts +114 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.js +569 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.js.map +1 -0
- package/dist/esm/billing/testing/billing-test-fixtures.d.ts +109 -0
- package/dist/esm/billing/testing/billing-test-fixtures.d.ts.map +1 -0
- package/dist/esm/billing/testing/billing-test-fixtures.js +200 -0
- package/dist/esm/billing/testing/billing-test-fixtures.js.map +1 -0
- package/dist/esm/billing/testing/mock-billing-provider.d.ts +152 -0
- package/dist/esm/billing/testing/mock-billing-provider.d.ts.map +1 -0
- package/dist/esm/billing/testing/mock-billing-provider.js +394 -0
- package/dist/esm/billing/testing/mock-billing-provider.js.map +1 -0
- package/dist/esm/charts/controllers/chart.backend.controller.d.ts +46 -0
- package/dist/esm/charts/controllers/chart.backend.controller.d.ts.map +1 -0
- package/dist/esm/charts/controllers/chart.backend.controller.js +214 -0
- package/dist/esm/charts/controllers/chart.backend.controller.js.map +1 -0
- package/dist/esm/charts/services/chart-registry.backend.service.d.ts +55 -0
- package/dist/esm/charts/services/chart-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/charts/services/chart-registry.backend.service.js +102 -0
- package/dist/esm/charts/services/chart-registry.backend.service.js.map +1 -0
- package/dist/esm/compliance/audit-trails/audit-logs.custom-impl.backend.service.d.ts +9 -0
- package/dist/esm/compliance/audit-trails/audit-logs.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/compliance/audit-trails/audit-logs.custom-impl.backend.service.js +80 -0
- package/dist/esm/compliance/audit-trails/audit-logs.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/compliance/audit-trails/services/__tests__/mock-audit-logs.service.d.ts +23 -0
- package/dist/esm/compliance/audit-trails/services/__tests__/mock-audit-logs.service.d.ts.map +1 -0
- package/dist/esm/compliance/audit-trails/services/__tests__/mock-audit-logs.service.js +46 -0
- package/dist/esm/compliance/audit-trails/services/__tests__/mock-audit-logs.service.js.map +1 -0
- package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.d.ts +73 -0
- package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.d.ts.map +1 -0
- package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.js +291 -0
- package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.js.map +1 -0
- package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.d.ts +447 -0
- package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.d.ts.map +1 -0
- package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.js +898 -0
- package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.js.map +1 -0
- package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.d.ts +127 -0
- package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.d.ts.map +1 -0
- package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.js +462 -0
- package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.js.map +1 -0
- package/dist/esm/compliance/index.d.ts +2 -0
- package/dist/esm/compliance/index.d.ts.map +1 -0
- package/dist/esm/compliance/index.js +1 -0
- package/dist/esm/compliance/index.js.map +1 -0
- package/dist/esm/config/custom/application-config-controller.backend.service.d.ts +31 -0
- package/dist/esm/config/custom/application-config-controller.backend.service.d.ts.map +1 -0
- package/dist/esm/config/custom/application-config-controller.backend.service.js +112 -0
- package/dist/esm/config/custom/application-config-controller.backend.service.js.map +1 -0
- package/dist/esm/config/models/app-config-overrides.backend.definitions.d.ts +29 -0
- package/dist/esm/config/models/app-config-overrides.backend.definitions.d.ts.map +1 -0
- package/dist/esm/config/models/app-config-overrides.backend.definitions.js +143 -0
- package/dist/esm/config/models/app-config-overrides.backend.definitions.js.map +1 -0
- package/dist/esm/config/models/app-config-secrets.backend.schemas.d.ts +56 -0
- package/dist/esm/config/models/app-config-secrets.backend.schemas.d.ts.map +1 -0
- package/dist/esm/config/models/app-config-secrets.backend.schemas.js +121 -0
- package/dist/esm/config/models/app-config-secrets.backend.schemas.js.map +1 -0
- package/dist/esm/config/models/app-config.backend-authored.definitions.d.ts +35 -0
- package/dist/esm/config/models/app-config.backend-authored.definitions.d.ts.map +1 -0
- package/dist/esm/config/models/app-config.backend-authored.definitions.js +89 -0
- package/dist/esm/config/models/app-config.backend-authored.definitions.js.map +1 -0
- package/dist/esm/config/models/app-config.backend.schemas.d.ts +1651 -0
- package/dist/esm/config/models/app-config.backend.schemas.d.ts.map +1 -0
- package/dist/esm/config/models/app-config.backend.schemas.js +478 -0
- package/dist/esm/config/models/app-config.backend.schemas.js.map +1 -0
- package/dist/esm/config/models/app-env-config.backend.schemas.d.ts +74 -0
- package/dist/esm/config/models/app-env-config.backend.schemas.d.ts.map +1 -0
- package/dist/esm/config/models/app-env-config.backend.schemas.js +115 -0
- package/dist/esm/config/models/app-env-config.backend.schemas.js.map +1 -0
- package/dist/esm/config/models/config-mutation-boundary.utils.d.ts +11 -0
- package/dist/esm/config/models/config-mutation-boundary.utils.d.ts.map +1 -0
- package/dist/esm/config/models/config-mutation-boundary.utils.js +50 -0
- package/dist/esm/config/models/config-mutation-boundary.utils.js.map +1 -0
- package/dist/esm/config/models/postgresql-env-config.backend.schemas.d.ts +48 -0
- package/dist/esm/config/models/postgresql-env-config.backend.schemas.d.ts.map +1 -0
- package/dist/esm/config/models/postgresql-env-config.backend.schemas.js +106 -0
- package/dist/esm/config/models/postgresql-env-config.backend.schemas.js.map +1 -0
- package/dist/esm/config/models/runtime-topology.backend.contracts.d.ts +12 -0
- package/dist/esm/config/models/runtime-topology.backend.contracts.d.ts.map +1 -0
- package/dist/esm/config/models/runtime-topology.backend.contracts.js +23 -0
- package/dist/esm/config/models/runtime-topology.backend.contracts.js.map +1 -0
- package/dist/esm/config/services/__tests__/mock-app-configuration.service.d.ts +39 -0
- package/dist/esm/config/services/__tests__/mock-app-configuration.service.d.ts.map +1 -0
- package/dist/esm/config/services/__tests__/mock-app-configuration.service.js +124 -0
- package/dist/esm/config/services/__tests__/mock-app-configuration.service.js.map +1 -0
- package/dist/esm/config/services/app-configuration-loader.backend.service.d.ts +76 -0
- package/dist/esm/config/services/app-configuration-loader.backend.service.d.ts.map +1 -0
- package/dist/esm/config/services/app-configuration-loader.backend.service.js +375 -0
- package/dist/esm/config/services/app-configuration-loader.backend.service.js.map +1 -0
- package/dist/esm/config/services/app-configuration.backend.service.d.ts +148 -0
- package/dist/esm/config/services/app-configuration.backend.service.d.ts.map +1 -0
- package/dist/esm/config/services/app-configuration.backend.service.js +494 -0
- package/dist/esm/config/services/app-configuration.backend.service.js.map +1 -0
- package/dist/esm/config/services/app-configuration.backend.utils.d.ts +17 -0
- package/dist/esm/config/services/app-configuration.backend.utils.d.ts.map +1 -0
- package/dist/esm/config/services/app-configuration.backend.utils.js +61 -0
- package/dist/esm/config/services/app-configuration.backend.utils.js.map +1 -0
- package/dist/esm/config/services/application-startup-config-validator.backend.service.d.ts +70 -0
- package/dist/esm/config/services/application-startup-config-validator.backend.service.d.ts.map +1 -0
- package/dist/esm/config/services/application-startup-config-validator.backend.service.js +470 -0
- package/dist/esm/config/services/application-startup-config-validator.backend.service.js.map +1 -0
- package/dist/esm/databases/models/aggregation.backend.schemas.d.ts +136 -0
- package/dist/esm/databases/models/aggregation.backend.schemas.d.ts.map +1 -0
- package/dist/esm/databases/models/aggregation.backend.schemas.js +9 -0
- package/dist/esm/databases/models/aggregation.backend.schemas.js.map +1 -0
- package/dist/esm/databases/models/databases.backend.schemas.d.ts +32 -0
- package/dist/esm/databases/models/databases.backend.schemas.d.ts.map +1 -0
- package/dist/esm/databases/models/databases.backend.schemas.js +60 -0
- package/dist/esm/databases/models/databases.backend.schemas.js.map +1 -0
- package/dist/esm/databases/models/filter.backend.schemas.d.ts +83 -0
- package/dist/esm/databases/models/filter.backend.schemas.d.ts.map +1 -0
- package/dist/esm/databases/models/filter.backend.schemas.js +27 -0
- package/dist/esm/databases/models/filter.backend.schemas.js.map +1 -0
- package/dist/esm/databases/models/sql.backend.schemas.d.ts +75 -0
- package/dist/esm/databases/models/sql.backend.schemas.d.ts.map +1 -0
- package/dist/esm/databases/models/sql.backend.schemas.js +31 -0
- package/dist/esm/databases/models/sql.backend.schemas.js.map +1 -0
- package/dist/esm/databases/models/transaction.shared.schemas.d.ts +120 -0
- package/dist/esm/databases/models/transaction.shared.schemas.d.ts.map +1 -0
- package/dist/esm/databases/models/transaction.shared.schemas.js +30 -0
- package/dist/esm/databases/models/transaction.shared.schemas.js.map +1 -0
- package/dist/esm/databases/services/__tests__/mock-mongo-transaction-registry.service.d.ts +15 -0
- package/dist/esm/databases/services/__tests__/mock-mongo-transaction-registry.service.d.ts.map +1 -0
- package/dist/esm/databases/services/__tests__/mock-mongo-transaction-registry.service.js +60 -0
- package/dist/esm/databases/services/__tests__/mock-mongo-transaction-registry.service.js.map +1 -0
- package/dist/esm/databases/services/__tests__/mock-mongodb.service.d.ts +19 -0
- package/dist/esm/databases/services/__tests__/mock-mongodb.service.d.ts.map +1 -0
- package/dist/esm/databases/services/__tests__/mock-mongodb.service.js +69 -0
- package/dist/esm/databases/services/__tests__/mock-mongodb.service.js.map +1 -0
- package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.d.ts +11 -0
- package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.d.ts.map +1 -0
- package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.js +315 -0
- package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.js.map +1 -0
- package/dist/esm/databases/services/__tests__/mock-redis.service.d.ts +29 -0
- package/dist/esm/databases/services/__tests__/mock-redis.service.d.ts.map +1 -0
- package/dist/esm/databases/services/__tests__/mock-redis.service.js +65 -0
- package/dist/esm/databases/services/__tests__/mock-redis.service.js.map +1 -0
- package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.d.ts +19 -0
- package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.d.ts.map +1 -0
- package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.js +44 -0
- package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.js.map +1 -0
- package/dist/esm/databases/services/aggregation/aggregation-authorization.backend.service.d.ts +74 -0
- package/dist/esm/databases/services/aggregation/aggregation-authorization.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/aggregation/aggregation-authorization.backend.service.js +369 -0
- package/dist/esm/databases/services/aggregation/aggregation-authorization.backend.service.js.map +1 -0
- package/dist/esm/databases/services/aggregation/aggregation-query.backend.service.d.ts +110 -0
- package/dist/esm/databases/services/aggregation/aggregation-query.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/aggregation/aggregation-query.backend.service.js +444 -0
- package/dist/esm/databases/services/aggregation/aggregation-query.backend.service.js.map +1 -0
- package/dist/esm/databases/services/aggregation/computed-measure-evaluator.backend.service.d.ts +38 -0
- package/dist/esm/databases/services/aggregation/computed-measure-evaluator.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/aggregation/computed-measure-evaluator.backend.service.js +180 -0
- package/dist/esm/databases/services/aggregation/computed-measure-evaluator.backend.service.js.map +1 -0
- package/dist/esm/databases/services/aggregation/field-access-validator.backend.service.d.ts +42 -0
- package/dist/esm/databases/services/aggregation/field-access-validator.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/aggregation/field-access-validator.backend.service.js +183 -0
- package/dist/esm/databases/services/aggregation/field-access-validator.backend.service.js.map +1 -0
- package/dist/esm/databases/services/aggregation/time-series-densifier.backend.service.d.ts +48 -0
- package/dist/esm/databases/services/aggregation/time-series-densifier.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/aggregation/time-series-densifier.backend.service.js +320 -0
- package/dist/esm/databases/services/aggregation/time-series-densifier.backend.service.js.map +1 -0
- package/dist/esm/databases/services/aggregation/topn-processor.backend.service.d.ts +47 -0
- package/dist/esm/databases/services/aggregation/topn-processor.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/aggregation/topn-processor.backend.service.js +187 -0
- package/dist/esm/databases/services/aggregation/topn-processor.backend.service.js.map +1 -0
- package/dist/esm/databases/services/aggregation/window-function-processor.backend.service.d.ts +47 -0
- package/dist/esm/databases/services/aggregation/window-function-processor.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/aggregation/window-function-processor.backend.service.js +250 -0
- package/dist/esm/databases/services/aggregation/window-function-processor.backend.service.js.map +1 -0
- package/dist/esm/databases/services/db-utils.d.ts +56 -0
- package/dist/esm/databases/services/db-utils.d.ts.map +1 -0
- package/dist/esm/databases/services/db-utils.js +66 -0
- package/dist/esm/databases/services/db-utils.js.map +1 -0
- package/dist/esm/databases/services/mongo-aggregation.backend.service.d.ts +91 -0
- package/dist/esm/databases/services/mongo-aggregation.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/mongo-aggregation.backend.service.js +652 -0
- package/dist/esm/databases/services/mongo-aggregation.backend.service.js.map +1 -0
- package/dist/esm/databases/services/mongodb.service.d.ts +132 -0
- package/dist/esm/databases/services/mongodb.service.d.ts.map +1 -0
- package/dist/esm/databases/services/mongodb.service.js +630 -0
- package/dist/esm/databases/services/mongodb.service.js.map +1 -0
- package/dist/esm/databases/services/postgresql-aggregation.backend.service.d.ts +113 -0
- package/dist/esm/databases/services/postgresql-aggregation.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/postgresql-aggregation.backend.service.js +635 -0
- package/dist/esm/databases/services/postgresql-aggregation.backend.service.js.map +1 -0
- package/dist/esm/databases/services/postgresql-database.backend.service.d.ts +75 -0
- package/dist/esm/databases/services/postgresql-database.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/postgresql-database.backend.service.js +255 -0
- package/dist/esm/databases/services/postgresql-database.backend.service.js.map +1 -0
- package/dist/esm/databases/services/postgresql-filter.backend.service.d.ts +116 -0
- package/dist/esm/databases/services/postgresql-filter.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/postgresql-filter.backend.service.js +624 -0
- package/dist/esm/databases/services/postgresql-filter.backend.service.js.map +1 -0
- package/dist/esm/databases/services/redis.service.d.ts +143 -0
- package/dist/esm/databases/services/redis.service.d.ts.map +1 -0
- package/dist/esm/databases/services/redis.service.js +429 -0
- package/dist/esm/databases/services/redis.service.js.map +1 -0
- package/dist/esm/databases/services/zod-to-mongoose-schema-convertor.backend.service.d.ts +302 -0
- package/dist/esm/databases/services/zod-to-mongoose-schema-convertor.backend.service.d.ts.map +1 -0
- package/dist/esm/databases/services/zod-to-mongoose-schema-convertor.backend.service.js +1787 -0
- package/dist/esm/databases/services/zod-to-mongoose-schema-convertor.backend.service.js.map +1 -0
- package/dist/esm/databases/services/zod-to-sql-hybrid-schema.planner.d.ts +65 -0
- package/dist/esm/databases/services/zod-to-sql-hybrid-schema.planner.d.ts.map +1 -0
- package/dist/esm/databases/services/zod-to-sql-hybrid-schema.planner.js +237 -0
- package/dist/esm/databases/services/zod-to-sql-hybrid-schema.planner.js.map +1 -0
- package/dist/esm/errors/services/__tests__/mock-error-builder.service.d.ts +339 -0
- package/dist/esm/errors/services/__tests__/mock-error-builder.service.d.ts.map +1 -0
- package/dist/esm/errors/services/__tests__/mock-error-builder.service.js +209 -0
- package/dist/esm/errors/services/__tests__/mock-error-builder.service.js.map +1 -0
- package/dist/esm/errors/services/error-builder.backend.service.d.ts +95 -0
- package/dist/esm/errors/services/error-builder.backend.service.d.ts.map +1 -0
- package/dist/esm/errors/services/error-builder.backend.service.js +334 -0
- package/dist/esm/errors/services/error-builder.backend.service.js.map +1 -0
- package/dist/esm/errors/services/error-handler.backend.service.d.ts +43 -0
- package/dist/esm/errors/services/error-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/errors/services/error-handler.backend.service.js +219 -0
- package/dist/esm/errors/services/error-handler.backend.service.js.map +1 -0
- package/dist/esm/errors/services/rate-limit.backend.service.d.ts +23 -0
- package/dist/esm/errors/services/rate-limit.backend.service.d.ts.map +1 -0
- package/dist/esm/errors/services/rate-limit.backend.service.js +59 -0
- package/dist/esm/errors/services/rate-limit.backend.service.js.map +1 -0
- package/dist/esm/external-providers/models/external-providers.backend.schemas.d.ts +135 -0
- package/dist/esm/external-providers/models/external-providers.backend.schemas.d.ts.map +1 -0
- package/dist/esm/external-providers/models/external-providers.backend.schemas.js +129 -0
- package/dist/esm/external-providers/models/external-providers.backend.schemas.js.map +1 -0
- package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.d.ts +18 -0
- package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.d.ts.map +1 -0
- package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.js +38 -0
- package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.js.map +1 -0
- package/dist/esm/external-providers/services/__tests__/mock-lazy-provider-registry.service.d.ts +20 -0
- package/dist/esm/external-providers/services/__tests__/mock-lazy-provider-registry.service.d.ts.map +1 -0
- package/dist/esm/external-providers/services/__tests__/mock-lazy-provider-registry.service.js +44 -0
- package/dist/esm/external-providers/services/__tests__/mock-lazy-provider-registry.service.js.map +1 -0
- package/dist/esm/external-providers/services/external-api-handler.backend.service.d.ts +9 -0
- package/dist/esm/external-providers/services/external-api-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/external-providers/services/external-api-handler.backend.service.js +36 -0
- package/dist/esm/external-providers/services/external-api-handler.backend.service.js.map +1 -0
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +83 -0
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +422 -0
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -0
- package/dist/esm/external-providers/services/feature-bindings.backend.service.d.ts +102 -0
- package/dist/esm/external-providers/services/feature-bindings.backend.service.d.ts.map +1 -0
- package/dist/esm/external-providers/services/feature-bindings.backend.service.js +352 -0
- package/dist/esm/external-providers/services/feature-bindings.backend.service.js.map +1 -0
- package/dist/esm/external-providers/services/lazy-provider-registry.backend.service.d.ts +141 -0
- package/dist/esm/external-providers/services/lazy-provider-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/external-providers/services/lazy-provider-registry.backend.service.js +391 -0
- package/dist/esm/external-providers/services/lazy-provider-registry.backend.service.js.map +1 -0
- package/dist/esm/features/controllers/features.backend.controller.d.ts +35 -0
- package/dist/esm/features/controllers/features.backend.controller.d.ts.map +1 -0
- package/dist/esm/features/controllers/features.backend.controller.js +179 -0
- package/dist/esm/features/controllers/features.backend.controller.js.map +1 -0
- package/dist/esm/features/services/__tests__/mock-capability-bindings.service.d.ts +8 -0
- package/dist/esm/features/services/__tests__/mock-capability-bindings.service.d.ts.map +1 -0
- package/dist/esm/features/services/__tests__/mock-capability-bindings.service.js +31 -0
- package/dist/esm/features/services/__tests__/mock-capability-bindings.service.js.map +1 -0
- package/dist/esm/features/services/__tests__/mock-feature-definition-registry.service.d.ts +22 -0
- package/dist/esm/features/services/__tests__/mock-feature-definition-registry.service.d.ts.map +1 -0
- package/dist/esm/features/services/__tests__/mock-feature-definition-registry.service.js +52 -0
- package/dist/esm/features/services/__tests__/mock-feature-definition-registry.service.js.map +1 -0
- package/dist/esm/features/services/__tests__/mock-feature-resolution.service.d.ts +13 -0
- package/dist/esm/features/services/__tests__/mock-feature-resolution.service.d.ts.map +1 -0
- package/dist/esm/features/services/__tests__/mock-feature-resolution.service.js +36 -0
- package/dist/esm/features/services/__tests__/mock-feature-resolution.service.js.map +1 -0
- package/dist/esm/features/services/feature-definition-registry.backend.service.d.ts +111 -0
- package/dist/esm/features/services/feature-definition-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/features/services/feature-definition-registry.backend.service.js +437 -0
- package/dist/esm/features/services/feature-definition-registry.backend.service.js.map +1 -0
- package/dist/esm/features/services/feature-gate.backend.service.d.ts +110 -0
- package/dist/esm/features/services/feature-gate.backend.service.d.ts.map +1 -0
- package/dist/esm/features/services/feature-gate.backend.service.js +414 -0
- package/dist/esm/features/services/feature-gate.backend.service.js.map +1 -0
- package/dist/esm/features/services/feature-resolution.backend.service.d.ts +163 -0
- package/dist/esm/features/services/feature-resolution.backend.service.d.ts.map +1 -0
- package/dist/esm/features/services/feature-resolution.backend.service.js +550 -0
- package/dist/esm/features/services/feature-resolution.backend.service.js.map +1 -0
- package/dist/esm/features/testing/feature-test-utils.d.ts +85 -0
- package/dist/esm/features/testing/feature-test-utils.d.ts.map +1 -0
- package/dist/esm/features/testing/feature-test-utils.js +127 -0
- package/dist/esm/features/testing/feature-test-utils.js.map +1 -0
- package/dist/esm/files/batches/files-cleanup.batch.backend.service.d.ts +34 -0
- package/dist/esm/files/batches/files-cleanup.batch.backend.service.d.ts.map +1 -0
- package/dist/esm/files/batches/files-cleanup.batch.backend.service.js +226 -0
- package/dist/esm/files/batches/files-cleanup.batch.backend.service.js.map +1 -0
- package/dist/esm/files/constraints/file-analyzers.types.d.ts +76 -0
- package/dist/esm/files/constraints/file-analyzers.types.d.ts.map +1 -0
- package/dist/esm/files/constraints/file-analyzers.types.js +16 -0
- package/dist/esm/files/constraints/file-analyzers.types.js.map +1 -0
- package/dist/esm/files/constraints/file-constraint-resolver-chain.backend.service.d.ts +38 -0
- package/dist/esm/files/constraints/file-constraint-resolver-chain.backend.service.d.ts.map +1 -0
- package/dist/esm/files/constraints/file-constraint-resolver-chain.backend.service.js +99 -0
- package/dist/esm/files/constraints/file-constraint-resolver-chain.backend.service.js.map +1 -0
- package/dist/esm/files/constraints/file-constraint.types.d.ts +77 -0
- package/dist/esm/files/constraints/file-constraint.types.d.ts.map +1 -0
- package/dist/esm/files/constraints/file-constraint.types.js +16 -0
- package/dist/esm/files/constraints/file-constraint.types.js.map +1 -0
- package/dist/esm/files/constraints/file-validation.backend.service.d.ts +63 -0
- package/dist/esm/files/constraints/file-validation.backend.service.d.ts.map +1 -0
- package/dist/esm/files/constraints/file-validation.backend.service.js +317 -0
- package/dist/esm/files/constraints/file-validation.backend.service.js.map +1 -0
- package/dist/esm/files/constraints/resource-field-constraint-resolver.backend.service.d.ts +33 -0
- package/dist/esm/files/constraints/resource-field-constraint-resolver.backend.service.d.ts.map +1 -0
- package/dist/esm/files/constraints/resource-field-constraint-resolver.backend.service.js +126 -0
- package/dist/esm/files/constraints/resource-field-constraint-resolver.backend.service.js.map +1 -0
- package/dist/esm/files/controllers/file.controller.d.ts +145 -0
- package/dist/esm/files/controllers/file.controller.d.ts.map +1 -0
- package/dist/esm/files/controllers/file.controller.js +806 -0
- package/dist/esm/files/controllers/file.controller.js.map +1 -0
- package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.d.ts +85 -0
- package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.js +512 -0
- package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.js.map +1 -0
- package/dist/esm/files/rag/weaviate-vector-store.backend.service.d.ts +84 -0
- package/dist/esm/files/rag/weaviate-vector-store.backend.service.d.ts.map +1 -0
- package/dist/esm/files/rag/weaviate-vector-store.backend.service.js +224 -0
- package/dist/esm/files/rag/weaviate-vector-store.backend.service.js.map +1 -0
- package/dist/esm/files/scanning/clamav-scanner.backend.service.d.ts +55 -0
- package/dist/esm/files/scanning/clamav-scanner.backend.service.d.ts.map +1 -0
- package/dist/esm/files/scanning/clamav-scanner.backend.service.js +202 -0
- package/dist/esm/files/scanning/clamav-scanner.backend.service.js.map +1 -0
- package/dist/esm/files/scanning/file-scan.types.d.ts +17 -0
- package/dist/esm/files/scanning/file-scan.types.d.ts.map +1 -0
- package/dist/esm/files/scanning/file-scan.types.js +7 -0
- package/dist/esm/files/scanning/file-scan.types.js.map +1 -0
- package/dist/esm/files/scanning/yara-scanner.backend.service.d.ts +73 -0
- package/dist/esm/files/scanning/yara-scanner.backend.service.d.ts.map +1 -0
- package/dist/esm/files/scanning/yara-scanner.backend.service.js +184 -0
- package/dist/esm/files/scanning/yara-scanner.backend.service.js.map +1 -0
- package/dist/esm/files/services/__tests__/mock-file-field-detection.service.d.ts +12 -0
- package/dist/esm/files/services/__tests__/mock-file-field-detection.service.d.ts.map +1 -0
- package/dist/esm/files/services/__tests__/mock-file-field-detection.service.js +41 -0
- package/dist/esm/files/services/__tests__/mock-file-field-detection.service.js.map +1 -0
- package/dist/esm/files/services/__tests__/mock-file-operation-handler.service.d.ts +33 -0
- package/dist/esm/files/services/__tests__/mock-file-operation-handler.service.d.ts.map +1 -0
- package/dist/esm/files/services/__tests__/mock-file-operation-handler.service.js +71 -0
- package/dist/esm/files/services/__tests__/mock-file-operation-handler.service.js.map +1 -0
- package/dist/esm/files/services/__tests__/mock-file-repository.service.d.ts +16 -0
- package/dist/esm/files/services/__tests__/mock-file-repository.service.d.ts.map +1 -0
- package/dist/esm/files/services/__tests__/mock-file-repository.service.js +95 -0
- package/dist/esm/files/services/__tests__/mock-file-repository.service.js.map +1 -0
- package/dist/esm/files/services/file-field-detection.backend.service.d.ts +57 -0
- package/dist/esm/files/services/file-field-detection.backend.service.d.ts.map +1 -0
- package/dist/esm/files/services/file-field-detection.backend.service.js +145 -0
- package/dist/esm/files/services/file-field-detection.backend.service.js.map +1 -0
- package/dist/esm/files/services/file-operation-handler.backend.service.d.ts +103 -0
- package/dist/esm/files/services/file-operation-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/files/services/file-operation-handler.backend.service.js +604 -0
- package/dist/esm/files/services/file-operation-handler.backend.service.js.map +1 -0
- package/dist/esm/files/services/file-population.backend.service.d.ts +73 -0
- package/dist/esm/files/services/file-population.backend.service.d.ts.map +1 -0
- package/dist/esm/files/services/file-population.backend.service.js +367 -0
- package/dist/esm/files/services/file-population.backend.service.js.map +1 -0
- package/dist/esm/files/services/file-rag-indexing.backend.service.d.ts +64 -0
- package/dist/esm/files/services/file-rag-indexing.backend.service.d.ts.map +1 -0
- package/dist/esm/files/services/file-rag-indexing.backend.service.js +188 -0
- package/dist/esm/files/services/file-rag-indexing.backend.service.js.map +1 -0
- package/dist/esm/files/services/file-scanning.backend.service.d.ts +97 -0
- package/dist/esm/files/services/file-scanning.backend.service.d.ts.map +1 -0
- package/dist/esm/files/services/file-scanning.backend.service.js +323 -0
- package/dist/esm/files/services/file-scanning.backend.service.js.map +1 -0
- package/dist/esm/files/services/file-text-extraction.backend.service.d.ts +52 -0
- package/dist/esm/files/services/file-text-extraction.backend.service.d.ts.map +1 -0
- package/dist/esm/files/services/file-text-extraction.backend.service.js +168 -0
- package/dist/esm/files/services/file-text-extraction.backend.service.js.map +1 -0
- package/dist/esm/files/services/files.backend.service.d.ts +235 -0
- package/dist/esm/files/services/files.backend.service.d.ts.map +1 -0
- package/dist/esm/files/services/files.backend.service.js +987 -0
- package/dist/esm/files/services/files.backend.service.js.map +1 -0
- package/dist/esm/files/storage/file-storage-path-resolver.backend.service.d.ts +50 -0
- package/dist/esm/files/storage/file-storage-path-resolver.backend.service.d.ts.map +1 -0
- package/dist/esm/files/storage/file-storage-path-resolver.backend.service.js +253 -0
- package/dist/esm/files/storage/file-storage-path-resolver.backend.service.js.map +1 -0
- package/dist/esm/files/storage/file-storage-provider.types.d.ts +156 -0
- package/dist/esm/files/storage/file-storage-provider.types.d.ts.map +1 -0
- package/dist/esm/files/storage/file-storage-provider.types.js +10 -0
- package/dist/esm/files/storage/file-storage-provider.types.js.map +1 -0
- package/dist/esm/files/storage/file-storage-router.backend.service.d.ts +68 -0
- package/dist/esm/files/storage/file-storage-router.backend.service.d.ts.map +1 -0
- package/dist/esm/files/storage/file-storage-router.backend.service.js +168 -0
- package/dist/esm/files/storage/file-storage-router.backend.service.js.map +1 -0
- package/dist/esm/files/storage/local-directory-storage-provider.backend.service.d.ts +57 -0
- package/dist/esm/files/storage/local-directory-storage-provider.backend.service.d.ts.map +1 -0
- package/dist/esm/files/storage/local-directory-storage-provider.backend.service.js +307 -0
- package/dist/esm/files/storage/local-directory-storage-provider.backend.service.js.map +1 -0
- package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.d.ts +41 -0
- package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.d.ts.map +1 -0
- package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.js +397 -0
- package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.js.map +1 -0
- package/dist/esm/files/utils/file-field-schema-path.backend.utils.d.ts +30 -0
- package/dist/esm/files/utils/file-field-schema-path.backend.utils.d.ts.map +1 -0
- package/dist/esm/files/utils/file-field-schema-path.backend.utils.js +251 -0
- package/dist/esm/files/utils/file-field-schema-path.backend.utils.js.map +1 -0
- package/dist/esm/files/utils/file-upload.utils.d.ts +74 -0
- package/dist/esm/files/utils/file-upload.utils.d.ts.map +1 -0
- package/dist/esm/files/utils/file-upload.utils.js +116 -0
- package/dist/esm/files/utils/file-upload.utils.js.map +1 -0
- package/dist/esm/files/utils/file-uploader.utils.d.ts +15 -0
- package/dist/esm/files/utils/file-uploader.utils.d.ts.map +1 -0
- package/dist/esm/files/utils/file-uploader.utils.js +47 -0
- package/dist/esm/files/utils/file-uploader.utils.js.map +1 -0
- package/dist/esm/files/utils/file-validation.utils.d.ts +111 -0
- package/dist/esm/files/utils/file-validation.utils.d.ts.map +1 -0
- package/dist/esm/files/utils/file-validation.utils.js +516 -0
- package/dist/esm/files/utils/file-validation.utils.js.map +1 -0
- package/dist/esm/flows-actors/agent-catalogs.backend.d.ts +222 -0
- package/dist/esm/flows-actors/agent-catalogs.backend.d.ts.map +1 -0
- package/dist/esm/flows-actors/agent-catalogs.backend.js +320 -0
- package/dist/esm/flows-actors/agent-catalogs.backend.js.map +1 -0
- package/dist/esm/flows-actors/controllers/flows-actors.controller.d.ts +33 -0
- package/dist/esm/flows-actors/controllers/flows-actors.controller.d.ts.map +1 -0
- package/dist/esm/flows-actors/controllers/flows-actors.controller.js +96 -0
- package/dist/esm/flows-actors/controllers/flows-actors.controller.js.map +1 -0
- package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.d.ts +225 -0
- package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.d.ts.map +1 -0
- package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.js +323 -0
- package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.js.map +1 -0
- package/dist/esm/flows-actors/models/agent-facets.backend.definitions.d.ts +77 -0
- package/dist/esm/flows-actors/models/agent-facets.backend.definitions.d.ts.map +1 -0
- package/dist/esm/flows-actors/models/agent-facets.backend.definitions.js +28 -0
- package/dist/esm/flows-actors/models/agent-facets.backend.definitions.js.map +1 -0
- package/dist/esm/flows-actors/models/agents.backend.definitions.d.ts +1 -0
- package/dist/esm/flows-actors/models/agents.backend.definitions.d.ts.map +1 -0
- package/dist/esm/flows-actors/models/agents.backend.definitions.js +1 -0
- package/dist/esm/flows-actors/models/agents.backend.definitions.js.map +1 -0
- package/dist/esm/flows-actors/models/core-facets.backend.definitions.d.ts +52 -0
- package/dist/esm/flows-actors/models/core-facets.backend.definitions.d.ts.map +1 -0
- package/dist/esm/flows-actors/models/core-facets.backend.definitions.js +307 -0
- package/dist/esm/flows-actors/models/core-facets.backend.definitions.js.map +1 -0
- package/dist/esm/flows-actors/models/flows-actors.backend.definitions.d.ts +7 -0
- package/dist/esm/flows-actors/models/flows-actors.backend.definitions.d.ts.map +1 -0
- package/dist/esm/flows-actors/models/flows-actors.backend.definitions.js +8 -0
- package/dist/esm/flows-actors/models/flows-actors.backend.definitions.js.map +1 -0
- package/dist/esm/flows-actors/models/flows-actors.backend.schemas.d.ts +30 -0
- package/dist/esm/flows-actors/models/flows-actors.backend.schemas.d.ts.map +1 -0
- package/dist/esm/flows-actors/models/flows-actors.backend.schemas.js +7 -0
- package/dist/esm/flows-actors/models/flows-actors.backend.schemas.js.map +1 -0
- package/dist/esm/flows-actors/services/actors-system.backend.service.d.ts +72 -0
- package/dist/esm/flows-actors/services/actors-system.backend.service.d.ts.map +1 -0
- package/dist/esm/flows-actors/services/actors-system.backend.service.js +229 -0
- package/dist/esm/flows-actors/services/actors-system.backend.service.js.map +1 -0
- package/dist/esm/flows-actors/services/agent-facets.backend.service.d.ts +95 -0
- package/dist/esm/flows-actors/services/agent-facets.backend.service.d.ts.map +1 -0
- package/dist/esm/flows-actors/services/agent-facets.backend.service.js +276 -0
- package/dist/esm/flows-actors/services/agent-facets.backend.service.js.map +1 -0
- package/dist/esm/flows-actors/services/agents.backend.service.d.ts +183 -0
- package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -0
- package/dist/esm/flows-actors/services/agents.backend.service.js +2095 -0
- package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -0
- package/dist/esm/flows-actors/services/context-curation.backend.service.d.ts +64 -0
- package/dist/esm/flows-actors/services/context-curation.backend.service.d.ts.map +1 -0
- package/dist/esm/flows-actors/services/context-curation.backend.service.js +180 -0
- package/dist/esm/flows-actors/services/context-curation.backend.service.js.map +1 -0
- package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts +101 -0
- package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts.map +1 -0
- package/dist/esm/flows-actors/services/flows-actors-registry.service.js +313 -0
- package/dist/esm/flows-actors/services/flows-actors-registry.service.js.map +1 -0
- package/dist/esm/flows-actors/services/flows.backend.services.d.ts +64 -0
- package/dist/esm/flows-actors/services/flows.backend.services.d.ts.map +1 -0
- package/dist/esm/flows-actors/services/flows.backend.services.js +203 -0
- package/dist/esm/flows-actors/services/flows.backend.services.js.map +1 -0
- package/dist/esm/flows-actors/services/prompt-compiler.backend.service.d.ts +91 -0
- package/dist/esm/flows-actors/services/prompt-compiler.backend.service.d.ts.map +1 -0
- package/dist/esm/flows-actors/services/prompt-compiler.backend.service.js +629 -0
- package/dist/esm/flows-actors/services/prompt-compiler.backend.service.js.map +1 -0
- package/dist/esm/flows-actors/utils/cli-runtime-operation-support.backend.utils.d.ts +15 -0
- package/dist/esm/flows-actors/utils/cli-runtime-operation-support.backend.utils.d.ts.map +1 -0
- package/dist/esm/flows-actors/utils/cli-runtime-operation-support.backend.utils.js +55 -0
- package/dist/esm/flows-actors/utils/cli-runtime-operation-support.backend.utils.js.map +1 -0
- package/dist/esm/flows-actors/utils/cli-runtime-runner.backend.utils.d.ts +22 -0
- package/dist/esm/flows-actors/utils/cli-runtime-runner.backend.utils.d.ts.map +1 -0
- package/dist/esm/flows-actors/utils/cli-runtime-runner.backend.utils.js +131 -0
- package/dist/esm/flows-actors/utils/cli-runtime-runner.backend.utils.js.map +1 -0
- package/dist/esm/flows-actors/utils/flows-actors-frontend-extractor.utils.d.ts +15 -0
- package/dist/esm/flows-actors/utils/flows-actors-frontend-extractor.utils.d.ts.map +1 -0
- package/dist/esm/flows-actors/utils/flows-actors-frontend-extractor.utils.js +43 -0
- package/dist/esm/flows-actors/utils/flows-actors-frontend-extractor.utils.js.map +1 -0
- package/dist/esm/flows-actors/utils/prompt-ir-adapters.backend.utils.d.ts +66 -0
- package/dist/esm/flows-actors/utils/prompt-ir-adapters.backend.utils.d.ts.map +1 -0
- package/dist/esm/flows-actors/utils/prompt-ir-adapters.backend.utils.js +219 -0
- package/dist/esm/flows-actors/utils/prompt-ir-adapters.backend.utils.js.map +1 -0
- package/dist/esm/guidance/batches/dormancy-detection.batch.backend.service.d.ts +17 -0
- package/dist/esm/guidance/batches/dormancy-detection.batch.backend.service.d.ts.map +1 -0
- package/dist/esm/guidance/batches/dormancy-detection.batch.backend.service.js +110 -0
- package/dist/esm/guidance/batches/dormancy-detection.batch.backend.service.js.map +1 -0
- package/dist/esm/guidance/services/guidance-trigger-evaluator.backend.service.d.ts +41 -0
- package/dist/esm/guidance/services/guidance-trigger-evaluator.backend.service.d.ts.map +1 -0
- package/dist/esm/guidance/services/guidance-trigger-evaluator.backend.service.js +135 -0
- package/dist/esm/guidance/services/guidance-trigger-evaluator.backend.service.js.map +1 -0
- package/dist/esm/guidance/services/lifecycle-custom-implementations.backend.d.ts +33 -0
- package/dist/esm/guidance/services/lifecycle-custom-implementations.backend.d.ts.map +1 -0
- package/dist/esm/guidance/services/lifecycle-custom-implementations.backend.js +105 -0
- package/dist/esm/guidance/services/lifecycle-custom-implementations.backend.js.map +1 -0
- package/dist/esm/guidance/services/lifecycle-evaluator.backend.service.d.ts +103 -0
- package/dist/esm/guidance/services/lifecycle-evaluator.backend.service.d.ts.map +1 -0
- package/dist/esm/guidance/services/lifecycle-evaluator.backend.service.js +685 -0
- package/dist/esm/guidance/services/lifecycle-evaluator.backend.service.js.map +1 -0
- package/dist/esm/guidance/services/milestone-condition-registry.backend.service.d.ts +23 -0
- package/dist/esm/guidance/services/milestone-condition-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/guidance/services/milestone-condition-registry.backend.service.js +57 -0
- package/dist/esm/guidance/services/milestone-condition-registry.backend.service.js.map +1 -0
- package/dist/esm/guidance/services/milestone-definition-registry.backend.service.d.ts +49 -0
- package/dist/esm/guidance/services/milestone-definition-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/guidance/services/milestone-definition-registry.backend.service.js +248 -0
- package/dist/esm/guidance/services/milestone-definition-registry.backend.service.js.map +1 -0
- package/dist/esm/guidance/services/milestone-evaluator.backend.service.d.ts +64 -0
- package/dist/esm/guidance/services/milestone-evaluator.backend.service.d.ts.map +1 -0
- package/dist/esm/guidance/services/milestone-evaluator.backend.service.js +487 -0
- package/dist/esm/guidance/services/milestone-evaluator.backend.service.js.map +1 -0
- package/dist/esm/i18n/controllers/i18n-controller.backend.service.d.ts +55 -0
- package/dist/esm/i18n/controllers/i18n-controller.backend.service.d.ts.map +1 -0
- package/dist/esm/i18n/controllers/i18n-controller.backend.service.js +208 -0
- package/dist/esm/i18n/controllers/i18n-controller.backend.service.js.map +1 -0
- package/dist/esm/i18n/services/i18n.backend.service.d.ts +43 -0
- package/dist/esm/i18n/services/i18n.backend.service.d.ts.map +1 -0
- package/dist/esm/i18n/services/i18n.backend.service.js +83 -0
- package/dist/esm/i18n/services/i18n.backend.service.js.map +1 -0
- package/dist/esm/index.d.ts +203 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +239 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/inject/models/container.d.ts +44 -0
- package/dist/esm/inject/models/container.d.ts.map +1 -0
- package/dist/esm/inject/models/container.js +489 -0
- package/dist/esm/inject/models/container.js.map +1 -0
- package/dist/esm/inject/models/service-types.d.ts +198 -0
- package/dist/esm/inject/models/service-types.d.ts.map +1 -0
- package/dist/esm/inject/models/service-types.js +226 -0
- package/dist/esm/inject/models/service-types.js.map +1 -0
- package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.d.ts +34 -0
- package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.d.ts.map +1 -0
- package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.js +122 -0
- package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.js.map +1 -0
- package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.d.ts +41 -0
- package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.d.ts.map +1 -0
- package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.js +62 -0
- package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.js.map +1 -0
- package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.d.ts +18 -0
- package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.js +43 -0
- package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.js.map +1 -0
- package/dist/esm/monitoring/logger/middleware/logging.middleware.d.ts +12 -0
- package/dist/esm/monitoring/logger/middleware/logging.middleware.d.ts.map +1 -0
- package/dist/esm/monitoring/logger/middleware/logging.middleware.js +25 -0
- package/dist/esm/monitoring/logger/middleware/logging.middleware.js.map +1 -0
- package/dist/esm/monitoring/logger/models/logger.backend.schemas.d.ts +41 -0
- package/dist/esm/monitoring/logger/models/logger.backend.schemas.d.ts.map +1 -0
- package/dist/esm/monitoring/logger/models/logger.backend.schemas.js +29 -0
- package/dist/esm/monitoring/logger/models/logger.backend.schemas.js.map +1 -0
- package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.d.ts +22 -0
- package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.d.ts.map +1 -0
- package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.js +53 -0
- package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.js.map +1 -0
- package/dist/esm/monitoring/logger/services/logger.service.d.ts +37 -0
- package/dist/esm/monitoring/logger/services/logger.service.d.ts.map +1 -0
- package/dist/esm/monitoring/logger/services/logger.service.js +189 -0
- package/dist/esm/monitoring/logger/services/logger.service.js.map +1 -0
- package/dist/esm/monitoring/observability/middleware/metrics.middleware.d.ts +38 -0
- package/dist/esm/monitoring/observability/middleware/metrics.middleware.d.ts.map +1 -0
- package/dist/esm/monitoring/observability/middleware/metrics.middleware.js +147 -0
- package/dist/esm/monitoring/observability/middleware/metrics.middleware.js.map +1 -0
- package/dist/esm/monitoring/observability/middleware/telemetry.middleware.d.ts +26 -0
- package/dist/esm/monitoring/observability/middleware/telemetry.middleware.d.ts.map +1 -0
- package/dist/esm/monitoring/observability/middleware/telemetry.middleware.js +117 -0
- package/dist/esm/monitoring/observability/middleware/telemetry.middleware.js.map +1 -0
- package/dist/esm/monitoring/observability/middleware/tracing.middleware.d.ts +28 -0
- package/dist/esm/monitoring/observability/middleware/tracing.middleware.d.ts.map +1 -0
- package/dist/esm/monitoring/observability/middleware/tracing.middleware.js +182 -0
- package/dist/esm/monitoring/observability/middleware/tracing.middleware.js.map +1 -0
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts +86 -0
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts.map +1 -0
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.js +1 -0
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.js.map +1 -0
- package/dist/esm/monitoring/observability/services/instrumentations/custom.instrumentations.d.ts +57 -0
- package/dist/esm/monitoring/observability/services/instrumentations/custom.instrumentations.d.ts.map +1 -0
- package/dist/esm/monitoring/observability/services/instrumentations/custom.instrumentations.js +77 -0
- package/dist/esm/monitoring/observability/services/instrumentations/custom.instrumentations.js.map +1 -0
- package/dist/esm/monitoring/observability/services/metrics.service.d.ts +27 -0
- package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -0
- package/dist/esm/monitoring/observability/services/metrics.service.js +236 -0
- package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -0
- package/dist/esm/monitoring/observability/services/telemetry.service.d.ts +28 -0
- package/dist/esm/monitoring/observability/services/telemetry.service.d.ts.map +1 -0
- package/dist/esm/monitoring/observability/services/telemetry.service.js +144 -0
- package/dist/esm/monitoring/observability/services/telemetry.service.js.map +1 -0
- package/dist/esm/monitoring/observability/services/tracer.service.d.ts +24 -0
- package/dist/esm/monitoring/observability/services/tracer.service.d.ts.map +1 -0
- package/dist/esm/monitoring/observability/services/tracer.service.js +287 -0
- package/dist/esm/monitoring/observability/services/tracer.service.js.map +1 -0
- package/dist/esm/notifications/email/components/email-components.d.ts +90 -0
- package/dist/esm/notifications/email/components/email-components.d.ts.map +1 -0
- package/dist/esm/notifications/email/components/email-components.js +171 -0
- package/dist/esm/notifications/email/components/email-components.js.map +1 -0
- package/dist/esm/notifications/email/models/email-context-provider.interface.d.ts +80 -0
- package/dist/esm/notifications/email/models/email-context-provider.interface.d.ts.map +1 -0
- package/dist/esm/notifications/email/models/email-context-provider.interface.js +25 -0
- package/dist/esm/notifications/email/models/email-context-provider.interface.js.map +1 -0
- package/dist/esm/notifications/email/models/email-template-definition.d.ts +68 -0
- package/dist/esm/notifications/email/models/email-template-definition.d.ts.map +1 -0
- package/dist/esm/notifications/email/models/email-template-definition.js +12 -0
- package/dist/esm/notifications/email/models/email-template-definition.js.map +1 -0
- package/dist/esm/notifications/email/models/email-template.actors-system.backend.definitions.d.ts +19 -0
- package/dist/esm/notifications/email/models/email-template.actors-system.backend.definitions.d.ts.map +1 -0
- package/dist/esm/notifications/email/models/email-template.actors-system.backend.definitions.js +66 -0
- package/dist/esm/notifications/email/models/email-template.actors-system.backend.definitions.js.map +1 -0
- package/dist/esm/notifications/email/models/email.backend.scheamas.d.ts +1 -0
- package/dist/esm/notifications/email/models/email.backend.scheamas.d.ts.map +1 -0
- package/dist/esm/notifications/email/models/email.backend.scheamas.js +1 -0
- package/dist/esm/notifications/email/models/email.backend.scheamas.js.map +1 -0
- package/dist/esm/notifications/email/services/email-batch-send.batch.backend.service.d.ts +74 -0
- package/dist/esm/notifications/email/services/email-batch-send.batch.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/email/services/email-batch-send.batch.backend.service.js +196 -0
- package/dist/esm/notifications/email/services/email-batch-send.batch.backend.service.js.map +1 -0
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.d.ts +49 -0
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.js +141 -0
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.js.map +1 -0
- package/dist/esm/notifications/email/services/email-renderer.backend.service.d.ts +74 -0
- package/dist/esm/notifications/email/services/email-renderer.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/email/services/email-renderer.backend.service.js +215 -0
- package/dist/esm/notifications/email/services/email-renderer.backend.service.js.map +1 -0
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.d.ts +37 -0
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.js +121 -0
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.js.map +1 -0
- package/dist/esm/notifications/email/services/email-template-generation.backend.service.d.ts +115 -0
- package/dist/esm/notifications/email/services/email-template-generation.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/email/services/email-template-generation.backend.service.js +634 -0
- package/dist/esm/notifications/email/services/email-template-generation.backend.service.js.map +1 -0
- package/dist/esm/notifications/email/services/email-template-registry.backend.service.d.ts +48 -0
- package/dist/esm/notifications/email/services/email-template-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/email/services/email-template-registry.backend.service.js +146 -0
- package/dist/esm/notifications/email/services/email-template-registry.backend.service.js.map +1 -0
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.d.ts +58 -0
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.js +223 -0
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.js.map +1 -0
- package/dist/esm/notifications/email/services/email-template-validator.backend.service.d.ts +49 -0
- package/dist/esm/notifications/email/services/email-template-validator.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/email/services/email-template-validator.backend.service.js +204 -0
- package/dist/esm/notifications/email/services/email-template-validator.backend.service.js.map +1 -0
- package/dist/esm/notifications/email/services/email.backend.service.d.ts +76 -0
- package/dist/esm/notifications/email/services/email.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/email/services/email.backend.service.js +294 -0
- package/dist/esm/notifications/email/services/email.backend.service.js.map +1 -0
- package/dist/esm/notifications/email/utils/color-conversion.utils.d.ts +56 -0
- package/dist/esm/notifications/email/utils/color-conversion.utils.d.ts.map +1 -0
- package/dist/esm/notifications/email/utils/color-conversion.utils.js +108 -0
- package/dist/esm/notifications/email/utils/color-conversion.utils.js.map +1 -0
- package/dist/esm/notifications/email/utils/interpolate-email-label.utils.d.ts +8 -0
- package/dist/esm/notifications/email/utils/interpolate-email-label.utils.d.ts.map +1 -0
- package/dist/esm/notifications/email/utils/interpolate-email-label.utils.js +15 -0
- package/dist/esm/notifications/email/utils/interpolate-email-label.utils.js.map +1 -0
- package/dist/esm/notifications/email/utils/zod-to-typescript.utils.d.ts +50 -0
- package/dist/esm/notifications/email/utils/zod-to-typescript.utils.d.ts.map +1 -0
- package/dist/esm/notifications/email/utils/zod-to-typescript.utils.js +281 -0
- package/dist/esm/notifications/email/utils/zod-to-typescript.utils.js.map +1 -0
- package/dist/esm/notifications/services/notification-badge.backend.service.d.ts +94 -0
- package/dist/esm/notifications/services/notification-badge.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/services/notification-badge.backend.service.js +292 -0
- package/dist/esm/notifications/services/notification-badge.backend.service.js.map +1 -0
- package/dist/esm/notifications/services/notifications-dispatcher.backend.service.d.ts +202 -0
- package/dist/esm/notifications/services/notifications-dispatcher.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/services/notifications-dispatcher.backend.service.js +1290 -0
- package/dist/esm/notifications/services/notifications-dispatcher.backend.service.js.map +1 -0
- package/dist/esm/notifications/sms/services/sms.backend.service.d.ts +50 -0
- package/dist/esm/notifications/sms/services/sms.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/sms/services/sms.backend.service.js +209 -0
- package/dist/esm/notifications/sms/services/sms.backend.service.js.map +1 -0
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts +58 -0
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js +184 -0
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js.map +1 -0
- package/dist/esm/notifications/webhooks/services/polymorphic-lookup.backend.service.d.ts +56 -0
- package/dist/esm/notifications/webhooks/services/polymorphic-lookup.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/webhooks/services/polymorphic-lookup.backend.service.js +109 -0
- package/dist/esm/notifications/webhooks/services/polymorphic-lookup.backend.service.js.map +1 -0
- package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.d.ts +96 -0
- package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.js +396 -0
- package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.js.map +1 -0
- package/dist/esm/organizations/services/org-creation-on-registration.backend.utils.d.ts +39 -0
- package/dist/esm/organizations/services/org-creation-on-registration.backend.utils.d.ts.map +1 -0
- package/dist/esm/organizations/services/org-creation-on-registration.backend.utils.js +73 -0
- package/dist/esm/organizations/services/org-creation-on-registration.backend.utils.js.map +1 -0
- package/dist/esm/organizations/services/org-member-roles-validation.backend.utils.d.ts +22 -0
- package/dist/esm/organizations/services/org-member-roles-validation.backend.utils.d.ts.map +1 -0
- package/dist/esm/organizations/services/org-member-roles-validation.backend.utils.js +35 -0
- package/dist/esm/organizations/services/org-member-roles-validation.backend.utils.js.map +1 -0
- package/dist/esm/organizations/services/organization-custom-implementation.backend.service.d.ts +10 -0
- package/dist/esm/organizations/services/organization-custom-implementation.backend.service.d.ts.map +1 -0
- package/dist/esm/organizations/services/organization-custom-implementation.backend.service.js +77 -0
- package/dist/esm/organizations/services/organization-custom-implementation.backend.service.js.map +1 -0
- package/dist/esm/organizations/services/organization-member-custom-implementation.backend.service.d.ts +10 -0
- package/dist/esm/organizations/services/organization-member-custom-implementation.backend.service.d.ts.map +1 -0
- package/dist/esm/organizations/services/organization-member-custom-implementation.backend.service.js +131 -0
- package/dist/esm/organizations/services/organization-member-custom-implementation.backend.service.js.map +1 -0
- package/dist/esm/organizations/services/scim-provisioning-gate.backend.utils.d.ts +22 -0
- package/dist/esm/organizations/services/scim-provisioning-gate.backend.utils.d.ts.map +1 -0
- package/dist/esm/organizations/services/scim-provisioning-gate.backend.utils.js +21 -0
- package/dist/esm/organizations/services/scim-provisioning-gate.backend.utils.js.map +1 -0
- package/dist/esm/organizations/services/user-org-type-grant.backend.utils.d.ts +25 -0
- package/dist/esm/organizations/services/user-org-type-grant.backend.utils.d.ts.map +1 -0
- package/dist/esm/organizations/services/user-org-type-grant.backend.utils.js +34 -0
- package/dist/esm/organizations/services/user-org-type-grant.backend.utils.js.map +1 -0
- package/dist/esm/organizations/services/user-type-revocation-on-org-leave.backend.utils.d.ts +32 -0
- package/dist/esm/organizations/services/user-type-revocation-on-org-leave.backend.utils.d.ts.map +1 -0
- package/dist/esm/organizations/services/user-type-revocation-on-org-leave.backend.utils.js +66 -0
- package/dist/esm/organizations/services/user-type-revocation-on-org-leave.backend.utils.js.map +1 -0
- package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.d.ts +126 -0
- package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.js +370 -0
- package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.js.map +1 -0
- package/dist/esm/queue/apps-crontabs-manager.backend.service.d.ts +86 -0
- package/dist/esm/queue/apps-crontabs-manager.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/apps-crontabs-manager.backend.service.js +176 -0
- package/dist/esm/queue/apps-crontabs-manager.backend.service.js.map +1 -0
- package/dist/esm/queue/cron-job-sync.backend.service.d.ts +42 -0
- package/dist/esm/queue/cron-job-sync.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/cron-job-sync.backend.service.js +181 -0
- package/dist/esm/queue/cron-job-sync.backend.service.js.map +1 -0
- package/dist/esm/queue/domain-queue-consumer.backend.service.d.ts +84 -0
- package/dist/esm/queue/domain-queue-consumer.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/domain-queue-consumer.backend.service.js +275 -0
- package/dist/esm/queue/domain-queue-consumer.backend.service.js.map +1 -0
- package/dist/esm/queue/job-completion-registry.backend.service.d.ts +111 -0
- package/dist/esm/queue/job-completion-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/job-completion-registry.backend.service.js +237 -0
- package/dist/esm/queue/job-completion-registry.backend.service.js.map +1 -0
- package/dist/esm/queue/job-consumer.backend.service.d.ts +109 -0
- package/dist/esm/queue/job-consumer.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/job-consumer.backend.service.js +515 -0
- package/dist/esm/queue/job-consumer.backend.service.js.map +1 -0
- package/dist/esm/queue/job-executor.backend.service.d.ts +53 -0
- package/dist/esm/queue/job-executor.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/job-executor.backend.service.js +278 -0
- package/dist/esm/queue/job-executor.backend.service.js.map +1 -0
- package/dist/esm/queue/job-payload-storage.backend.service.d.ts +86 -0
- package/dist/esm/queue/job-payload-storage.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/job-payload-storage.backend.service.js +250 -0
- package/dist/esm/queue/job-payload-storage.backend.service.js.map +1 -0
- package/dist/esm/queue/job-status-tracking.backend.service.d.ts +97 -0
- package/dist/esm/queue/job-status-tracking.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/job-status-tracking.backend.service.js +281 -0
- package/dist/esm/queue/job-status-tracking.backend.service.js.map +1 -0
- package/dist/esm/queue/queue-monitoring.backend.service.d.ts +71 -0
- package/dist/esm/queue/queue-monitoring.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/queue-monitoring.backend.service.js +297 -0
- package/dist/esm/queue/queue-monitoring.backend.service.js.map +1 -0
- package/dist/esm/queue/queue-worker-initializer.backend.service.d.ts +63 -0
- package/dist/esm/queue/queue-worker-initializer.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/queue-worker-initializer.backend.service.js +171 -0
- package/dist/esm/queue/queue-worker-initializer.backend.service.js.map +1 -0
- package/dist/esm/queue/queue.backend.service.d.ts +108 -0
- package/dist/esm/queue/queue.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/queue.backend.service.js +419 -0
- package/dist/esm/queue/queue.backend.service.js.map +1 -0
- package/dist/esm/queue/scheduled-message-verifier.backend.service.d.ts +74 -0
- package/dist/esm/queue/scheduled-message-verifier.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/scheduled-message-verifier.backend.service.js +189 -0
- package/dist/esm/queue/scheduled-message-verifier.backend.service.js.map +1 -0
- package/dist/esm/queue/worker-shutdown-manager.backend.service.d.ts +124 -0
- package/dist/esm/queue/worker-shutdown-manager.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/worker-shutdown-manager.backend.service.js +250 -0
- package/dist/esm/queue/worker-shutdown-manager.backend.service.js.map +1 -0
- package/dist/esm/requests/models/api-routes.backend.defintions.d.ts +34 -0
- package/dist/esm/requests/models/api-routes.backend.defintions.d.ts.map +1 -0
- package/dist/esm/requests/models/api-routes.backend.defintions.js +42 -0
- package/dist/esm/requests/models/api-routes.backend.defintions.js.map +1 -0
- package/dist/esm/requests/models/requests.backend.schemas.d.ts +48 -0
- package/dist/esm/requests/models/requests.backend.schemas.d.ts.map +1 -0
- package/dist/esm/requests/models/requests.backend.schemas.js +7 -0
- package/dist/esm/requests/models/requests.backend.schemas.js.map +1 -0
- package/dist/esm/requests/service/__tests__/mock-apps-shared-resources-gateway.service.d.ts +6 -0
- package/dist/esm/requests/service/__tests__/mock-apps-shared-resources-gateway.service.d.ts.map +1 -0
- package/dist/esm/requests/service/__tests__/mock-apps-shared-resources-gateway.service.js +20 -0
- package/dist/esm/requests/service/__tests__/mock-apps-shared-resources-gateway.service.js.map +1 -0
- package/dist/esm/requests/service/apps-shared-resources-gateway.backend.service.d.ts +84 -0
- package/dist/esm/requests/service/apps-shared-resources-gateway.backend.service.d.ts.map +1 -0
- package/dist/esm/requests/service/apps-shared-resources-gateway.backend.service.js +462 -0
- package/dist/esm/requests/service/apps-shared-resources-gateway.backend.service.js.map +1 -0
- package/dist/esm/requests/service/platform-mutualized-handler.backend.service.d.ts +9 -0
- package/dist/esm/requests/service/platform-mutualized-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/requests/service/platform-mutualized-handler.backend.service.js +36 -0
- package/dist/esm/requests/service/platform-mutualized-handler.backend.service.js.map +1 -0
- package/dist/esm/requests/service/platform-requests.backend.utils.d.ts +6 -0
- package/dist/esm/requests/service/platform-requests.backend.utils.d.ts.map +1 -0
- package/dist/esm/requests/service/platform-requests.backend.utils.js +47 -0
- package/dist/esm/requests/service/platform-requests.backend.utils.js.map +1 -0
- package/dist/esm/requests/service/remote-client-base.backend.service.d.ts +111 -0
- package/dist/esm/requests/service/remote-client-base.backend.service.d.ts.map +1 -0
- package/dist/esm/requests/service/remote-client-base.backend.service.js +354 -0
- package/dist/esm/requests/service/remote-client-base.backend.service.js.map +1 -0
- package/dist/esm/requests/service/serverless-services-handler.backend.service.d.ts +9 -0
- package/dist/esm/requests/service/serverless-services-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/requests/service/serverless-services-handler.backend.service.js +36 -0
- package/dist/esm/requests/service/serverless-services-handler.backend.service.js.map +1 -0
- package/dist/esm/requests/service/websocket.service.d.ts +507 -0
- package/dist/esm/requests/service/websocket.service.d.ts.map +1 -0
- package/dist/esm/requests/service/websocket.service.js +2222 -0
- package/dist/esm/requests/service/websocket.service.js.map +1 -0
- package/dist/esm/resources/models/custom-service-implementations.backend.definition.d.ts +3 -0
- package/dist/esm/resources/models/custom-service-implementations.backend.definition.d.ts.map +1 -0
- package/dist/esm/resources/models/custom-service-implementations.backend.definition.js +17 -0
- package/dist/esm/resources/models/custom-service-implementations.backend.definition.js.map +1 -0
- package/dist/esm/resources/models/index.d.ts +7 -0
- package/dist/esm/resources/models/index.d.ts.map +1 -0
- package/dist/esm/resources/models/index.js +7 -0
- package/dist/esm/resources/models/index.js.map +1 -0
- package/dist/esm/resources/models/resources-operations.backend.definitions.d.ts +4 -0
- package/dist/esm/resources/models/resources-operations.backend.definitions.d.ts.map +1 -0
- package/dist/esm/resources/models/resources-operations.backend.definitions.js +7 -0
- package/dist/esm/resources/models/resources-operations.backend.definitions.js.map +1 -0
- package/dist/esm/resources/models/resources-relationships.backend.definitions.d.ts +3 -0
- package/dist/esm/resources/models/resources-relationships.backend.definitions.d.ts.map +1 -0
- package/dist/esm/resources/models/resources-relationships.backend.definitions.js +19 -0
- package/dist/esm/resources/models/resources-relationships.backend.definitions.js.map +1 -0
- package/dist/esm/resources/models/resources-types.backend.schemas.d.ts +13 -0
- package/dist/esm/resources/models/resources-types.backend.schemas.d.ts.map +1 -0
- package/dist/esm/resources/models/resources-types.backend.schemas.js +14 -0
- package/dist/esm/resources/models/resources-types.backend.schemas.js.map +1 -0
- package/dist/esm/resources/models/resources.backend.schemas.d.ts +7 -0
- package/dist/esm/resources/models/resources.backend.schemas.d.ts.map +1 -0
- package/dist/esm/resources/models/resources.backend.schemas.js +8 -0
- package/dist/esm/resources/models/resources.backend.schemas.js.map +1 -0
- package/dist/esm/resources/models/virtual-fields.backend.types.d.ts +121 -0
- package/dist/esm/resources/models/virtual-fields.backend.types.d.ts.map +1 -0
- package/dist/esm/resources/models/virtual-fields.backend.types.js +10 -0
- package/dist/esm/resources/models/virtual-fields.backend.types.js.map +1 -0
- package/dist/esm/resources/services/__tests__/mock-resources-registry.service.d.ts +25 -0
- package/dist/esm/resources/services/__tests__/mock-resources-registry.service.d.ts.map +1 -0
- package/dist/esm/resources/services/__tests__/mock-resources-registry.service.js +59 -0
- package/dist/esm/resources/services/__tests__/mock-resources-registry.service.js.map +1 -0
- package/dist/esm/resources/services/resource-context.backend.service.d.ts +321 -0
- package/dist/esm/resources/services/resource-context.backend.service.d.ts.map +1 -0
- package/dist/esm/resources/services/resource-context.backend.service.js +723 -0
- package/dist/esm/resources/services/resource-context.backend.service.js.map +1 -0
- package/dist/esm/resources/services/resource-id.backend.service.d.ts +110 -0
- package/dist/esm/resources/services/resource-id.backend.service.d.ts.map +1 -0
- package/dist/esm/resources/services/resource-id.backend.service.js +267 -0
- package/dist/esm/resources/services/resource-id.backend.service.js.map +1 -0
- package/dist/esm/resources/services/resource-population.backend.service.d.ts +149 -0
- package/dist/esm/resources/services/resource-population.backend.service.d.ts.map +1 -0
- package/dist/esm/resources/services/resource-population.backend.service.js +543 -0
- package/dist/esm/resources/services/resource-population.backend.service.js.map +1 -0
- package/dist/esm/resources/services/resources-registry.backend.service.d.ts +151 -0
- package/dist/esm/resources/services/resources-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/resources/services/resources-registry.backend.service.js +867 -0
- package/dist/esm/resources/services/resources-registry.backend.service.js.map +1 -0
- package/dist/esm/resources/services/virtual-fields.backend.service.d.ts +72 -0
- package/dist/esm/resources/services/virtual-fields.backend.service.d.ts.map +1 -0
- package/dist/esm/resources/services/virtual-fields.backend.service.js +254 -0
- package/dist/esm/resources/services/virtual-fields.backend.service.js.map +1 -0
- package/dist/esm/runtime/controllers/health-controller.backend.service.d.ts +73 -0
- package/dist/esm/runtime/controllers/health-controller.backend.service.d.ts.map +1 -0
- package/dist/esm/runtime/controllers/health-controller.backend.service.js +275 -0
- package/dist/esm/runtime/controllers/health-controller.backend.service.js.map +1 -0
- package/dist/esm/runtime/domain-module.backend.definitions.d.ts +43 -0
- package/dist/esm/runtime/domain-module.backend.definitions.d.ts.map +1 -0
- package/dist/esm/runtime/domain-module.backend.definitions.js +70 -0
- package/dist/esm/runtime/domain-module.backend.definitions.js.map +1 -0
- package/dist/esm/runtime/models/execution-context.backend.schemas.d.ts +253 -0
- package/dist/esm/runtime/models/execution-context.backend.schemas.d.ts.map +1 -0
- package/dist/esm/runtime/models/execution-context.backend.schemas.js +329 -0
- package/dist/esm/runtime/models/execution-context.backend.schemas.js.map +1 -0
- package/dist/esm/runtime/models/runtime.backend.schemas.d.ts +45 -0
- package/dist/esm/runtime/models/runtime.backend.schemas.d.ts.map +1 -0
- package/dist/esm/runtime/models/runtime.backend.schemas.js +73 -0
- package/dist/esm/runtime/models/runtime.backend.schemas.js.map +1 -0
- package/dist/esm/runtime/services/execution-context-creator.backend.service.d.ts +315 -0
- package/dist/esm/runtime/services/execution-context-creator.backend.service.d.ts.map +1 -0
- package/dist/esm/runtime/services/execution-context-creator.backend.service.js +1525 -0
- package/dist/esm/runtime/services/execution-context-creator.backend.service.js.map +1 -0
- package/dist/esm/runtime/services/execution-context-handler.backend.service.d.ts +60 -0
- package/dist/esm/runtime/services/execution-context-handler.backend.service.d.ts.map +1 -0
- package/dist/esm/runtime/services/execution-context-handler.backend.service.js +150 -0
- package/dist/esm/runtime/services/execution-context-handler.backend.service.js.map +1 -0
- package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.d.ts +11 -0
- package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.d.ts.map +1 -0
- package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.js +1 -0
- package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.js.map +1 -0
- package/dist/esm/runtime/services/http-server.backend.service.d.ts +188 -0
- package/dist/esm/runtime/services/http-server.backend.service.d.ts.map +1 -0
- package/dist/esm/runtime/services/http-server.backend.service.js +755 -0
- package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -0
- package/dist/esm/runtime/services/start-application.backend.service.d.ts +240 -0
- package/dist/esm/runtime/services/start-application.backend.service.d.ts.map +1 -0
- package/dist/esm/runtime/services/start-application.backend.service.js +977 -0
- package/dist/esm/runtime/services/start-application.backend.service.js.map +1 -0
- package/dist/esm/runtime/testing/execution-context-test-fixtures.d.ts +10 -0
- package/dist/esm/runtime/testing/execution-context-test-fixtures.d.ts.map +1 -0
- package/dist/esm/runtime/testing/execution-context-test-fixtures.js +13 -0
- package/dist/esm/runtime/testing/execution-context-test-fixtures.js.map +1 -0
- package/dist/esm/runtime/testing/mock-execution-context-creator.service.d.ts +15 -0
- package/dist/esm/runtime/testing/mock-execution-context-creator.service.d.ts.map +1 -0
- package/dist/esm/runtime/testing/mock-execution-context-creator.service.js +42 -0
- package/dist/esm/runtime/testing/mock-execution-context-creator.service.js.map +1 -0
- package/dist/esm/runtime/utils/scan-default-exports.backend.utils.d.ts +85 -0
- package/dist/esm/runtime/utils/scan-default-exports.backend.utils.d.ts.map +1 -0
- package/dist/esm/runtime/utils/scan-default-exports.backend.utils.js +171 -0
- package/dist/esm/runtime/utils/scan-default-exports.backend.utils.js.map +1 -0
- package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.d.ts +19 -0
- package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.js +59 -0
- package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/controllers/auth-method-management-controller.backend.service.d.ts +31 -0
- package/dist/esm/security/authentications/controllers/auth-method-management-controller.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/controllers/auth-method-management-controller.backend.service.js +215 -0
- package/dist/esm/security/authentications/controllers/auth-method-management-controller.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.d.ts +493 -0
- package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.js +2371 -0
- package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/models/auth-constants.backend.d.ts +83 -0
- package/dist/esm/security/authentications/models/auth-constants.backend.d.ts.map +1 -0
- package/dist/esm/security/authentications/models/auth-constants.backend.js +113 -0
- package/dist/esm/security/authentications/models/auth-constants.backend.js.map +1 -0
- package/dist/esm/security/authentications/models/authentications.backend.schemas.d.ts +98 -0
- package/dist/esm/security/authentications/models/authentications.backend.schemas.d.ts.map +1 -0
- package/dist/esm/security/authentications/models/authentications.backend.schemas.js +59 -0
- package/dist/esm/security/authentications/models/authentications.backend.schemas.js.map +1 -0
- package/dist/esm/security/authentications/models/jwt.backend.schemas.d.ts +42 -0
- package/dist/esm/security/authentications/models/jwt.backend.schemas.d.ts.map +1 -0
- package/dist/esm/security/authentications/models/jwt.backend.schemas.js +98 -0
- package/dist/esm/security/authentications/models/jwt.backend.schemas.js.map +1 -0
- package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.d.ts +163 -0
- package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.d.ts.map +1 -0
- package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.js +12 -0
- package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.js.map +1 -0
- package/dist/esm/security/authentications/models/saml-authentication.backend.schemas.d.ts +102 -0
- package/dist/esm/security/authentications/models/saml-authentication.backend.schemas.d.ts.map +1 -0
- package/dist/esm/security/authentications/models/saml-authentication.backend.schemas.js +7 -0
- package/dist/esm/security/authentications/models/saml-authentication.backend.schemas.js.map +1 -0
- package/dist/esm/security/authentications/models/sso-connection.backend.schemas.d.ts +88 -0
- package/dist/esm/security/authentications/models/sso-connection.backend.schemas.d.ts.map +1 -0
- package/dist/esm/security/authentications/models/sso-connection.backend.schemas.js +17 -0
- package/dist/esm/security/authentications/models/sso-connection.backend.schemas.js.map +1 -0
- package/dist/esm/security/authentications/services/__tests__/mock-auth-execution-context-factory.service.d.ts +27 -0
- package/dist/esm/security/authentications/services/__tests__/mock-auth-execution-context-factory.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/__tests__/mock-auth-execution-context-factory.service.js +66 -0
- package/dist/esm/security/authentications/services/__tests__/mock-auth-execution-context-factory.service.js.map +1 -0
- package/dist/esm/security/authentications/services/__tests__/mock-auth-token-issuer.service.d.ts +30 -0
- package/dist/esm/security/authentications/services/__tests__/mock-auth-token-issuer.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/__tests__/mock-auth-token-issuer.service.js +44 -0
- package/dist/esm/security/authentications/services/__tests__/mock-auth-token-issuer.service.js.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/__tests__/mock-domain-to-org-lookup.service.d.ts +19 -0
- package/dist/esm/security/authentications/services/admin-config/__tests__/mock-domain-to-org-lookup.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/__tests__/mock-domain-to-org-lookup.service.js +43 -0
- package/dist/esm/security/authentications/services/admin-config/__tests__/mock-domain-to-org-lookup.service.js.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/__tests__/mock-enterprise-user-provisioning.service.d.ts +37 -0
- package/dist/esm/security/authentications/services/admin-config/__tests__/mock-enterprise-user-provisioning.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/__tests__/mock-enterprise-user-provisioning.service.js +58 -0
- package/dist/esm/security/authentications/services/admin-config/__tests__/mock-enterprise-user-provisioning.service.js.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.d.ts +85 -0
- package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.js +379 -0
- package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.js.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.d.ts +79 -0
- package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.js +205 -0
- package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.d.ts +59 -0
- package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.js +179 -0
- package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.d.ts +116 -0
- package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.js +436 -0
- package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/oidc-discovery.backend.service.d.ts +67 -0
- package/dist/esm/security/authentications/services/admin-config/oidc-discovery.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/admin-config/oidc-discovery.backend.service.js +222 -0
- package/dist/esm/security/authentications/services/admin-config/oidc-discovery.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/anonymous-session.backend.service.d.ts +80 -0
- package/dist/esm/security/authentications/services/anonymous-session.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/anonymous-session.backend.service.js +368 -0
- package/dist/esm/security/authentications/services/anonymous-session.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-credential-verifier.backend.service.d.ts +75 -0
- package/dist/esm/security/authentications/services/auth-credential-verifier.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-credential-verifier.backend.service.js +139 -0
- package/dist/esm/security/authentications/services/auth-credential-verifier.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-execution-context-factory.backend.service.d.ts +72 -0
- package/dist/esm/security/authentications/services/auth-execution-context-factory.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-execution-context-factory.backend.service.js +127 -0
- package/dist/esm/security/authentications/services/auth-execution-context-factory.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.d.ts +57 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.js +459 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-mfa.backend.service.d.ts +44 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-mfa.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-mfa.backend.service.js +131 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-mfa.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts +58 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js +209 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-phone-verification.backend.service.d.ts +46 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-phone-verification.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-phone-verification.backend.service.js +124 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-phone-verification.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.d.ts +165 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.js +816 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.d.ts +218 -0
- package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.js +1026 -0
- package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.d.ts +150 -0
- package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.js +737 -0
- package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-assertion-validator.backend.service.d.ts +224 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-assertion-validator.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-assertion-validator.backend.service.js +593 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-assertion-validator.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-authentication.backend.service.d.ts +267 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-authentication.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-authentication.backend.service.js +1376 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-authentication.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-metadata.backend.service.d.ts +93 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-metadata.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-metadata.backend.service.js +396 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-metadata.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-replay-guard.backend.service.d.ts +40 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-replay-guard.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-replay-guard.backend.service.js +92 -0
- package/dist/esm/security/authentications/services/auth-methods/saml-replay-guard.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.d.ts +82 -0
- package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.js +325 -0
- package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-session-store.backend.service.d.ts +66 -0
- package/dist/esm/security/authentications/services/auth-session-store.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-session-store.backend.service.js +198 -0
- package/dist/esm/security/authentications/services/auth-session-store.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.d.ts +108 -0
- package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.js +406 -0
- package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.d.ts +366 -0
- package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.js +2631 -0
- package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.d.ts +13 -0
- package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.js +53 -0
- package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.js.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/auth-policy.custom-impl.backend.service.d.ts +12 -0
- package/dist/esm/security/authentications/services/custom-impls/auth-policy.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/auth-policy.custom-impl.backend.service.js +41 -0
- package/dist/esm/security/authentications/services/custom-impls/auth-policy.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/scim-provisioning-config.custom-impl.backend.service.d.ts +18 -0
- package/dist/esm/security/authentications/services/custom-impls/scim-provisioning-config.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/scim-provisioning-config.custom-impl.backend.service.js +140 -0
- package/dist/esm/security/authentications/services/custom-impls/scim-provisioning-config.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/scim-tokens.custom-impl.backend.service.d.ts +16 -0
- package/dist/esm/security/authentications/services/custom-impls/scim-tokens.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/scim-tokens.custom-impl.backend.service.js +112 -0
- package/dist/esm/security/authentications/services/custom-impls/scim-tokens.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.d.ts +16 -0
- package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js +101 -0
- package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/siem-export-config.custom-impl.backend.service.d.ts +18 -0
- package/dist/esm/security/authentications/services/custom-impls/siem-export-config.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/siem-export-config.custom-impl.backend.service.js +136 -0
- package/dist/esm/security/authentications/services/custom-impls/siem-export-config.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.d.ts +19 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.js +154 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-connection.custom-impl.backend.service.d.ts +26 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-connection.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-connection.custom-impl.backend.service.js +657 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-connection.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/utils/__tests__/mock-auth-user-lookup.service.d.ts +27 -0
- package/dist/esm/security/authentications/services/utils/__tests__/mock-auth-user-lookup.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/utils/__tests__/mock-auth-user-lookup.service.js +60 -0
- package/dist/esm/security/authentications/services/utils/__tests__/mock-auth-user-lookup.service.js.map +1 -0
- package/dist/esm/security/authentications/services/utils/auth-controller.utils.d.ts +23 -0
- package/dist/esm/security/authentications/services/utils/auth-controller.utils.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/utils/auth-controller.utils.js +44 -0
- package/dist/esm/security/authentications/services/utils/auth-controller.utils.js.map +1 -0
- package/dist/esm/security/authentications/services/utils/auth-credential-ops.backend.service.d.ts +89 -0
- package/dist/esm/security/authentications/services/utils/auth-credential-ops.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/utils/auth-credential-ops.backend.service.js +192 -0
- package/dist/esm/security/authentications/services/utils/auth-credential-ops.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/utils/auth-response-helper.backend.service.d.ts +20 -0
- package/dist/esm/security/authentications/services/utils/auth-response-helper.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/utils/auth-response-helper.backend.service.js +55 -0
- package/dist/esm/security/authentications/services/utils/auth-response-helper.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.d.ts +50 -0
- package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.js +135 -0
- package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/utils/saml-java-availability.d.ts +26 -0
- package/dist/esm/security/authentications/services/utils/saml-java-availability.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/utils/saml-java-availability.js +59 -0
- package/dist/esm/security/authentications/services/utils/saml-java-availability.js.map +1 -0
- package/dist/esm/security/authorizations/services/authorizations.backend.service.d.ts +137 -0
- package/dist/esm/security/authorizations/services/authorizations.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authorizations/services/authorizations.backend.service.js +723 -0
- package/dist/esm/security/authorizations/services/authorizations.backend.service.js.map +1 -0
- package/dist/esm/security/consumable-tokens/batches/consumable-tokens-cleanup.batch.backend.service.d.ts +28 -0
- package/dist/esm/security/consumable-tokens/batches/consumable-tokens-cleanup.batch.backend.service.d.ts.map +1 -0
- package/dist/esm/security/consumable-tokens/batches/consumable-tokens-cleanup.batch.backend.service.js +156 -0
- package/dist/esm/security/consumable-tokens/batches/consumable-tokens-cleanup.batch.backend.service.js.map +1 -0
- package/dist/esm/security/consumable-tokens/models/consumable-tokens.backend.resources-config.schemas.d.ts +4 -0
- package/dist/esm/security/consumable-tokens/models/consumable-tokens.backend.resources-config.schemas.d.ts.map +1 -0
- package/dist/esm/security/consumable-tokens/models/consumable-tokens.backend.resources-config.schemas.js +72 -0
- package/dist/esm/security/consumable-tokens/models/consumable-tokens.backend.resources-config.schemas.js.map +1 -0
- package/dist/esm/security/consumable-tokens/models/consumable-tokens.shared.schemas.d.ts +125 -0
- package/dist/esm/security/consumable-tokens/models/consumable-tokens.shared.schemas.d.ts.map +1 -0
- package/dist/esm/security/consumable-tokens/models/consumable-tokens.shared.schemas.js +69 -0
- package/dist/esm/security/consumable-tokens/models/consumable-tokens.shared.schemas.js.map +1 -0
- package/dist/esm/security/consumable-tokens/models/index.d.ts +3 -0
- package/dist/esm/security/consumable-tokens/models/index.d.ts.map +1 -0
- package/dist/esm/security/consumable-tokens/models/index.js +3 -0
- package/dist/esm/security/consumable-tokens/models/index.js.map +1 -0
- package/dist/esm/security/consumable-tokens/services/__tests__/mock-consumable-token.service.d.ts +26 -0
- package/dist/esm/security/consumable-tokens/services/__tests__/mock-consumable-token.service.d.ts.map +1 -0
- package/dist/esm/security/consumable-tokens/services/__tests__/mock-consumable-token.service.js +55 -0
- package/dist/esm/security/consumable-tokens/services/__tests__/mock-consumable-token.service.js.map +1 -0
- package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.d.ts +142 -0
- package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.d.ts.map +1 -0
- package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.js +446 -0
- package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.js.map +1 -0
- package/dist/esm/security/jwt/services/auth-jwt-guard.backend.service.d.ts +46 -0
- package/dist/esm/security/jwt/services/auth-jwt-guard.backend.service.d.ts.map +1 -0
- package/dist/esm/security/jwt/services/auth-jwt-guard.backend.service.js +147 -0
- package/dist/esm/security/jwt/services/auth-jwt-guard.backend.service.js.map +1 -0
- package/dist/esm/security/jwt/services/jwt.backend.service.d.ts +75 -0
- package/dist/esm/security/jwt/services/jwt.backend.service.d.ts.map +1 -0
- package/dist/esm/security/jwt/services/jwt.backend.service.js +368 -0
- package/dist/esm/security/jwt/services/jwt.backend.service.js.map +1 -0
- package/dist/esm/security/scim/controllers/scim.backend.controller.d.ts +71 -0
- package/dist/esm/security/scim/controllers/scim.backend.controller.d.ts.map +1 -0
- package/dist/esm/security/scim/controllers/scim.backend.controller.js +863 -0
- package/dist/esm/security/scim/controllers/scim.backend.controller.js.map +1 -0
- package/dist/esm/security/scim/models/scim-protocol.backend.schemas.d.ts +275 -0
- package/dist/esm/security/scim/models/scim-protocol.backend.schemas.d.ts.map +1 -0
- package/dist/esm/security/scim/models/scim-protocol.backend.schemas.js +139 -0
- package/dist/esm/security/scim/models/scim-protocol.backend.schemas.js.map +1 -0
- package/dist/esm/security/scim/utils/scim-filter-parser.d.ts +35 -0
- package/dist/esm/security/scim/utils/scim-filter-parser.d.ts.map +1 -0
- package/dist/esm/security/scim/utils/scim-filter-parser.js +232 -0
- package/dist/esm/security/scim/utils/scim-filter-parser.js.map +1 -0
- package/dist/esm/security/scim/utils/scim-response-formatter.d.ts +42 -0
- package/dist/esm/security/scim/utils/scim-response-formatter.d.ts.map +1 -0
- package/dist/esm/security/scim/utils/scim-response-formatter.js +89 -0
- package/dist/esm/security/scim/utils/scim-response-formatter.js.map +1 -0
- package/dist/esm/testing.d.ts +31 -0
- package/dist/esm/testing.d.ts.map +1 -0
- package/dist/esm/testing.js +31 -0
- package/dist/esm/testing.js.map +1 -0
- package/dist/esm/users/services/user-self-custom-implementations.backend.d.ts +9 -0
- package/dist/esm/users/services/user-self-custom-implementations.backend.d.ts.map +1 -0
- package/dist/esm/users/services/user-self-custom-implementations.backend.js +48 -0
- package/dist/esm/users/services/user-self-custom-implementations.backend.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +163 -0
- package/src/__tests__/integration/bulk-repository-write-contract.integration.test.ts +373 -0
- package/src/__tests__/integration/custom-batch-job-execution.integration.test.ts +147 -0
- package/src/__tests__/integration/delete-file-rollback-persistence.integration.test.ts +551 -0
- package/src/__tests__/integration/file-management-nested-persistence.integration.test.ts +487 -0
- package/src/__tests__/integration/file-management-postgresql-persistence.integration.test.ts +466 -0
- package/src/__tests__/integration/files-cleanup-persistence.integration.test.ts +335 -0
- package/src/__tests__/integration/generated-bulk-relationship-runtime.integration.test.ts +545 -0
- package/src/__tests__/integration/lifecycle-delete-rollback-persistence.integration.test.ts +537 -0
- package/src/__tests__/integration/postgresql-contextual-filter-enforcement.integration.test.ts +170 -0
- package/src/__tests__/integration/postgresql-delete-best-effort-boundary.integration.test.ts +604 -0
- package/src/__tests__/integration/prompt-compiler.integration.test.ts +723 -0
- package/src/__tests__/integration/relationship-service-semantics.integration.test.ts +2086 -0
- package/src/__tests__/integration/repositories-registry.integration.test.ts +296 -0
- package/src/__tests__/integration/resource-factory-pipeline.integration.test.ts +556 -0
- package/src/__tests__/integration/resource-services.integration.test.ts +265 -0
- package/src/__tests__/integration/resources-registry.integration.test.ts +327 -0
- package/src/__tests__/integration/services-registry.integration.test.ts +231 -0
- package/src/__tests__/integration/update-many-runtime-guards.integration.test.ts +290 -0
- package/src/__tests__/setup.ts +15 -0
- package/src/__tests__/test-container.ts +120 -0
- package/src/applications/models/applications.backend.schemas.ts +18 -0
- package/src/base-classes/__tests__/batches-cronjobs-executor.test.ts +63 -0
- package/src/base-classes/__tests__/bulk-delete-child-file-guard.test.ts +152 -0
- package/src/base-classes/__tests__/bulk-nested-file-update-coordination.test.ts +171 -0
- package/src/base-classes/__tests__/delete-file-coordination.test.ts +185 -0
- package/src/base-classes/__tests__/postgresql-file-transaction-coordination.test.ts +424 -0
- package/src/base-classes/__tests__/postgresql-repository-contextual-filter-enforcement.test.ts +88 -0
- package/src/base-classes/__tests__/repository-contextual-filter-enforcement.test.ts +87 -0
- package/src/base-classes/__tests__/resource-operation-helper-context-enforcement.test.ts +74 -0
- package/src/base-classes/__tests__/transaction-boundaries.test.ts +153 -0
- package/src/base-classes/models/manual-controllers.backend.definition.ts +56 -0
- package/src/base-classes/models/repositories.backend.schemas.ts +105 -0
- package/src/base-classes/services/__tests__/mock-resource-operation-helper.service.ts +61 -0
- package/src/base-classes/services/batches/batches-cronjobs-custom-execution.service.ts +148 -0
- package/src/base-classes/services/batches/batches-cronjobs-executor.backend.service.ts +115 -0
- package/src/base-classes/services/batches/batches-cronjobs-resource-execution.backend.service.ts +58 -0
- package/src/base-classes/services/controllers/__tests__/controller-request-validation.utils.test.ts +292 -0
- package/src/base-classes/services/controllers/__tests__/controller-resource-file-upload-routes.test.ts +1335 -0
- package/src/base-classes/services/controllers/__tests__/controller-resource.version-conflict.test.ts +372 -0
- package/src/base-classes/services/controllers/abstract-controller.backend.service.ts +302 -0
- package/src/base-classes/services/controllers/controller-resource.backend.service.ts +1833 -0
- package/src/base-classes/services/controllers/controllers-registry-handler.backend.service.ts +494 -0
- package/src/base-classes/services/controllers/validate-field-handler.backend.service.ts +613 -0
- package/src/base-classes/services/repositories/__tests__/mock-repositories-registry-handler.service.ts +31 -0
- package/src/base-classes/services/repositories/__tests__/repository-resource.singleton-read.test.ts +50 -0
- package/src/base-classes/services/repositories/postgresql-resource-repository.backend.service.ts +1207 -0
- package/src/base-classes/services/repositories/repositories-registry-handler.backend.service.ts +804 -0
- package/src/base-classes/services/repositories/repository-resource.backend.service.ts +2186 -0
- package/src/base-classes/services/resource-operations-helper.backend.service.ts +468 -0
- package/src/base-classes/services/services/__tests__/mock-services-registry-handler.service.ts +21 -0
- package/src/base-classes/services/services/__tests__/services-registry-handler.notifications.test.ts +65 -0
- package/src/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.ts +305 -0
- package/src/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.ts +224 -0
- package/src/base-classes/services/services/resource-operation-custom-implementation.factory.backend.ts +331 -0
- package/src/base-classes/services/services/services-registry-handler.backend.service.ts +6288 -0
- package/src/base-classes/utils/backend-type-utils.ts +64 -0
- package/src/billing/services/back-office/__tests__/billing-feature-sync.backend.service.test.ts +132 -0
- package/src/billing/services/back-office/__tests__/billing-state.backend.service.test.ts +245 -0
- package/src/billing/services/back-office/__tests__/product-catalog-sync.backend.service.test.ts +238 -0
- package/src/billing/services/back-office/abstract-billing.backend.service.ts +89 -0
- package/src/billing/services/back-office/billing-feature-sync.backend.service.ts +473 -0
- package/src/billing/services/back-office/billing-state.backend.service.ts +348 -0
- package/src/billing/services/back-office/product-catalog-sync.backend.service.ts +415 -0
- package/src/billing/services/back-office/usage-metering.backend.service.ts +326 -0
- package/src/billing/services/billing.utils.ts +26 -0
- package/src/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.ts +342 -0
- package/src/billing/services/custom-impl/billing-custom-impl-utils.backend.ts +274 -0
- package/src/billing/services/custom-impl/billing-custom-implementations.backend.ts +236 -0
- package/src/billing/services/custom-impl/credit-pool.custom-ops.custom-impl.backend.service.ts +133 -0
- package/src/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.ts +242 -0
- package/src/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.ts +434 -0
- package/src/billing/services/webhooks/billing-webhook-adapter.backend.service.ts +70 -0
- package/src/billing/services/webhooks/billing-webhook-capability-handler.backend.service.ts +46 -0
- package/src/billing/services/webhooks/billing-webhook-event-router.backend.service.ts +727 -0
- package/src/billing/testing/billing-test-fixtures.ts +296 -0
- package/src/billing/testing/mock-billing-provider.ts +548 -0
- package/src/charts/controllers/__tests__/chart.backend.controller.test.ts +403 -0
- package/src/charts/controllers/chart.backend.controller.ts +238 -0
- package/src/charts/services/__tests__/chart-registry.backend.service.test.ts +120 -0
- package/src/charts/services/chart-registry.backend.service.ts +109 -0
- package/src/compliance/audit-trails/audit-logs.custom-impl.backend.service.ts +104 -0
- package/src/compliance/audit-trails/services/__tests__/mock-audit-logs.service.ts +48 -0
- package/src/compliance/audit-trails/services/audit-event-dispatcher.backend.service.ts +325 -0
- package/src/compliance/audit-trails/services/audit-logs.backend.service.ts +1313 -0
- package/src/compliance/audit-trails/services/siem-webhook-delivery.backend.service.ts +542 -0
- package/src/compliance/index.ts +1 -0
- package/src/config/custom/application-config-controller.backend.service.ts +119 -0
- package/src/config/models/__tests__/app-config-secrets.boundaries.test.ts +56 -0
- package/src/config/models/__tests__/app-config.backend-authored.definitions.test.ts +286 -0
- package/src/config/models/app-config-secrets.backend.schemas.ts +154 -0
- package/src/config/models/app-config.backend-authored.definitions.ts +165 -0
- package/src/config/models/app-config.backend.schemas.ts +614 -0
- package/src/config/models/app-env-config.backend.schemas.ts +135 -0
- package/src/config/models/config-mutation-boundary.utils.ts +76 -0
- package/src/config/models/postgresql-env-config.backend.schemas.ts +126 -0
- package/src/config/models/runtime-topology.backend.contracts.ts +42 -0
- package/src/config/services/__tests__/app-configuration-loader.backend.service.test.ts +118 -0
- package/src/config/services/__tests__/app-configuration.backend.service.test.ts +40 -0
- package/src/config/services/__tests__/app-configuration.backend.utils.test.ts +72 -0
- package/src/config/services/__tests__/application-startup-config-validator.backend.service.test.ts +404 -0
- package/src/config/services/__tests__/mock-app-configuration.service.ts +131 -0
- package/src/config/services/app-configuration-loader.backend.service.ts +443 -0
- package/src/config/services/app-configuration.backend.service.ts +570 -0
- package/src/config/services/app-configuration.backend.utils.ts +94 -0
- package/src/config/services/application-startup-config-validator.backend.service.ts +611 -0
- package/src/databases/models/aggregation.backend.schemas.ts +174 -0
- package/src/databases/models/databases.backend.schemas.ts +70 -0
- package/src/databases/models/filter.backend.schemas.ts +101 -0
- package/src/databases/models/sql.backend.schemas.ts +111 -0
- package/src/databases/models/transaction.shared.schemas.ts +172 -0
- package/src/databases/services/__tests__/mock-mongo-transaction-registry.service.ts +90 -0
- package/src/databases/services/__tests__/mock-mongodb.service.ts +86 -0
- package/src/databases/services/__tests__/mock-mongoose-model.service.ts +411 -0
- package/src/databases/services/__tests__/mock-redis.service.ts +72 -0
- package/src/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.ts +41 -0
- package/src/databases/services/__tests__/mongo-aggregation-compiler.test.ts +918 -0
- package/src/databases/services/__tests__/postgresql-filter.backend.service.test.ts +180 -0
- package/src/databases/services/__tests__/sql-hybrid-transform.test.ts +73 -0
- package/src/databases/services/aggregation/__tests__/aggregation-authorization.backend.service.test.ts +444 -0
- package/src/databases/services/aggregation/__tests__/aggregation-query.backend.service.test.ts +150 -0
- package/src/databases/services/aggregation/__tests__/computed-measure-evaluator.test.ts +525 -0
- package/src/databases/services/aggregation/__tests__/field-access-validator.test.ts +458 -0
- package/src/databases/services/aggregation/__tests__/time-series-densifier.test.ts +631 -0
- package/src/databases/services/aggregation/__tests__/window-function-processor.test.ts +598 -0
- package/src/databases/services/aggregation/aggregation-authorization.backend.service.ts +516 -0
- package/src/databases/services/aggregation/aggregation-query.backend.service.ts +514 -0
- package/src/databases/services/aggregation/computed-measure-evaluator.backend.service.ts +196 -0
- package/src/databases/services/aggregation/field-access-validator.backend.service.ts +225 -0
- package/src/databases/services/aggregation/time-series-densifier.backend.service.ts +389 -0
- package/src/databases/services/aggregation/topn-processor.backend.service.ts +221 -0
- package/src/databases/services/aggregation/window-function-processor.backend.service.ts +301 -0
- package/src/databases/services/db-utils.ts +96 -0
- package/src/databases/services/mongo-aggregation.backend.service.ts +762 -0
- package/src/databases/services/mongodb.service.ts +736 -0
- package/src/databases/services/postgresql-aggregation.backend.service.ts +794 -0
- package/src/databases/services/postgresql-database.backend.service.ts +288 -0
- package/src/databases/services/postgresql-filter.backend.service.ts +673 -0
- package/src/databases/services/redis.service.ts +531 -0
- package/src/databases/services/zod-to-mongoose-schema-convertor.backend.service.ts +2486 -0
- package/src/databases/services/zod-to-sql-hybrid-schema.planner.ts +312 -0
- package/src/errors/services/__tests__/error-builder.backend.service.test.ts +31 -0
- package/src/errors/services/__tests__/error-handler.backend.service.test.ts +82 -0
- package/src/errors/services/__tests__/mock-error-builder.service.ts +288 -0
- package/src/errors/services/error-builder.backend.service.ts +403 -0
- package/src/errors/services/error-handler.backend.service.ts +236 -0
- package/src/errors/services/rate-limit.backend.service.ts +45 -0
- package/src/external-providers/models/external-providers.backend.schemas.ts +243 -0
- package/src/external-providers/services/__tests__/external-providers-registry.backend.service.test.ts +136 -0
- package/src/external-providers/services/__tests__/feature-bindings.backend.service.test.ts +40 -0
- package/src/external-providers/services/__tests__/mock-external-providers-registry.service.ts +33 -0
- package/src/external-providers/services/__tests__/mock-lazy-provider-registry.service.ts +45 -0
- package/src/external-providers/services/external-api-handler.backend.service.ts +19 -0
- package/src/external-providers/services/external-providers-registry.backend.service.ts +534 -0
- package/src/external-providers/services/feature-bindings.backend.service.ts +422 -0
- package/src/external-providers/services/lazy-provider-registry.backend.service.ts +486 -0
- package/src/features/__tests__/feature-builders.test.ts +152 -0
- package/src/features/controllers/__tests__/features.backend.controller.test.ts +173 -0
- package/src/features/controllers/features.backend.controller.ts +200 -0
- package/src/features/services/__tests__/feature-definition-registry.backend.service.test.ts +152 -0
- package/src/features/services/__tests__/feature-gate.test.ts +484 -0
- package/src/features/services/__tests__/feature-resolution.backend.service.test.ts +203 -0
- package/src/features/services/__tests__/mock-capability-bindings.service.ts +26 -0
- package/src/features/services/__tests__/mock-feature-definition-registry.service.ts +56 -0
- package/src/features/services/__tests__/mock-feature-resolution.service.ts +36 -0
- package/src/features/services/feature-definition-registry.backend.service.ts +537 -0
- package/src/features/services/feature-gate.backend.service.ts +522 -0
- package/src/features/services/feature-resolution.backend.service.ts +652 -0
- package/src/features/testing/feature-test-utils.ts +200 -0
- package/src/files/batches/__tests__/files-cleanup.batch.backend.service.test.ts +186 -0
- package/src/files/batches/files-cleanup.batch.backend.service.ts +259 -0
- package/src/files/constraints/file-analyzers.types.ts +85 -0
- package/src/files/constraints/file-constraint-resolver-chain.backend.service.ts +99 -0
- package/src/files/constraints/file-constraint.types.ts +104 -0
- package/src/files/constraints/file-validation.backend.service.ts +359 -0
- package/src/files/constraints/resource-field-constraint-resolver.backend.service.ts +138 -0
- package/src/files/controllers/__tests__/file.controller.behavior.test.ts +655 -0
- package/src/files/controllers/file.controller.ts +1030 -0
- package/src/files/handlers/__tests__/resource-file-upload-handler.backend.service.test.ts +392 -0
- package/src/files/handlers/resource-file-upload-handler.backend.service.ts +605 -0
- package/src/files/rag/weaviate-vector-store.backend.service.ts +271 -0
- package/src/files/scanning/clamav-scanner.backend.service.ts +214 -0
- package/src/files/scanning/file-scan.types.ts +17 -0
- package/src/files/scanning/yara-scanner.backend.service.ts +212 -0
- package/src/files/services/__tests__/file-field-detection.backend.service.test.ts +91 -0
- package/src/files/services/__tests__/file-operation-handler.backend.service.test.ts +272 -0
- package/src/files/services/__tests__/file-population.backend.service.test.ts +120 -0
- package/src/files/services/__tests__/file-scanning.backend.service.test.ts +163 -0
- package/src/files/services/__tests__/files.backend.service.test.ts +885 -0
- package/src/files/services/__tests__/mock-file-field-detection.service.ts +43 -0
- package/src/files/services/__tests__/mock-file-operation-handler.service.ts +113 -0
- package/src/files/services/__tests__/mock-file-repository.service.ts +104 -0
- package/src/files/services/file-field-detection.backend.service.ts +156 -0
- package/src/files/services/file-operation-handler.backend.service.ts +861 -0
- package/src/files/services/file-population.backend.service.ts +485 -0
- package/src/files/services/file-rag-indexing.backend.service.ts +229 -0
- package/src/files/services/file-scanning.backend.service.ts +373 -0
- package/src/files/services/file-text-extraction.backend.service.ts +193 -0
- package/src/files/services/files.backend.service.ts +1356 -0
- package/src/files/storage/file-storage-path-resolver.backend.service.ts +289 -0
- package/src/files/storage/file-storage-provider.types.ts +188 -0
- package/src/files/storage/file-storage-router.backend.service.ts +172 -0
- package/src/files/storage/local-directory-storage-provider.backend.service.ts +417 -0
- package/src/files/storage/wildo-managed-storage-provider.backend.service.ts +530 -0
- package/src/files/utils/__tests__/file-field-schema-path.backend.utils.test.ts +44 -0
- package/src/files/utils/__tests__/file-uploader.utils.test.ts +57 -0
- package/src/files/utils/__tests__/file-validation.utils.test.ts +559 -0
- package/src/files/utils/file-field-schema-path.backend.utils.ts +385 -0
- package/src/files/utils/file-upload.utils.ts +146 -0
- package/src/files/utils/file-uploader.utils.ts +65 -0
- package/src/files/utils/file-validation.utils.ts +753 -0
- package/src/flows-actors/agent-catalogs.backend.ts +427 -0
- package/src/flows-actors/controllers/flows-actors.controller.ts +91 -0
- package/src/flows-actors/models/agent-catalogs.backend.definitions.ts +430 -0
- package/src/flows-actors/models/agent-facets.backend.definitions.ts +120 -0
- package/src/flows-actors/models/agents.backend.definitions.ts +4 -0
- package/src/flows-actors/models/core-facets.backend.definitions.ts +348 -0
- package/src/flows-actors/models/flows-actors.backend.definitions.ts +13 -0
- package/src/flows-actors/models/flows-actors.backend.schemas.ts +44 -0
- package/src/flows-actors/services/__tests__/agent-facets-catalogs.test.ts +544 -0
- package/src/flows-actors/services/__tests__/agents.backend.service.cli-runtime.test.ts +234 -0
- package/src/flows-actors/services/actors-system.backend.service.ts +270 -0
- package/src/flows-actors/services/agent-facets.backend.service.ts +350 -0
- package/src/flows-actors/services/agents.backend.service.ts +2730 -0
- package/src/flows-actors/services/context-curation.backend.service.ts +203 -0
- package/src/flows-actors/services/flows-actors-registry.service.ts +374 -0
- package/src/flows-actors/services/flows.backend.services.ts +237 -0
- package/src/flows-actors/services/prompt-compiler.backend.service.ts +734 -0
- package/src/flows-actors/utils/__tests__/cli-runtime-operation-support.backend.utils.test.ts +95 -0
- package/src/flows-actors/utils/cli-runtime-operation-support.backend.utils.ts +87 -0
- package/src/flows-actors/utils/cli-runtime-runner.backend.utils.ts +171 -0
- package/src/flows-actors/utils/flows-actors-frontend-extractor.utils.ts +63 -0
- package/src/flows-actors/utils/prompt-ir-adapters.backend.utils.ts +257 -0
- package/src/guidance/batches/dormancy-detection.batch.backend.service.ts +126 -0
- package/src/guidance/services/__tests__/guidance-trigger-evaluator.backend.service.test.ts +49 -0
- package/src/guidance/services/__tests__/lifecycle-evaluator.backend.service.test.ts +85 -0
- package/src/guidance/services/__tests__/milestone-definition-registry.backend.service.test.ts +211 -0
- package/src/guidance/services/__tests__/milestone-evaluator.backend.service.test.ts +561 -0
- package/src/guidance/services/guidance-trigger-evaluator.backend.service.ts +151 -0
- package/src/guidance/services/lifecycle-custom-implementations.backend.ts +139 -0
- package/src/guidance/services/lifecycle-evaluator.backend.service.ts +908 -0
- package/src/guidance/services/milestone-condition-registry.backend.service.ts +57 -0
- package/src/guidance/services/milestone-definition-registry.backend.service.ts +265 -0
- package/src/guidance/services/milestone-evaluator.backend.service.ts +611 -0
- package/src/i18n/controllers/i18n-controller.backend.service.ts +227 -0
- package/src/i18n/services/i18n.backend.service.ts +88 -0
- package/src/index.ts +286 -0
- package/src/inject/models/container.ts +586 -0
- package/src/inject/models/service-types.ts +488 -0
- package/src/monitoring/analytics/controllers/analytics.backend.controller.ts +114 -0
- package/src/monitoring/analytics/services/value-moment-engine.backend.service.ts +53 -0
- package/src/monitoring/analytics/services/value-moment-handler-registry.backend.service.ts +38 -0
- package/src/monitoring/logger/middleware/logging.middleware.ts +40 -0
- package/src/monitoring/logger/models/logger.backend.schemas.ts +56 -0
- package/src/monitoring/logger/services/__tests__/mock-logger.service.ts +49 -0
- package/src/monitoring/logger/services/logger.service.ts +214 -0
- package/src/monitoring/observability/middleware/metrics.middleware.ts +205 -0
- package/src/monitoring/observability/middleware/telemetry.middleware.ts +188 -0
- package/src/monitoring/observability/middleware/tracing.middleware.ts +265 -0
- package/src/monitoring/observability/models/observability.backend.schemas.ts +96 -0
- package/src/monitoring/observability/services/instrumentations/custom.instrumentations.ts +132 -0
- package/src/monitoring/observability/services/metrics.service.ts +266 -0
- package/src/monitoring/observability/services/telemetry.service.ts +157 -0
- package/src/monitoring/observability/services/tracer.service.ts +334 -0
- package/src/notifications/email/components/email-components.ts +341 -0
- package/src/notifications/email/models/email-context-provider.interface.ts +107 -0
- package/src/notifications/email/models/email-template-definition.ts +74 -0
- package/src/notifications/email/models/email-template.actors-system.backend.definitions.ts +80 -0
- package/src/notifications/email/models/email.backend.scheamas.ts +0 -0
- package/src/notifications/email/services/email-batch-send.batch.backend.service.ts +236 -0
- package/src/notifications/email/services/email-context-provider-registry.backend.service.ts +157 -0
- package/src/notifications/email/services/email-renderer.backend.service.ts +274 -0
- package/src/notifications/email/services/email-template-compiler.backend.service.ts +136 -0
- package/src/notifications/email/services/email-template-generation.backend.service.ts +811 -0
- package/src/notifications/email/services/email-template-registry.backend.service.ts +166 -0
- package/src/notifications/email/services/email-template-sandbox.backend.service.ts +255 -0
- package/src/notifications/email/services/email-template-validator.backend.service.ts +229 -0
- package/src/notifications/email/services/email.backend.service.ts +429 -0
- package/src/notifications/email/utils/color-conversion.utils.ts +142 -0
- package/src/notifications/email/utils/interpolate-email-label.utils.ts +16 -0
- package/src/notifications/email/utils/zod-to-typescript.utils.ts +352 -0
- package/src/notifications/services/__tests__/notifications-dispatcher.operation-semantics.test.ts +773 -0
- package/src/notifications/services/__tests__/notifications-dispatcher.websocket-integration.test.ts +173 -0
- package/src/notifications/services/notification-badge.backend.service.ts +412 -0
- package/src/notifications/services/notifications-dispatcher.backend.service.ts +1696 -0
- package/src/notifications/sms/services/sms.backend.service.ts +283 -0
- package/src/notifications/webhooks/controllers/webhook-auto-controller.backend.service.ts +220 -0
- package/src/notifications/webhooks/services/polymorphic-lookup.backend.service.ts +131 -0
- package/src/notifications/webhooks/services/webhook-handler.backend.service.ts +481 -0
- package/src/organizations/services/__tests__/org-creation-on-registration.backend.utils.test.ts +193 -0
- package/src/organizations/services/__tests__/org-member-roles-validation.backend.utils.test.ts +101 -0
- package/src/organizations/services/__tests__/organization-custom-implementation.backend.service.test.ts +113 -0
- package/src/organizations/services/__tests__/scim-provisioning-gate.backend.utils.test.ts +94 -0
- package/src/organizations/services/__tests__/user-org-type-grant.backend.utils.test.ts +164 -0
- package/src/organizations/services/__tests__/user-type-revocation-on-org-leave.backend.utils.test.ts +161 -0
- package/src/organizations/services/org-creation-on-registration.backend.utils.ts +119 -0
- package/src/organizations/services/org-member-roles-validation.backend.utils.ts +51 -0
- package/src/organizations/services/organization-custom-implementation.backend.service.ts +106 -0
- package/src/organizations/services/organization-member-custom-implementation.backend.service.ts +150 -0
- package/src/organizations/services/scim-provisioning-gate.backend.utils.ts +34 -0
- package/src/organizations/services/user-org-type-grant.backend.utils.ts +49 -0
- package/src/organizations/services/user-type-revocation-on-org-leave.backend.utils.ts +102 -0
- package/src/queue/adapters/rabbitmq-adapter.backend.service.ts +494 -0
- package/src/queue/apps-crontabs-manager.backend.service.ts +258 -0
- package/src/queue/cron-job-sync.backend.service.ts +184 -0
- package/src/queue/domain-queue-consumer.backend.service.ts +333 -0
- package/src/queue/job-completion-registry.backend.service.ts +342 -0
- package/src/queue/job-consumer.backend.service.ts +646 -0
- package/src/queue/job-executor.backend.service.ts +315 -0
- package/src/queue/job-payload-storage.backend.service.ts +297 -0
- package/src/queue/job-status-tracking.backend.service.ts +376 -0
- package/src/queue/queue-monitoring.backend.service.ts +333 -0
- package/src/queue/queue-worker-initializer.backend.service.ts +179 -0
- package/src/queue/queue.backend.service.ts +530 -0
- package/src/queue/scheduled-message-verifier.backend.service.ts +228 -0
- package/src/queue/worker-shutdown-manager.backend.service.ts +298 -0
- package/src/requests/models/api-routes.backend.defintions.ts +45 -0
- package/src/requests/models/requests.backend.schemas.ts +73 -0
- package/src/requests/service/__tests__/websocket.service.auth-refresh.test.ts +361 -0
- package/src/requests/service/__tests__/websocket.service.resource-room-validation.test.ts +234 -0
- package/src/requests/service/__tests__/websocket.service.variant-authorization.test.ts +94 -0
- package/src/requests/service/platform-mutualized-handler.backend.service.ts +19 -0
- package/src/requests/service/platform-requests.backend.utils.ts +54 -0
- package/src/requests/service/remote-client-base.backend.service.ts +485 -0
- package/src/requests/service/serverless-services-handler.backend.service.ts +19 -0
- package/src/requests/service/websocket.service.ts +2844 -0
- package/src/resources/models/custom-service-implementations.backend.definition.ts +22 -0
- package/src/resources/models/index.ts +7 -0
- package/src/resources/models/resources-operations.backend.definitions.ts +9 -0
- package/src/resources/models/resources-relationships.backend.definitions.ts +30 -0
- package/src/resources/models/resources-types.backend.schemas.ts +14 -0
- package/src/resources/models/resources.backend.schemas.ts +6 -0
- package/src/resources/models/virtual-fields.backend.types.ts +132 -0
- package/src/resources/services/__tests__/mock-resources-registry.service.ts +69 -0
- package/src/resources/services/__tests__/resource-id.backend.service.test.ts +69 -0
- package/src/resources/services/resource-context.backend.service.ts +1107 -0
- package/src/resources/services/resource-id.backend.service.ts +280 -0
- package/src/resources/services/resource-population.backend.service.ts +761 -0
- package/src/resources/services/resources-registry.backend.service.ts +1126 -0
- package/src/resources/services/virtual-fields.backend.service.ts +303 -0
- package/src/runtime/__tests__/execution-context-creator.backend.service.test.ts +469 -0
- package/src/runtime/controllers/health-controller.backend.service.ts +297 -0
- package/src/runtime/domain-module.backend.definitions.test.ts +83 -0
- package/src/runtime/domain-module.backend.definitions.ts +161 -0
- package/src/runtime/models/execution-context.backend.schemas.ts +456 -0
- package/src/runtime/models/runtime.backend.schemas.ts +82 -0
- package/src/runtime/services/execution-context-creator.backend.service.ts +2102 -0
- package/src/runtime/services/execution-context-handler.backend.service.ts +224 -0
- package/src/runtime/services/health-readiness-contributor.backend.interface.ts +11 -0
- package/src/runtime/services/http-server.backend.service.ts +870 -0
- package/src/runtime/services/start-application.backend.service.ts +1109 -0
- package/src/runtime/testing/execution-context-test-fixtures.ts +14 -0
- package/src/runtime/testing/mock-execution-context-creator.service.ts +46 -0
- package/src/runtime/utils/scan-default-exports.backend.utils.ts +247 -0
- package/src/security/authentications/__tests__/auth-registration.test.ts +338 -0
- package/src/security/authentications/__tests__/authentication-controller.test.ts +31 -0
- package/src/security/authentications/__tests__/authentication-orchestrator.test.ts +27 -0
- package/src/security/authentications/__tests__/saml-assertion-validator.test.ts +631 -0
- package/src/security/authentications/__tests__/saml-authentication.test.ts +126 -0
- package/src/security/authentications/__tests__/saml-integration-test-helpers.test.ts +234 -0
- package/src/security/authentications/__tests__/saml-metadata.test.ts +185 -0
- package/src/security/authentications/__tests__/saml-replay-guard.test.ts +99 -0
- package/src/security/authentications/__tests__/saml-sso-flow.integration.test.ts +355 -0
- package/src/security/authentications/__tests__/saml-test-fixtures.test.ts +433 -0
- package/src/security/authentications/__tests__/saml-test-parser.test.ts +117 -0
- package/src/security/authentications/__tests__/sso-connection-custom-ops.integration.test.ts +236 -0
- package/src/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.ts +71 -0
- package/src/security/authentications/controllers/auth-method-management-controller.backend.service.ts +205 -0
- package/src/security/authentications/controllers/authentication-controller.backend.service.ts +2712 -0
- package/src/security/authentications/models/auth-constants.backend.ts +141 -0
- package/src/security/authentications/models/authentications.backend.schemas.ts +106 -0
- package/src/security/authentications/models/jwt.backend.schemas.ts +107 -0
- package/src/security/authentications/models/oauth2-connection.backend.schemas.ts +196 -0
- package/src/security/authentications/models/saml-authentication.backend.schemas.ts +124 -0
- package/src/security/authentications/models/sso-connection.backend.schemas.ts +104 -0
- package/src/security/authentications/services/__tests__/mock-auth-execution-context-factory.service.ts +73 -0
- package/src/security/authentications/services/__tests__/mock-auth-token-issuer.service.ts +46 -0
- package/src/security/authentications/services/admin-config/__tests__/mock-domain-to-org-lookup.service.ts +40 -0
- package/src/security/authentications/services/admin-config/__tests__/mock-enterprise-user-provisioning.service.ts +67 -0
- package/src/security/authentications/services/admin-config/auth-organization-configuration.service.ts +424 -0
- package/src/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.ts +244 -0
- package/src/security/authentications/services/admin-config/domain-verification.backend.service.ts +215 -0
- package/src/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.ts +509 -0
- package/src/security/authentications/services/admin-config/oidc-discovery.backend.service.ts +250 -0
- package/src/security/authentications/services/anonymous-session.backend.service.ts +442 -0
- package/src/security/authentications/services/auth-credential-verifier.backend.service.ts +147 -0
- package/src/security/authentications/services/auth-execution-context-factory.backend.service.ts +132 -0
- package/src/security/authentications/services/auth-methods/auth-method-management.backend.service.ts +532 -0
- package/src/security/authentications/services/auth-methods/auth-mfa.backend.service.ts +141 -0
- package/src/security/authentications/services/auth-methods/auth-password-reset.backend.service.ts +215 -0
- package/src/security/authentications/services/auth-methods/auth-phone-verification.backend.service.ts +136 -0
- package/src/security/authentications/services/auth-methods/auth-registration.backend.service.ts +994 -0
- package/src/security/authentications/services/auth-methods/oauth2-authentication.backend.service.ts +1210 -0
- package/src/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.ts +903 -0
- package/src/security/authentications/services/auth-methods/saml-assertion-validator.backend.service.ts +791 -0
- package/src/security/authentications/services/auth-methods/saml-authentication.backend.service.ts +1727 -0
- package/src/security/authentications/services/auth-methods/saml-metadata.backend.service.ts +432 -0
- package/src/security/authentications/services/auth-methods/saml-replay-guard.backend.service.ts +90 -0
- package/src/security/authentications/services/auth-methods/webauthn.backend.service.ts +393 -0
- package/src/security/authentications/services/auth-session-store.backend.service.ts +211 -0
- package/src/security/authentications/services/auth-token-issuer.backend.service.ts +496 -0
- package/src/security/authentications/services/authentication-orchestrator.backend.service.ts +3156 -0
- package/src/security/authentications/services/custom-impls/auth-custom-implementations.backend.ts +88 -0
- package/src/security/authentications/services/custom-impls/auth-policy.custom-impl.backend.service.ts +54 -0
- package/src/security/authentications/services/custom-impls/scim-provisioning-config.custom-impl.backend.service.ts +167 -0
- package/src/security/authentications/services/custom-impls/scim-tokens.custom-impl.backend.service.ts +136 -0
- package/src/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.ts +123 -0
- package/src/security/authentications/services/custom-impls/siem-export-config.custom-impl.backend.service.ts +161 -0
- package/src/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.ts +185 -0
- package/src/security/authentications/services/custom-impls/sso-connection.custom-impl.backend.service.ts +792 -0
- package/src/security/authentications/services/utils/__tests__/mock-auth-user-lookup.service.ts +62 -0
- package/src/security/authentications/services/utils/auth-controller.utils.ts +51 -0
- package/src/security/authentications/services/utils/auth-credential-ops.backend.service.ts +202 -0
- package/src/security/authentications/services/utils/auth-response-helper.backend.service.ts +38 -0
- package/src/security/authentications/services/utils/auth-user-lookup.backend.service.ts +128 -0
- package/src/security/authentications/services/utils/saml-java-availability.ts +64 -0
- package/src/security/authorizations/__tests__/authorizations.backend.service.test.ts +82 -0
- package/src/security/authorizations/services/authorizations.backend.service.ts +934 -0
- package/src/security/consumable-tokens/batches/consumable-tokens-cleanup.batch.backend.service.ts +168 -0
- package/src/security/consumable-tokens/models/consumable-tokens.backend.resources-config.schemas.ts +92 -0
- package/src/security/consumable-tokens/models/consumable-tokens.shared.schemas.ts +86 -0
- package/src/security/consumable-tokens/models/index.ts +3 -0
- package/src/security/consumable-tokens/services/__tests__/mock-consumable-token.service.ts +63 -0
- package/src/security/consumable-tokens/services/consumable-token.backend.service.ts +568 -0
- package/src/security/jwt/services/auth-jwt-guard.backend.service.ts +137 -0
- package/src/security/jwt/services/jwt.backend.service.ts +397 -0
- package/src/security/scim/__tests__/scim-filter-parser.test.ts +121 -0
- package/src/security/scim/controllers/scim.backend.controller.ts +1066 -0
- package/src/security/scim/models/scim-protocol.backend.schemas.ts +258 -0
- package/src/security/scim/utils/scim-filter-parser.ts +289 -0
- package/src/security/scim/utils/scim-response-formatter.ts +122 -0
- package/src/testing.ts +30 -0
- package/src/types/xmldom.d.ts +9 -0
- package/src/users/services/user-self-custom-implementations.backend.ts +62 -0
|
@@ -0,0 +1,2712 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { injectable, inject } from 'inversify';
|
|
3
|
+
import express, { Request, Response, NextFunction } from 'express';
|
|
4
|
+
import { AbstractControllerBackendService } from '~wildo-backend-lib/base-classes/services/controllers/abstract-controller.backend.service';
|
|
5
|
+
import { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';
|
|
6
|
+
import { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';
|
|
7
|
+
import { ErrorHandlerService } from '~wildo-backend-lib/errors/services/error-handler.backend.service';
|
|
8
|
+
import { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';
|
|
9
|
+
import { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';
|
|
10
|
+
import { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';
|
|
11
|
+
import { AuthenticationOrchestratorBackendService } from '~wildo-backend-lib/security/authentications/services/authentication-orchestrator.backend.service';
|
|
12
|
+
import { AuthTokenIssuerBackendService } from '~wildo-backend-lib/security/authentications/services/auth-token-issuer.backend.service';
|
|
13
|
+
import { OAuth2AuthenticationBackendService } from '~wildo-backend-lib/security/authentications/services/auth-methods/oauth2-authentication.backend.service';
|
|
14
|
+
import { OAuth2ConnectionResolverBackendService } from '~wildo-backend-lib/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service';
|
|
15
|
+
import { ConsumableTokenBackendService } from '~wildo-backend-lib/security/consumable-tokens/services/consumable-token.backend.service';
|
|
16
|
+
import { JwtBackendService } from '~wildo-backend-lib/security/jwt/services/jwt.backend.service';
|
|
17
|
+
import { WebAuthnBackendService } from '~wildo-backend-lib/security/authentications/services/auth-methods/webauthn.backend.service';
|
|
18
|
+
import { DomainToOrgLookupBackendService } from '~wildo-backend-lib/security/authentications/services/admin-config/domain-to-org-lookup.backend.service';
|
|
19
|
+
import { SAMLAuthenticationBackendService } from '~wildo-backend-lib/security/authentications/services/auth-methods/saml-authentication.backend.service';
|
|
20
|
+
import { SAMLMetadataBackendService } from '~wildo-backend-lib/security/authentications/services/auth-methods/saml-metadata.backend.service';
|
|
21
|
+
import { EmailBackendService } from '~wildo-backend-lib/notifications/email/services/email.backend.service';
|
|
22
|
+
import { SMSBackendService } from '~wildo-backend-lib/notifications/sms/services/sms.backend.service';
|
|
23
|
+
import { AuthExecutionContextFactoryBackendService } from '~wildo-backend-lib/security/authentications/services/auth-execution-context-factory.backend.service';
|
|
24
|
+
import type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';
|
|
25
|
+
import { AUTH_REDIS_KEYS, AUTH_OPERATION, AuthSource } from '~wildo-backend-lib/security/authentications/models/auth-constants.backend';
|
|
26
|
+
import { AuthControllerUtils } from '~wildo-backend-lib/security/authentications/services/utils/auth-controller.utils';
|
|
27
|
+
import { AuthResponseHelperBackendService } from '~wildo-backend-lib/security/authentications/services/utils/auth-response-helper.backend.service';
|
|
28
|
+
import { AuthJwtGuardBackendService } from '~wildo-backend-lib/security/jwt/services/auth-jwt-guard.backend.service';
|
|
29
|
+
import { AuthPasswordResetBackendService } from '~wildo-backend-lib/security/authentications/services/auth-methods/auth-password-reset.backend.service';
|
|
30
|
+
import { AuthRegistrationBackendService } from '~wildo-backend-lib/security/authentications/services/auth-methods/auth-registration.backend.service';
|
|
31
|
+
import { AuthMfaBackendService } from '~wildo-backend-lib/security/authentications/services/auth-methods/auth-mfa.backend.service';
|
|
32
|
+
import { AuthPhoneVerificationBackendService } from '~wildo-backend-lib/security/authentications/services/auth-methods/auth-phone-verification.backend.service';
|
|
33
|
+
import { AuthMethodManagementBackendService } from '~wildo-backend-lib/security/authentications/services/auth-methods/auth-method-management.backend.service';
|
|
34
|
+
import { AnonymousSessionBackendService } from '~wildo-backend-lib/security/authentications/services/anonymous-session.backend.service';
|
|
35
|
+
import { AuthUserLookupBackendService } from '~wildo-backend-lib/security/authentications/services/utils/auth-user-lookup.backend.service';
|
|
36
|
+
import { RateLimitBackendService } from '~wildo-backend-lib/errors/services/rate-limit.backend.service';
|
|
37
|
+
import { z } from 'zod';
|
|
38
|
+
import {
|
|
39
|
+
AuthIdentificationRequestSchema,
|
|
40
|
+
AuthenticationRequestSchema,
|
|
41
|
+
AuthLoginFormDtoSchema,
|
|
42
|
+
PasswordResetRequestDtoSchema,
|
|
43
|
+
PasswordResetCompleteDtoSchema,
|
|
44
|
+
UserRegisterApiDtoSchema,
|
|
45
|
+
UserInvitationApiDtoSchema,
|
|
46
|
+
UserInvitationRejectApiDtoSchema,
|
|
47
|
+
EmailVerifyDtoSchema,
|
|
48
|
+
NativeTokenExchangeRequestSchema,
|
|
49
|
+
AuthMethod,
|
|
50
|
+
AuthFactorLevel,
|
|
51
|
+
AuthenticationSessionState,
|
|
52
|
+
CoreConsumableTokenTypes,
|
|
53
|
+
ConsumableToken_ConsumptionMode,
|
|
54
|
+
ConsumableTokenTypesSchema,
|
|
55
|
+
CoreResourceType,
|
|
56
|
+
CoreResourceOperation,
|
|
57
|
+
CoreAuditableEventType,
|
|
58
|
+
ResourceOperationVariantType,
|
|
59
|
+
ResourceOperationRiskLevel,
|
|
60
|
+
ResourcePrimaryScope,
|
|
61
|
+
CORE_APP_ROLES,
|
|
62
|
+
UserStatus,
|
|
63
|
+
SsoConnectionType,
|
|
64
|
+
EmailTemplateType,
|
|
65
|
+
SystemEmailTemplateRef,
|
|
66
|
+
ErrorType,
|
|
67
|
+
ErrorCustomMessageReference,
|
|
68
|
+
isWildoBackendError,
|
|
69
|
+
MANUAL_CONTROLLER_ROUTES_URLS,
|
|
70
|
+
ManualControllerRouteKey,
|
|
71
|
+
AuthRedirectErrorCode,
|
|
72
|
+
AuthScopeType,
|
|
73
|
+
SessionType,
|
|
74
|
+
WildoHeaderKeys,
|
|
75
|
+
} from '@wildo-ai/saas-models';
|
|
76
|
+
import { DurationUnit } from '@wildo-ai/zod-decorators';
|
|
77
|
+
import type { AuthIdentificationResponse, AuthenticationRequest, AuthenticationResponse, User } from '@wildo-ai/saas-models';
|
|
78
|
+
import { MagicLinkSendRequestSchema, MagicLinkVerifyRequestSchema, PhoneVerifySendRequestSchema, PhoneVerifyConfirmRequestSchema } from '@wildo-ai/saas-models';
|
|
79
|
+
import { AvailableLanguage, AuthResponseMessageRef, BackendSmsMessageRef } from '@wildo-ai/presets-components-models';
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
// Password auth body extends the shared login form DTO with session/method/factor fields
|
|
83
|
+
// that are added programmatically by the frontend service layer.
|
|
84
|
+
const PasswordAuthBodySchema = AuthLoginFormDtoSchema.extend({
|
|
85
|
+
sessionId: z.string(),
|
|
86
|
+
method: z.literal(AuthMethod.PASSWORD),
|
|
87
|
+
factorLevel: z.literal(AuthFactorLevel.FIRST),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const RefreshTokenBodySchema = z.object({
|
|
91
|
+
refreshToken: z.string().min(1),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const TokenExchangeBodySchema = z.object({
|
|
95
|
+
code: z.string().min(1),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const LogoutBodySchema = z.object({
|
|
99
|
+
refreshToken: z.string().min(1),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const CreateOneOffTokenRequestSchema = z.object({
|
|
103
|
+
userId: z.string().min(1),
|
|
104
|
+
tokenType: ConsumableTokenTypesSchema,
|
|
105
|
+
consumeAt: z.enum(['EXCHANGE', 'TARGET_OPERATION']),
|
|
106
|
+
consumptionMode: z.enum(ConsumableToken_ConsumptionMode).optional().default(ConsumableToken_ConsumptionMode.SINGLE_USE),
|
|
107
|
+
maxUses: z.number().int().min(1).optional(),
|
|
108
|
+
expiresIn: z.object({
|
|
109
|
+
value: z.number().int().min(1),
|
|
110
|
+
unit: z.enum(['minutes', 'hours', 'days']),
|
|
111
|
+
}).optional().default({ value: 24, unit: 'hours' }),
|
|
112
|
+
resourceIdentifier: z.string().optional(),
|
|
113
|
+
relatedId: z.string().optional(),
|
|
114
|
+
metadata: z.record(z.string(), z.any()).optional(),
|
|
115
|
+
targeting: z.object({
|
|
116
|
+
initiatorIds: z.record(z.string(), z.string()).optional(),
|
|
117
|
+
}).optional(),
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const OneOffSessionExchangeBodySchema = z.object({
|
|
121
|
+
token: z.string().min(1),
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
@injectable()
|
|
125
|
+
export class AuthenticationControllerBackendService extends AbstractControllerBackendService {
|
|
126
|
+
private readonly authService: AuthenticationOrchestratorBackendService;
|
|
127
|
+
private readonly tokenIssuer: AuthTokenIssuerBackendService;
|
|
128
|
+
private readonly oauth2Service: OAuth2AuthenticationBackendService;
|
|
129
|
+
private readonly oauth2Resolver: OAuth2ConnectionResolverBackendService;
|
|
130
|
+
private readonly consumableTokenService: ConsumableTokenBackendService;
|
|
131
|
+
private readonly jwtService: JwtBackendService;
|
|
132
|
+
private readonly emailService: EmailBackendService;
|
|
133
|
+
private readonly appConfigService: AppConfigurationService;
|
|
134
|
+
private readonly auditLogsService: AuditLogsBackendService;
|
|
135
|
+
private readonly rateLimitService: RateLimitBackendService;
|
|
136
|
+
private readonly webAuthnService: WebAuthnBackendService;
|
|
137
|
+
private readonly smsService: SMSBackendService;
|
|
138
|
+
private readonly domainToOrgLookup: DomainToOrgLookupBackendService;
|
|
139
|
+
private readonly samlAuthService: SAMLAuthenticationBackendService;
|
|
140
|
+
private readonly samlMetadataService: SAMLMetadataBackendService;
|
|
141
|
+
private readonly authResponseHelper: AuthResponseHelperBackendService;
|
|
142
|
+
private readonly authJwtGuard: AuthJwtGuardBackendService;
|
|
143
|
+
private readonly passwordResetService: AuthPasswordResetBackendService;
|
|
144
|
+
private readonly registrationService: AuthRegistrationBackendService;
|
|
145
|
+
private readonly mfaService: AuthMfaBackendService;
|
|
146
|
+
private readonly phoneVerificationService: AuthPhoneVerificationBackendService;
|
|
147
|
+
private readonly methodManagementService: AuthMethodManagementBackendService;
|
|
148
|
+
private readonly anonymousSessionService: AnonymousSessionBackendService;
|
|
149
|
+
private readonly userLookup: AuthUserLookupBackendService;
|
|
150
|
+
|
|
151
|
+
constructor(
|
|
152
|
+
@inject(SAAS_SERVICE_TYPES.Logger) logger: LoggerService,
|
|
153
|
+
@inject(SAAS_SERVICE_TYPES.ErrorBuilderService) errorBuilder: ErrorBuilderBackendService,
|
|
154
|
+
@inject(SAAS_SERVICE_TYPES.ErrorHandlerService) errorHandler: ErrorHandlerService,
|
|
155
|
+
@inject(SAAS_SERVICE_TYPES.AuthenticationOrchestratorService) authService: AuthenticationOrchestratorBackendService,
|
|
156
|
+
@inject(SAAS_SERVICE_TYPES.AuthTokenIssuer) tokenIssuer: AuthTokenIssuerBackendService,
|
|
157
|
+
@inject(SAAS_SERVICE_TYPES.OAuth2AuthenticationService) oauth2Service: OAuth2AuthenticationBackendService,
|
|
158
|
+
@inject(SAAS_SERVICE_TYPES.OAuth2ConnectionResolverService) oauth2Resolver: OAuth2ConnectionResolverBackendService,
|
|
159
|
+
@inject(SAAS_SERVICE_TYPES.ConsumableTokenService) consumableTokenService: ConsumableTokenBackendService,
|
|
160
|
+
@inject(SAAS_SERVICE_TYPES.JwtBackendService) jwtService: JwtBackendService,
|
|
161
|
+
@inject(SAAS_SERVICE_TYPES.EmailService) emailService: EmailBackendService,
|
|
162
|
+
@inject(SAAS_SERVICE_TYPES.AuthExecutionContextFactory) private readonly authEcFactory: AuthExecutionContextFactoryBackendService,
|
|
163
|
+
@inject(SAAS_SERVICE_TYPES.AppConfigService) appConfigService: AppConfigurationService,
|
|
164
|
+
@inject(SAAS_SERVICE_TYPES.AuditLogsService) auditLogsService: AuditLogsBackendService,
|
|
165
|
+
@inject(SAAS_SERVICE_TYPES.RateLimitBackendService) rateLimitService: RateLimitBackendService,
|
|
166
|
+
@inject(SAAS_SERVICE_TYPES.WebAuthnService) webAuthnService: WebAuthnBackendService,
|
|
167
|
+
@inject(SAAS_SERVICE_TYPES.SMSService) smsService: SMSBackendService,
|
|
168
|
+
@inject(SAAS_SERVICE_TYPES.DomainToOrgLookupService) domainToOrgLookup: DomainToOrgLookupBackendService,
|
|
169
|
+
@inject(SAAS_SERVICE_TYPES.SAMLAuthenticationService) samlAuthService: SAMLAuthenticationBackendService,
|
|
170
|
+
@inject(SAAS_SERVICE_TYPES.SAMLMetadataService) samlMetadataService: SAMLMetadataBackendService,
|
|
171
|
+
@inject(SAAS_SERVICE_TYPES.AuthResponseHelperService) authResponseHelper: AuthResponseHelperBackendService,
|
|
172
|
+
@inject(SAAS_SERVICE_TYPES.AuthJwtGuardService) authJwtGuard: AuthJwtGuardBackendService,
|
|
173
|
+
@inject(SAAS_SERVICE_TYPES.AuthPasswordResetService) passwordResetService: AuthPasswordResetBackendService,
|
|
174
|
+
@inject(SAAS_SERVICE_TYPES.AuthRegistrationService) registrationService: AuthRegistrationBackendService,
|
|
175
|
+
@inject(SAAS_SERVICE_TYPES.AuthMfaService) mfaService: AuthMfaBackendService,
|
|
176
|
+
@inject(SAAS_SERVICE_TYPES.AuthPhoneVerificationService) phoneVerificationService: AuthPhoneVerificationBackendService,
|
|
177
|
+
@inject(SAAS_SERVICE_TYPES.AuthMethodManagementService) methodManagementService: AuthMethodManagementBackendService,
|
|
178
|
+
@inject(SAAS_SERVICE_TYPES.AnonymousSessionService) anonymousSessionService: AnonymousSessionBackendService,
|
|
179
|
+
@inject(SAAS_SERVICE_TYPES.AuthUserLookupService) userLookup: AuthUserLookupBackendService,
|
|
180
|
+
) {
|
|
181
|
+
super(logger, errorBuilder, errorHandler, 'AuthenticationController');
|
|
182
|
+
this.authService = authService;
|
|
183
|
+
this.tokenIssuer = tokenIssuer;
|
|
184
|
+
this.oauth2Service = oauth2Service;
|
|
185
|
+
this.oauth2Resolver = oauth2Resolver;
|
|
186
|
+
this.consumableTokenService = consumableTokenService;
|
|
187
|
+
this.jwtService = jwtService;
|
|
188
|
+
this.emailService = emailService;
|
|
189
|
+
this.appConfigService = appConfigService;
|
|
190
|
+
this.auditLogsService = auditLogsService;
|
|
191
|
+
this.rateLimitService = rateLimitService;
|
|
192
|
+
this.webAuthnService = webAuthnService;
|
|
193
|
+
this.smsService = smsService;
|
|
194
|
+
this.domainToOrgLookup = domainToOrgLookup;
|
|
195
|
+
this.samlAuthService = samlAuthService;
|
|
196
|
+
this.samlMetadataService = samlMetadataService;
|
|
197
|
+
this.authResponseHelper = authResponseHelper;
|
|
198
|
+
this.authJwtGuard = authJwtGuard;
|
|
199
|
+
this.passwordResetService = passwordResetService;
|
|
200
|
+
this.registrationService = registrationService;
|
|
201
|
+
this.mfaService = mfaService;
|
|
202
|
+
this.phoneVerificationService = phoneVerificationService;
|
|
203
|
+
this.methodManagementService = methodManagementService;
|
|
204
|
+
this.anonymousSessionService = anonymousSessionService;
|
|
205
|
+
this.userLookup = userLookup;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
protected setupRoutes(): void {
|
|
209
|
+
// ─── Existing Authentication Routes ───
|
|
210
|
+
|
|
211
|
+
// User/Customer identification
|
|
212
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_IDENTIFY], this.asyncHandler(this.identify.bind(this)));
|
|
213
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_IDENTIFY], 'Identify user/customer and get available methods');
|
|
214
|
+
|
|
215
|
+
// Authentication methods
|
|
216
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_AUTHENTICATE_PASSWORD], this.asyncHandler(this.authenticatePassword.bind(this)));
|
|
217
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_AUTHENTICATE_PASSWORD], 'Authenticate with password');
|
|
218
|
+
|
|
219
|
+
// Generic authentication endpoint for all methods
|
|
220
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_AUTHENTICATE], this.asyncHandler(this.authenticate.bind(this)));
|
|
221
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_AUTHENTICATE], 'Universal authentication endpoint (all methods)');
|
|
222
|
+
|
|
223
|
+
// Token refresh (TRAP 11: NOT behind JWT auth — user's access token may be expired)
|
|
224
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_TOKEN_REFRESH], this.asyncHandler(this.refreshToken.bind(this)));
|
|
225
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_TOKEN_REFRESH], 'Refresh access token using refresh token');
|
|
226
|
+
|
|
227
|
+
// Session management
|
|
228
|
+
this.router.get(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SESSION_STATE], this.asyncHandler(this.getSessionState.bind(this)));
|
|
229
|
+
this.logRouteRegistration('GET', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SESSION_STATE], 'Get authentication session state');
|
|
230
|
+
|
|
231
|
+
// ─── OAuth2 Routes (Step 5) ───
|
|
232
|
+
// [Capacitor] [OAuth2] [SAML]
|
|
233
|
+
// These routes serve both web and Capacitor clients:
|
|
234
|
+
// - oauth2Authorize: returns authorizationUrl — web uses window.location.href, Capacitor uses Browser.open()
|
|
235
|
+
// - oauth2Callback: IdP redirects here (server-to-server) — unaffected by Capacitor
|
|
236
|
+
// - tokenExchange: frontend/Capacitor app exchanges one-time code for JWT — works identically
|
|
237
|
+
// When Capacitor introduces native Apple/Google SDKs, a new POST /auth/native-token/exchange
|
|
238
|
+
// route will be needed to accept native SDK tokens (Apple identityToken, Google idToken)
|
|
239
|
+
// and issue JWT tokens. The existing oauth2Callback route is NOT used for native SDK flows.
|
|
240
|
+
|
|
241
|
+
// OAuth2 authorize — returns authorization URL for frontend to redirect
|
|
242
|
+
this.router.get(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_OAUTH2_AUTHORIZE], this.asyncHandler(this.oauth2Authorize.bind(this)));
|
|
243
|
+
this.logRouteRegistration('GET', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_OAUTH2_AUTHORIZE], 'OAuth2 authorize — get IdP authorization URL');
|
|
244
|
+
|
|
245
|
+
// OAuth2 callback — accepts GET and POST only (L7 fix: was router.all(), narrowed to reduce attack surface)
|
|
246
|
+
// GET: standard OAuth2 authorization code flow
|
|
247
|
+
// POST: Apple uses response_mode=form_post (TRAP 5)
|
|
248
|
+
const oauth2CallbackHandler = this.asyncHandler(this.oauth2Callback.bind(this));
|
|
249
|
+
const oauth2CallbackUrl = MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_OAUTH2_CALLBACK];
|
|
250
|
+
this.router.get(oauth2CallbackUrl, oauth2CallbackHandler);
|
|
251
|
+
this.router.post(oauth2CallbackUrl, oauth2CallbackHandler);
|
|
252
|
+
this.logRouteRegistration('GET+POST', oauth2CallbackUrl, 'OAuth2 callback — handle IdP redirect (GET+POST for Apple form_post)');
|
|
253
|
+
|
|
254
|
+
// Token exchange — frontend exchanges one-time code for JWT tokens (Decision 7)
|
|
255
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_TOKEN_EXCHANGE], this.asyncHandler(this.tokenExchange.bind(this)));
|
|
256
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_TOKEN_EXCHANGE], 'Exchange one-time code for JWT tokens');
|
|
257
|
+
|
|
258
|
+
// Logout — revoke refresh token
|
|
259
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_LOGOUT], this.asyncHandler(this.logout.bind(this)));
|
|
260
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_LOGOUT], 'Logout — revoke refresh token');
|
|
261
|
+
|
|
262
|
+
// ─── Password Reset Routes (Step 7) ───
|
|
263
|
+
|
|
264
|
+
// Request password reset — sends email with reset link
|
|
265
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSWORD_RESET_REQUEST], this.asyncHandler(this.passwordResetRequest.bind(this)));
|
|
266
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSWORD_RESET_REQUEST], 'Request password reset — send email with reset link');
|
|
267
|
+
|
|
268
|
+
// Complete password reset — validate token and update password
|
|
269
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSWORD_RESET_COMPLETE], this.asyncHandler(this.passwordResetComplete.bind(this)));
|
|
270
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSWORD_RESET_COMPLETE], 'Complete password reset — validate token and set new password');
|
|
271
|
+
|
|
272
|
+
// ─── Registration Routes (Step 8) ───
|
|
273
|
+
|
|
274
|
+
// Register — create account with email verification
|
|
275
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_REGISTER], this.asyncHandler(this.register.bind(this)));
|
|
276
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_REGISTER], 'Register — create user account with email verification');
|
|
277
|
+
|
|
278
|
+
// Accept invitation — public token-driven invitation completion
|
|
279
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_ACCEPT_INVITATION], this.asyncHandler(this.acceptInvitation.bind(this)));
|
|
280
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_ACCEPT_INVITATION], 'Accept invitation — create/link account and continue auth flow');
|
|
281
|
+
|
|
282
|
+
// Reject invitation — public token-driven invitation decline
|
|
283
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_REJECT_INVITATION], this.asyncHandler(this.rejectInvitation.bind(this)));
|
|
284
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_REJECT_INVITATION], 'Reject invitation — mark invitee decline explicitly');
|
|
285
|
+
|
|
286
|
+
// Verify email — confirm email and auto-login
|
|
287
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_VERIFY_EMAIL], this.asyncHandler(this.verifyEmail.bind(this)));
|
|
288
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_VERIFY_EMAIL], 'Verify email — confirm email address and issue tokens');
|
|
289
|
+
|
|
290
|
+
// Resend verification email (F5)
|
|
291
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_RESEND_VERIFICATION], this.asyncHandler(this.resendVerificationEmail.bind(this)));
|
|
292
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_RESEND_VERIFICATION], 'Resend verification email — re-send email verification link');
|
|
293
|
+
|
|
294
|
+
// W5.7: Complete org onboarding (deferred org creation)
|
|
295
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_COMPLETE_ORG_ONBOARDING], this.asyncHandler(this.completeOrgOnboarding.bind(this)));
|
|
296
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_COMPLETE_ORG_ONBOARDING], 'Complete org onboarding — create deferred organization');
|
|
297
|
+
|
|
298
|
+
// ─── MFA: Email OTP Routes (Step 10) ───
|
|
299
|
+
|
|
300
|
+
// Send email OTP — generates OTP and sends via email
|
|
301
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MFA_EMAIL_OTP_SEND], this.asyncHandler(this.mfaEmailOTPSend.bind(this)));
|
|
302
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MFA_EMAIL_OTP_SEND], 'Send email OTP for MFA second factor');
|
|
303
|
+
|
|
304
|
+
// Verify email OTP — validates the submitted OTP code
|
|
305
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MFA_EMAIL_OTP_VERIFY], this.asyncHandler(this.mfaEmailOTPVerify.bind(this)));
|
|
306
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MFA_EMAIL_OTP_VERIFY], 'Verify email OTP for MFA second factor');
|
|
307
|
+
|
|
308
|
+
// ─── MFA: TOTP Routes (Step 11) ───
|
|
309
|
+
|
|
310
|
+
// TOTP setup — generate secret + QR URI for enrollment
|
|
311
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MFA_TOTP_SETUP], this.asyncHandler(this.mfaTOTPSetup.bind(this)));
|
|
312
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MFA_TOTP_SETUP], 'Setup TOTP — generate secret and QR code URI');
|
|
313
|
+
|
|
314
|
+
// TOTP verify setup — confirm enrollment with a code from the authenticator app
|
|
315
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MFA_TOTP_VERIFY_SETUP], this.asyncHandler(this.mfaTOTPVerifySetup.bind(this)));
|
|
316
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MFA_TOTP_VERIFY_SETUP], 'Verify TOTP setup — confirm enrollment with code');
|
|
317
|
+
|
|
318
|
+
// TOTP verify — validate TOTP code during login MFA
|
|
319
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MFA_TOTP_VERIFY], this.asyncHandler(this.mfaTOTPVerify.bind(this)));
|
|
320
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MFA_TOTP_VERIFY], 'Verify TOTP code for MFA second factor');
|
|
321
|
+
|
|
322
|
+
// ─── Enterprise SSO Routes (Step 15) ───
|
|
323
|
+
// Enterprise OIDC authorize — initiate SSO flow for an org's OIDC connection
|
|
324
|
+
// Callback reuses the same /auth/oauth2/callback/:providerRef route — state token carries enterprise context
|
|
325
|
+
this.router.get(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_ENTERPRISE_SSO_AUTHORIZE], this.asyncHandler(this.enterpriseSSOAuthorize.bind(this)));
|
|
326
|
+
this.logRouteRegistration('GET', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_ENTERPRISE_SSO_AUTHORIZE], 'Enterprise SSO authorize — get IdP authorization URL for org OIDC connection');
|
|
327
|
+
|
|
328
|
+
// App-enterprise OIDC authorize — initiate SSO flow for an APPLICATION-scoped connection
|
|
329
|
+
this.router.get(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_APP_ENTERPRISE_AUTHORIZE], this.asyncHandler(this.appEnterpriseSSOAuthorize.bind(this)));
|
|
330
|
+
this.logRouteRegistration('GET', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_APP_ENTERPRISE_AUTHORIZE], 'App-enterprise SSO authorize — get IdP authorization URL for app OIDC connection');
|
|
331
|
+
|
|
332
|
+
// ─── SAML Routes (AUTH-2) ───
|
|
333
|
+
this.router.get(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SAML_LOGIN], this.asyncHandler(this.handleSAMLLogin.bind(this)));
|
|
334
|
+
this.logRouteRegistration('GET', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SAML_LOGIN], 'SAML login — initiate SP-initiated SSO');
|
|
335
|
+
|
|
336
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SAML_ACS],
|
|
337
|
+
express.urlencoded({ extended: false, limit: '2mb' }),
|
|
338
|
+
this.asyncHandler(this.handleSAMLACS.bind(this)),
|
|
339
|
+
);
|
|
340
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SAML_ACS], 'SAML ACS — process IdP response (SC-30: 2mb urlencoded)');
|
|
341
|
+
|
|
342
|
+
this.router.get(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SAML_METADATA], this.asyncHandler(this.handleSAMLMetadata.bind(this)));
|
|
343
|
+
this.logRouteRegistration('GET', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SAML_METADATA], 'SAML SP metadata — public XML endpoint');
|
|
344
|
+
|
|
345
|
+
this.router.get(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SAML_SLO], this.asyncHandler(this.handleSAMLSLO_GET.bind(this)));
|
|
346
|
+
this.logRouteRegistration('GET', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SAML_SLO], 'SAML SLO — IdP-initiated via HTTP-Redirect or SP-initiated LogoutResponse');
|
|
347
|
+
|
|
348
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SAML_SLO],
|
|
349
|
+
express.urlencoded({ extended: false, limit: '2mb' }),
|
|
350
|
+
this.asyncHandler(this.handleSAMLSLO_POST.bind(this)),
|
|
351
|
+
);
|
|
352
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SAML_SLO], 'SAML SLO — IdP-initiated via HTTP-POST');
|
|
353
|
+
|
|
354
|
+
// ─── WebAuthn/Passkey Routes (Phase G1) ───
|
|
355
|
+
// Registration (JWT-authenticated)
|
|
356
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_REGISTER_OPTIONS], this.asyncHandler(this.handlePasskeyRegisterOptions.bind(this)));
|
|
357
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_REGISTER_OPTIONS], 'Passkey register options — generate registration challenge');
|
|
358
|
+
|
|
359
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_REGISTER_VERIFY], this.asyncHandler(this.handlePasskeyRegisterVerify.bind(this)));
|
|
360
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_REGISTER_VERIFY], 'Passkey register verify — verify and store credential');
|
|
361
|
+
|
|
362
|
+
// Authentication (unauthenticated — part of login flow)
|
|
363
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_AUTH_OPTIONS], this.asyncHandler(this.handlePasskeyAuthOptions.bind(this)));
|
|
364
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_AUTH_OPTIONS], 'Passkey auth options — generate authentication challenge');
|
|
365
|
+
|
|
366
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_AUTH_VERIFY], this.asyncHandler(this.handlePasskeyAuthVerify.bind(this)));
|
|
367
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_AUTH_VERIFY], 'Passkey auth verify — verify assertion and complete login');
|
|
368
|
+
|
|
369
|
+
// Management (JWT-authenticated)
|
|
370
|
+
this.router.get(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_LIST], this.asyncHandler(this.handlePasskeyList.bind(this)));
|
|
371
|
+
this.logRouteRegistration('GET', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_LIST], 'Passkey list — list registered passkeys');
|
|
372
|
+
|
|
373
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_REMOVE], this.asyncHandler(this.handlePasskeyRemove.bind(this)));
|
|
374
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_REMOVE], 'Passkey remove — remove a passkey');
|
|
375
|
+
|
|
376
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_RENAME], this.asyncHandler(this.handlePasskeyRename.bind(this)));
|
|
377
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PASSKEY_RENAME], 'Passkey rename — rename a passkey');
|
|
378
|
+
|
|
379
|
+
// ─── Magic Link Routes (Phase G2) ───
|
|
380
|
+
|
|
381
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MAGIC_LINK_SEND], this.asyncHandler(this.magicLinkSend.bind(this)));
|
|
382
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MAGIC_LINK_SEND], 'Magic link send — send passwordless login link via email');
|
|
383
|
+
|
|
384
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MAGIC_LINK_VERIFY], this.asyncHandler(this.magicLinkVerify.bind(this)));
|
|
385
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_MAGIC_LINK_VERIFY], 'Magic link verify — verify token and issue auth tokens');
|
|
386
|
+
|
|
387
|
+
// ─── SMS OTP Routes (Phase G2) ───
|
|
388
|
+
|
|
389
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SMS_OTP_SEND], this.asyncHandler(this.smsOTPSend.bind(this)));
|
|
390
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_SMS_OTP_SEND], 'SMS OTP send — send OTP code via SMS');
|
|
391
|
+
|
|
392
|
+
// Note: SMS OTP verify goes through the generic /auth/authenticate endpoint via SMS_OTP method
|
|
393
|
+
|
|
394
|
+
// ─── Phone Verification Routes (Phase G2) ───
|
|
395
|
+
|
|
396
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PHONE_VERIFY_SEND], this.asyncHandler(this.phoneVerifySend.bind(this)));
|
|
397
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PHONE_VERIFY_SEND], 'Phone verify send — send verification code via SMS');
|
|
398
|
+
|
|
399
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PHONE_VERIFY_CONFIRM], this.asyncHandler(this.phoneVerifyConfirm.bind(this)));
|
|
400
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_PHONE_VERIFY_CONFIRM], 'Phone verify confirm — confirm phone ownership with code');
|
|
401
|
+
|
|
402
|
+
// ─── Native SDK Token Exchange (F2) ───
|
|
403
|
+
|
|
404
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_NATIVE_TOKEN_EXCHANGE], this.asyncHandler(this.nativeTokenExchange.bind(this)));
|
|
405
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_NATIVE_TOKEN_EXCHANGE], 'Exchange native SDK identity token for Wildo JWT');
|
|
406
|
+
|
|
407
|
+
// ─── One-Off Session Routes (W7.3b) ───
|
|
408
|
+
|
|
409
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_ONE_OFF_SESSION_CREATE], this.asyncHandler(this.createOneOffToken.bind(this)));
|
|
410
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_ONE_OFF_SESSION_CREATE], 'Create one-off session token (app-scoped)');
|
|
411
|
+
|
|
412
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_ONE_OFF_SESSION_CREATE_ORG], this.asyncHandler(this.createOneOffToken.bind(this)));
|
|
413
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_ONE_OFF_SESSION_CREATE_ORG], 'Create one-off session token (org+app-scoped)');
|
|
414
|
+
|
|
415
|
+
this.router.post(MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_ONE_OFF_SESSION_EXCHANGE], this.asyncHandler(this.exchangeOneOffToken.bind(this)));
|
|
416
|
+
this.logRouteRegistration('POST', MANUAL_CONTROLLER_ROUTES_URLS[ManualControllerRouteKey.AUTH_ONE_OFF_SESSION_EXCHANGE], 'Exchange one-off token for JWT session');
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// ═══════════════════════════════════════════════════════════════
|
|
420
|
+
// Existing Authentication Route Handlers
|
|
421
|
+
// ═══════════════════════════════════════════════════════════════
|
|
422
|
+
|
|
423
|
+
private async identify(req: Request, res: Response): Promise<void> {
|
|
424
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
425
|
+
const body = AuthIdentificationRequestSchema.parse(req.body || {});
|
|
426
|
+
|
|
427
|
+
// Capture device information from request headers (consistent IP extraction)
|
|
428
|
+
const deviceInfo = {
|
|
429
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
430
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
const identificationRequest = {
|
|
434
|
+
...body,
|
|
435
|
+
deviceInfo
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
// W3.5 + W3.11: Resolve activeUserType hint from X-Frontend-Service-Name header.
|
|
439
|
+
// AUTH-10: This is only a hint for pre-identification flows (unknown users).
|
|
440
|
+
// For known users, the orchestrator overrides with the DB-stored userTypes[0].
|
|
441
|
+
// AUTH-10: Cross-validate Origin against claimed frontend service identity (defense-in-depth).
|
|
442
|
+
const frontendServiceName = req.headers[WildoHeaderKeys.FRONTEND_SERVICE_NAME] as string | undefined;
|
|
443
|
+
this._validateFrontendAppOrigin(req, frontendServiceName);
|
|
444
|
+
const activeUserType = frontendServiceName
|
|
445
|
+
? this.appConfigService.resolveUserTypeFromFrontendServiceName(frontendServiceName) ?? undefined
|
|
446
|
+
: undefined;
|
|
447
|
+
|
|
448
|
+
const result: AuthIdentificationResponse = await this.authService.identify(
|
|
449
|
+
ec,
|
|
450
|
+
identificationRequest,
|
|
451
|
+
activeUserType,
|
|
452
|
+
frontendServiceName,
|
|
453
|
+
);
|
|
454
|
+
this.jsonSuccess(res, result);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
private async authenticatePassword(req: Request, res: Response): Promise<void> {
|
|
458
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
459
|
+
const body = PasswordAuthBodySchema.parse(req.body || {});
|
|
460
|
+
const passwordRequest = {
|
|
461
|
+
sessionId: body.sessionId,
|
|
462
|
+
method: body.method,
|
|
463
|
+
factorLevel: body.factorLevel,
|
|
464
|
+
password: body.password,
|
|
465
|
+
email: body.email, // Email should be available from session, but included for compatibility
|
|
466
|
+
rememberMe: false,
|
|
467
|
+
requestedIntegrations: []
|
|
468
|
+
};
|
|
469
|
+
const result: AuthenticationResponse = await this.authService.authenticatePassword(ec, passwordRequest);
|
|
470
|
+
await this.handleAnonymousTransposition(req, result);
|
|
471
|
+
this.jsonSuccess(res, result);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Generic authenticate endpoint for future extensibility (SSO/MFA/etc.)
|
|
475
|
+
private async authenticate(req: Request, res: Response): Promise<void> {
|
|
476
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
477
|
+
const request = AuthenticationRequestSchema.parse(req.body || {}) as AuthenticationRequest;
|
|
478
|
+
const result: AuthenticationResponse = await this.authService.authenticate(ec, request);
|
|
479
|
+
await this.handleAnonymousTransposition(req, result);
|
|
480
|
+
this.jsonSuccess(res, result);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Refresh access token using a valid refresh token.
|
|
485
|
+
* POST /auth/token/refresh
|
|
486
|
+
* Body: { refreshToken: string }
|
|
487
|
+
* Response: { accessToken, refreshToken?, expiresIn }
|
|
488
|
+
*
|
|
489
|
+
* TRAP 11: This endpoint is NOT behind JWT auth middleware.
|
|
490
|
+
* The user's access token is expired — that's why they're calling refresh.
|
|
491
|
+
*/
|
|
492
|
+
private async refreshToken(req: Request, res: Response): Promise<void> {
|
|
493
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
494
|
+
const body = RefreshTokenBodySchema.parse(req.body || {});
|
|
495
|
+
const tokens = await this.tokenIssuer.refreshAccessToken(body.refreshToken);
|
|
496
|
+
|
|
497
|
+
// H5: Audit token refresh
|
|
498
|
+
try {
|
|
499
|
+
const decoded = await this.jwtService.verify(tokens.accessToken);
|
|
500
|
+
if (typeof decoded === 'object' && decoded !== null) {
|
|
501
|
+
const payload = decoded as Record<string, unknown>;
|
|
502
|
+
const refreshUserId = typeof payload.userId === 'string' ? payload.userId : undefined;
|
|
503
|
+
const sessionId = typeof payload.sessionId === 'string' ? payload.sessionId : 'unknown';
|
|
504
|
+
if (refreshUserId) {
|
|
505
|
+
this.auditLogsService.logUserTokenRefreshed({
|
|
506
|
+
userId: refreshUserId,
|
|
507
|
+
sessionId,
|
|
508
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
509
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
510
|
+
}).catch(() => {});
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
} catch { /* token decode failure — don't block the response */ }
|
|
514
|
+
|
|
515
|
+
this.jsonSuccess(res, tokens);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Get current authentication session state
|
|
519
|
+
private async getSessionState(req: Request, res: Response): Promise<void> {
|
|
520
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
521
|
+
const sessionId = req.params.sessionId as string | undefined;
|
|
522
|
+
|
|
523
|
+
if (!sessionId) {
|
|
524
|
+
return this.jsonError(res, 'Session ID is required');
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
const sessionState = await this.authService.getAuthenticationSessionState(ec, sessionId);
|
|
528
|
+
|
|
529
|
+
if (!sessionState) {
|
|
530
|
+
return this.jsonError(res, 'Session not found or expired');
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// H2 fix: Strip sensitive fields from public endpoint to prevent enumeration.
|
|
534
|
+
// Removed: email, userExists, userId (H2), remainingAttempts, lockedUntil (review fix #5).
|
|
535
|
+
// Frontend uses error responses (customMessageReference, authResponse) for retry/lockout UI.
|
|
536
|
+
const publicSessionState = {
|
|
537
|
+
sessionId: sessionState.sessionId,
|
|
538
|
+
state: sessionState.state,
|
|
539
|
+
completedFactors: sessionState.completedFactors,
|
|
540
|
+
currentFactor: sessionState.currentFactor,
|
|
541
|
+
availableFirstFactorMethods: sessionState.availableFirstFactorMethods,
|
|
542
|
+
availableSecondFactorMethods: sessionState.availableSecondFactorMethods,
|
|
543
|
+
enrolledSecondFactorMethods: sessionState.enrolledSecondFactorMethods,
|
|
544
|
+
usableSecondFactorMethods: sessionState.usableSecondFactorMethods,
|
|
545
|
+
requiresMFA: sessionState.requiresMFA,
|
|
546
|
+
requireStrongMFA: sessionState.requireStrongMFA,
|
|
547
|
+
mfaMethodsRequired: sessionState.mfaMethodsRequired,
|
|
548
|
+
expiresAt: sessionState.expiresAt,
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
this.jsonSuccess(res, publicSessionState);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// ═══════════════════════════════════════════════════════════════
|
|
555
|
+
// OAuth2 Route Handlers (Step 5)
|
|
556
|
+
// ═══════════════════════════════════════════════════════════════
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* GET /auth/oauth2/authorize/:providerRef
|
|
560
|
+
*
|
|
561
|
+
* Initiates an OAuth2 authorization flow for a social SSO provider.
|
|
562
|
+
* Returns the IdP authorization URL for the frontend to redirect to.
|
|
563
|
+
*
|
|
564
|
+
* Enterprise-ready: In Step 14/15, a query param (?org=...&connection=...)
|
|
565
|
+
* will trigger resolveEnterpriseConnection() instead.
|
|
566
|
+
*/
|
|
567
|
+
private async oauth2Authorize(req: Request, res: Response): Promise<void> {
|
|
568
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
569
|
+
const providerRef = req.params.providerRef as string | undefined;
|
|
570
|
+
|
|
571
|
+
if (!providerRef) {
|
|
572
|
+
throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
|
|
573
|
+
customMessageReference: ErrorCustomMessageReference.VALIDATION,
|
|
574
|
+
context: { message: 'providerRef parameter is required' },
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// G3 + P3: Determine scope context from email hint before resolving credentials.
|
|
579
|
+
// Used for both provider restriction checks (G3) and social credential overrides (P3).
|
|
580
|
+
const emailHint = req.query.email as string | undefined;
|
|
581
|
+
let scopeContext: { scopeType: AuthScopeType; scopeId: string } | undefined;
|
|
582
|
+
|
|
583
|
+
if (emailHint) {
|
|
584
|
+
const emailDomain = emailHint.split('@')[1]?.toLowerCase();
|
|
585
|
+
if (emailDomain) {
|
|
586
|
+
const orgLookup = await this.domainToOrgLookup.findOrgByDomain(ec, emailDomain);
|
|
587
|
+
if (orgLookup) {
|
|
588
|
+
scopeContext = { scopeType: orgLookup.scopeType, scopeId: orgLookup.scopeId };
|
|
589
|
+
|
|
590
|
+
// G3: Check org-level provider restrictions (UX optimization — hard enforcement in callback G3-M5)
|
|
591
|
+
const { allowed, reason } = await this.oauth2Resolver.isProviderAllowed(
|
|
592
|
+
ec, orgLookup.scopeType, orgLookup.scopeId, providerRef,
|
|
593
|
+
);
|
|
594
|
+
if (!allowed) {
|
|
595
|
+
await this.auditLogsService.logOAuth2ProviderBlocked({
|
|
596
|
+
email: emailHint,
|
|
597
|
+
providerRef,
|
|
598
|
+
organizationId: orgLookup.scopeId,
|
|
599
|
+
reason: reason || 'Organization policy',
|
|
600
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
601
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
602
|
+
});
|
|
603
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
604
|
+
customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_INVALID_TOKEN,
|
|
605
|
+
context: { message: reason || 'This login provider is not allowed for your organization.' },
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Resolve connection config from catalog + app config + secrets + scope overrides (P3)
|
|
613
|
+
const connection = await this.oauth2Resolver.resolveSocialConnection(
|
|
614
|
+
providerRef,
|
|
615
|
+
scopeContext ? { ec, ...scopeContext } : undefined,
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
// Validate the frontend originator early — fail now with a clear error instead of
|
|
619
|
+
// silently storing undefined in the state token and getting a confusing error on callback.
|
|
620
|
+
// resolveFrontendAppPublicUrl throws if the header is missing or the frontend service is unknown.
|
|
621
|
+
const frontendUrl = this.resolveFrontendAppPublicUrl(req);
|
|
622
|
+
const frontendServiceName = req.headers[WildoHeaderKeys.FRONTEND_SERVICE_NAME] as string;
|
|
623
|
+
const returnUrl = typeof req.query.returnUrl === 'string' ? req.query.returnUrl : undefined;
|
|
624
|
+
void frontendUrl; // validated and discarded — the URL is resolved again on callback from the state token
|
|
625
|
+
if (returnUrl) {
|
|
626
|
+
this.validateFrontendReturnUrl(returnUrl, frontendUrl);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Build the authorization URL with PKCE + state token (includes frontendServiceName + scope in state)
|
|
630
|
+
const { authorizationUrl } = await this.oauth2Service.buildAuthorizationUrl(connection, {
|
|
631
|
+
frontendServiceName,
|
|
632
|
+
scopeType: scopeContext?.scopeType,
|
|
633
|
+
scopeId: scopeContext?.scopeId,
|
|
634
|
+
returnUrl,
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
this.logDebug('OAuth2 authorize URL generated', {
|
|
638
|
+
providerRef,
|
|
639
|
+
connectionType: connection.connectionType,
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
this.jsonSuccess(res, { authorizationUrl });
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* GET /auth/enterprise/authorize/:orgId/:connectionId
|
|
647
|
+
*
|
|
648
|
+
* Initiates an enterprise SSO OIDC flow for an organization's connection.
|
|
649
|
+
* Uses the same OAuth2 engine — only the resolver path is different.
|
|
650
|
+
* The callback reuses /auth/oauth2/callback/:providerRef — the state token
|
|
651
|
+
* carries connectionType='enterprise', organizationId, and connectionId.
|
|
652
|
+
*
|
|
653
|
+
* Step 15: Enterprise SSO authorize route.
|
|
654
|
+
*/
|
|
655
|
+
private async enterpriseSSOAuthorize(req: Request, res: Response): Promise<void> {
|
|
656
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
657
|
+
const orgId = req.params.orgId as string | undefined;
|
|
658
|
+
const connectionId = req.params.connectionId as string | undefined;
|
|
659
|
+
|
|
660
|
+
if (!orgId || !connectionId) {
|
|
661
|
+
throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
|
|
662
|
+
customMessageReference: ErrorCustomMessageReference.VALIDATION,
|
|
663
|
+
context: { message: 'orgId and connectionId parameters are required' },
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// Resolve enterprise connection from org config
|
|
668
|
+
const connection = await this.oauth2Resolver.resolveEnterpriseConnection(ec, AuthScopeType.ORGANIZATION, orgId, connectionId);
|
|
669
|
+
|
|
670
|
+
// Validate the frontend originator
|
|
671
|
+
const frontendUrl = this.resolveFrontendAppPublicUrl(req);
|
|
672
|
+
const frontendServiceName = req.headers[WildoHeaderKeys.FRONTEND_SERVICE_NAME] as string;
|
|
673
|
+
const returnUrl = typeof req.query.returnUrl === 'string' ? req.query.returnUrl : undefined;
|
|
674
|
+
void frontendUrl;
|
|
675
|
+
if (returnUrl) {
|
|
676
|
+
this.validateFrontendReturnUrl(returnUrl, frontendUrl);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// Build the authorization URL using the same OAuth2 engine
|
|
680
|
+
const { authorizationUrl } = await this.oauth2Service.buildAuthorizationUrl(connection, {
|
|
681
|
+
frontendServiceName,
|
|
682
|
+
returnUrl,
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
this.logDebug('Enterprise SSO authorize URL generated', {
|
|
686
|
+
orgId,
|
|
687
|
+
connectionId,
|
|
688
|
+
connectionType: connection.connectionType,
|
|
689
|
+
providerRef: connection.providerRef,
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
this.jsonSuccess(res, { authorizationUrl });
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* GET /auth/app-enterprise/authorize/:connectionId
|
|
697
|
+
*
|
|
698
|
+
* Application-scoped enterprise SSO authorize route.
|
|
699
|
+
* Same flow as org-scoped enterpriseSSOAuthorize but resolves from APPLICATION scope.
|
|
700
|
+
*/
|
|
701
|
+
private async appEnterpriseSSOAuthorize(req: Request, res: Response): Promise<void> {
|
|
702
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
703
|
+
const connectionId = req.params.connectionId as string | undefined;
|
|
704
|
+
|
|
705
|
+
if (!connectionId) {
|
|
706
|
+
throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
|
|
707
|
+
customMessageReference: ErrorCustomMessageReference.VALIDATION,
|
|
708
|
+
context: { message: 'connectionId parameter is required' },
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
const appId = req.headers[WildoHeaderKeys.APPLICATION_ID] as string | undefined;
|
|
713
|
+
if (!appId) {
|
|
714
|
+
throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
|
|
715
|
+
customMessageReference: ErrorCustomMessageReference.VALIDATION,
|
|
716
|
+
context: { message: 'Application ID header is required for app-enterprise SSO' },
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const connection = await this.oauth2Resolver.resolveEnterpriseConnection(ec, AuthScopeType.APPLICATION, appId, connectionId);
|
|
721
|
+
|
|
722
|
+
// Validate the frontend originator early so OAuth state always carries
|
|
723
|
+
// a usable frontendServiceName for callback redirection.
|
|
724
|
+
const frontendUrl = this.resolveFrontendAppPublicUrl(req);
|
|
725
|
+
const frontendServiceName = req.headers[WildoHeaderKeys.FRONTEND_SERVICE_NAME] as string;
|
|
726
|
+
const returnUrl = typeof req.query.returnUrl === 'string' ? req.query.returnUrl : undefined;
|
|
727
|
+
void frontendUrl;
|
|
728
|
+
if (returnUrl) {
|
|
729
|
+
this.validateFrontendReturnUrl(returnUrl, frontendUrl);
|
|
730
|
+
}
|
|
731
|
+
const { authorizationUrl } = await this.oauth2Service.buildAuthorizationUrl(connection, {
|
|
732
|
+
frontendServiceName,
|
|
733
|
+
returnUrl,
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
this.logDebug('App-enterprise SSO authorize URL generated', {
|
|
737
|
+
appId,
|
|
738
|
+
connectionId,
|
|
739
|
+
connectionType: connection.connectionType,
|
|
740
|
+
providerRef: connection.providerRef,
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
this.jsonSuccess(res, { authorizationUrl });
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* GET /auth/saml/login/:connectionId
|
|
748
|
+
*
|
|
749
|
+
* Initiate SP-initiated SAML SSO. Generates an AuthnRequest,
|
|
750
|
+
* creates a state token, and redirects the browser to the IdP SSO URL.
|
|
751
|
+
*
|
|
752
|
+
* Rate limit: SC-38 — 10 req/min per IP.
|
|
753
|
+
*/
|
|
754
|
+
private async handleSAMLLogin(req: Request, res: Response): Promise<void> {
|
|
755
|
+
const clientIp = AuthControllerUtils.getClientIpFromRequest(req);
|
|
756
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.SAML_LOGIN_IP}${clientIp}`, 10, 60);
|
|
757
|
+
|
|
758
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
759
|
+
const connectionId = req.params.connectionId as string;
|
|
760
|
+
const returnUrl = (req.query.returnUrl as string) || '/';
|
|
761
|
+
|
|
762
|
+
try {
|
|
763
|
+
const { redirectUrl } = await this.samlAuthService.initiateLogin(ec, connectionId, returnUrl);
|
|
764
|
+
res.redirect(302, redirectUrl);
|
|
765
|
+
} catch (error) {
|
|
766
|
+
if (isWildoBackendError(error)) {
|
|
767
|
+
this.logger.warn('SAML login initiation failed', { connectionId });
|
|
768
|
+
} else {
|
|
769
|
+
this.logger.error('SAML login initiation failed with unexpected error', {
|
|
770
|
+
connectionId,
|
|
771
|
+
error: error instanceof Error ? error.message : String(error),
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
const frontendUrl = this._resolveSAMLRedirectUrl();
|
|
775
|
+
return this.redirectToFrontendWithError(res, AuthRedirectErrorCode.SAML_LOGIN_FAILED, 'Authentication failed. Please try again.', frontendUrl);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* POST /auth/saml/acs
|
|
781
|
+
*
|
|
782
|
+
* Assertion Consumer Service — processes the SAML Response from the IdP.
|
|
783
|
+
* Route-specific body parser: `express.urlencoded({ extended: false, limit: '2mb' })` (SC-30).
|
|
784
|
+
*
|
|
785
|
+
* Rate limit: SC-39 — 20 req/min per IP (higher because IdPs may retry).
|
|
786
|
+
* E16: POST-only (enforced by route registration).
|
|
787
|
+
* E19: RelayState size check — accept up to 1024 bytes, warn if >80.
|
|
788
|
+
*/
|
|
789
|
+
private async handleSAMLACS(req: Request, res: Response): Promise<void> {
|
|
790
|
+
const clientIp = AuthControllerUtils.getClientIpFromRequest(req);
|
|
791
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.SAML_ACS_IP}${clientIp}`, 20, 60);
|
|
792
|
+
|
|
793
|
+
const samlResponse: string | undefined = req.body?.SAMLResponse;
|
|
794
|
+
const relayState: string | undefined = req.body?.RelayState;
|
|
795
|
+
|
|
796
|
+
if (!samlResponse) {
|
|
797
|
+
const frontendUrl = this._resolveSAMLRedirectUrl();
|
|
798
|
+
return this.redirectToFrontendWithError(res, AuthRedirectErrorCode.SAML_AUTH_FAILED, 'Authentication failed.', frontendUrl);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
if (relayState && relayState.length > 1024) {
|
|
802
|
+
this.logger.warn('SAML RelayState exceeds 1024 bytes, rejecting', { length: relayState.length });
|
|
803
|
+
const frontendUrl = this._resolveSAMLRedirectUrl();
|
|
804
|
+
return this.redirectToFrontendWithError(res, AuthRedirectErrorCode.SAML_AUTH_FAILED, 'Authentication failed.', frontendUrl);
|
|
805
|
+
}
|
|
806
|
+
if (relayState && relayState.length > 80) {
|
|
807
|
+
this.logger.warn('SAML RelayState exceeds 80-byte spec limit (accepted)', { length: relayState.length });
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
811
|
+
|
|
812
|
+
try {
|
|
813
|
+
const clientContext = {
|
|
814
|
+
ipAddress: clientIp,
|
|
815
|
+
userAgent: (req.headers[WildoHeaderKeys.USER_AGENT] as string) || 'unknown',
|
|
816
|
+
};
|
|
817
|
+
const result = await this.samlAuthService.handleACS(ec, samlResponse, relayState, clientContext);
|
|
818
|
+
res.redirect(302, result.redirectUrl);
|
|
819
|
+
} catch (error) {
|
|
820
|
+
if (isWildoBackendError(error)) {
|
|
821
|
+
this.logger.warn('SAML ACS processing failed', {
|
|
822
|
+
errorRef: (error as any).customMessageReference || 'unknown',
|
|
823
|
+
});
|
|
824
|
+
} else {
|
|
825
|
+
this.logger.error('SAML ACS failed with unexpected error', {
|
|
826
|
+
error: error instanceof Error ? error.message : String(error),
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
const frontendUrl = this._resolveSAMLRedirectUrl();
|
|
830
|
+
return this.redirectToFrontendWithError(res, AuthRedirectErrorCode.SAML_AUTH_FAILED, 'Authentication failed. Please try again.', frontendUrl);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* GET /auth/saml/metadata/:scopeType/:scopeId
|
|
836
|
+
*
|
|
837
|
+
* Public endpoint — returns SP metadata XML for IdP admins to configure their IdP.
|
|
838
|
+
* No auth middleware required (D16).
|
|
839
|
+
* Content-Type: application/samlmetadata+xml
|
|
840
|
+
*/
|
|
841
|
+
private async handleSAMLMetadata(req: Request, res: Response): Promise<void> {
|
|
842
|
+
const scopeType = req.params.scopeType as string;
|
|
843
|
+
const scopeId = req.params.scopeId as string;
|
|
844
|
+
|
|
845
|
+
const metadataXml = this.samlMetadataService.generateSPMetadata(scopeType, scopeId);
|
|
846
|
+
res.set(WildoHeaderKeys.CONTENT_TYPE, 'application/samlmetadata+xml');
|
|
847
|
+
res.status(200).send(metadataXml);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* GET /auth/saml/slo
|
|
852
|
+
*
|
|
853
|
+
* Handles two distinct cases via query params:
|
|
854
|
+
* - `SAMLRequest` present → IdP-initiated SLO (HTTP-Redirect binding)
|
|
855
|
+
* - `SAMLResponse` present → IdP's response to our SP-initiated SLO
|
|
856
|
+
*
|
|
857
|
+
* Rate limit: SC-40 — 10 req/min per IP.
|
|
858
|
+
*/
|
|
859
|
+
private async handleSAMLSLO_GET(req: Request, res: Response): Promise<void> {
|
|
860
|
+
const clientIp = AuthControllerUtils.getClientIpFromRequest(req);
|
|
861
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.SAML_SLO_IP}${clientIp}`, 10, 60);
|
|
862
|
+
|
|
863
|
+
const samlRequest: string | undefined = req.query.SAMLRequest as string | undefined;
|
|
864
|
+
const samlResponse: string | undefined = req.query.SAMLResponse as string | undefined;
|
|
865
|
+
const relayState: string | undefined = req.query.RelayState as string | undefined;
|
|
866
|
+
|
|
867
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
868
|
+
|
|
869
|
+
if (samlRequest) {
|
|
870
|
+
try {
|
|
871
|
+
const result = await this.samlAuthService.handleIdPInitiatedSLO(ec, 'redirect', samlRequest, relayState);
|
|
872
|
+
res.redirect(302, result.logoutResponseUrl);
|
|
873
|
+
} catch (error) {
|
|
874
|
+
this.logger.warn('SAML SLO (IdP-initiated GET) failed', {
|
|
875
|
+
errorRef: isWildoBackendError(error) ? (error as any).customMessageReference : 'unknown',
|
|
876
|
+
error: error instanceof Error ? error.message : String(error),
|
|
877
|
+
});
|
|
878
|
+
const frontendUrl = this._resolveSAMLRedirectUrl();
|
|
879
|
+
return this.redirectToFrontendWithError(res, AuthRedirectErrorCode.SAML_SLO_FAILED, 'Logout failed.', frontendUrl);
|
|
880
|
+
}
|
|
881
|
+
} else if (samlResponse) {
|
|
882
|
+
try {
|
|
883
|
+
await this.samlAuthService.handleSLOResponse(ec, 'redirect', samlResponse);
|
|
884
|
+
} catch (error) {
|
|
885
|
+
this.logger.warn('SAML SLO LogoutResponse processing failed (GET)', {
|
|
886
|
+
error: error instanceof Error ? error.message : String(error),
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
const frontendUrl = this._resolveSAMLRedirectUrl() || '/';
|
|
890
|
+
res.redirect(302, `${frontendUrl}/auth/login?slo=success`);
|
|
891
|
+
} else {
|
|
892
|
+
res.status(400).json({ error: 'Missing SAMLRequest or SAMLResponse parameter' });
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* POST /auth/saml/slo
|
|
898
|
+
*
|
|
899
|
+
* IdP-initiated SLO via HTTP-POST binding.
|
|
900
|
+
* Route-specific body parser: `express.urlencoded({ extended: false, limit: '2mb' })`.
|
|
901
|
+
*
|
|
902
|
+
* Rate limit: SC-40 — 10 req/min per IP.
|
|
903
|
+
*/
|
|
904
|
+
private async handleSAMLSLO_POST(req: Request, res: Response): Promise<void> {
|
|
905
|
+
const clientIp = AuthControllerUtils.getClientIpFromRequest(req);
|
|
906
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.SAML_SLO_IP}${clientIp}`, 10, 60);
|
|
907
|
+
|
|
908
|
+
const samlRequest: string | undefined = req.body?.SAMLRequest;
|
|
909
|
+
const samlResponse: string | undefined = req.body?.SAMLResponse;
|
|
910
|
+
const relayState: string | undefined = req.body?.RelayState;
|
|
911
|
+
|
|
912
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
913
|
+
|
|
914
|
+
if (samlRequest) {
|
|
915
|
+
try {
|
|
916
|
+
const result = await this.samlAuthService.handleIdPInitiatedSLO(ec, 'post', samlRequest, relayState);
|
|
917
|
+
res.redirect(302, result.logoutResponseUrl);
|
|
918
|
+
} catch (error) {
|
|
919
|
+
this.logger.warn('SAML SLO (IdP-initiated POST) failed', {
|
|
920
|
+
errorRef: isWildoBackendError(error) ? (error as any).customMessageReference : 'unknown',
|
|
921
|
+
error: error instanceof Error ? error.message : String(error),
|
|
922
|
+
});
|
|
923
|
+
const frontendUrl = this._resolveSAMLRedirectUrl();
|
|
924
|
+
return this.redirectToFrontendWithError(res, AuthRedirectErrorCode.SAML_SLO_FAILED, 'Logout failed.', frontendUrl);
|
|
925
|
+
}
|
|
926
|
+
} else if (samlResponse) {
|
|
927
|
+
try {
|
|
928
|
+
await this.samlAuthService.handleSLOResponse(ec, 'post', samlResponse);
|
|
929
|
+
} catch (error) {
|
|
930
|
+
this.logger.warn('SAML SLO LogoutResponse processing failed (POST)', {
|
|
931
|
+
error: error instanceof Error ? error.message : String(error),
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
const frontendUrl = this._resolveSAMLRedirectUrl() || '/';
|
|
935
|
+
res.redirect(302, `${frontendUrl}/auth/login?slo=success`);
|
|
936
|
+
} else {
|
|
937
|
+
res.status(400).json({ error: 'Missing SAMLRequest or SAMLResponse parameter' });
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/**
|
|
942
|
+
* Resolve a frontend URL for SAML redirects.
|
|
943
|
+
* Uses the user-type → frontend-service reverse lookup from `frontendServices.usersManagement`.
|
|
944
|
+
* When `userType` is provided (post-identification), resolves the frontend service that serves that user type.
|
|
945
|
+
* Falls back to the config's default frontend service (first with any `isDefault` entry).
|
|
946
|
+
*/
|
|
947
|
+
private _resolveSAMLRedirectUrl(userType?: string): string | undefined {
|
|
948
|
+
try {
|
|
949
|
+
const frontendServiceName = userType
|
|
950
|
+
? this.appConfigService.resolveFrontendServiceNameFromUserType(userType)
|
|
951
|
+
: this.appConfigService.resolveDefaultFrontendServiceName();
|
|
952
|
+
if (!frontendServiceName) return undefined;
|
|
953
|
+
return this.resolveFrontendAppPublicUrlFromFrontendServiceName(frontendServiceName);
|
|
954
|
+
} catch {
|
|
955
|
+
return undefined;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* GET+POST /auth/oauth2/callback/:providerRef
|
|
961
|
+
*
|
|
962
|
+
* Handles the IdP redirect after user authentication.
|
|
963
|
+
* Accepts both GET and POST — TRAP 5: Apple uses response_mode=form_post.
|
|
964
|
+
*
|
|
965
|
+
* Flow:
|
|
966
|
+
* 1. Extract code/state from query (GET) or body (POST)
|
|
967
|
+
* 2. handleCallback() — validate state, exchange code, extract profile
|
|
968
|
+
* 3. provisionOrLinkUser() — find/create user, create identity link
|
|
969
|
+
* 4. Issue JWT tokens via AuthTokenIssuer.issueTokensForUser() (TRAP 12)
|
|
970
|
+
* 5. Create AUTH_CODE_EXCHANGE consumable token containing JWT tokens
|
|
971
|
+
* 6. Redirect to frontend /auth/callback?code={consumableTokenCode}
|
|
972
|
+
*
|
|
973
|
+
* [Capacitor] [OAuth2] [SAML]
|
|
974
|
+
* The final redirect URL ({frontendUrl}/auth/callback?code=xxx) must be reachable by
|
|
975
|
+
* the client. On web, it's a normal navigation. On Capacitor, this URL must be configured
|
|
976
|
+
* as a Universal Link (iOS) / App Link (Android) so the OS routes it to the native app.
|
|
977
|
+
* The frontendUrl in app config may need a platform-aware variant (e.g., a custom URL scheme
|
|
978
|
+
* fallback: com.wildo.app://auth/callback?code=xxx) if Universal Links are not configured.
|
|
979
|
+
*
|
|
980
|
+
* TRAP 13: Audit logging for OAuth2 logins happens HERE (not in the engine).
|
|
981
|
+
*/
|
|
982
|
+
private async oauth2Callback(req: Request, res: Response): Promise<void> {
|
|
983
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
984
|
+
// M10 fix: Check for IdP error parameters FIRST, before extracting code/state.
|
|
985
|
+
// If the IdP sends both error and code/state (some IdPs do this), we must handle
|
|
986
|
+
// the error rather than consuming the state token and attempting a code exchange
|
|
987
|
+
// that will fail with an opaque error.
|
|
988
|
+
const idpError = (req.query.error as string) || req.body?.error;
|
|
989
|
+
if (idpError) {
|
|
990
|
+
const errorDescription = (req.query.error_description as string) || req.body?.error_description || 'Authentication denied by identity provider';
|
|
991
|
+
|
|
992
|
+
// Try to peek at the state token (without consuming it) to resolve the frontendUrl
|
|
993
|
+
// for a user-friendly redirect instead of a raw JSON 400 response.
|
|
994
|
+
// The state token expires naturally — not consuming it is safe.
|
|
995
|
+
let errorRedirectUrl: string | undefined;
|
|
996
|
+
let errorReturnUrl: string | undefined;
|
|
997
|
+
const stateValue = (req.query.state as string) || req.body?.state;
|
|
998
|
+
if (stateValue) {
|
|
999
|
+
try {
|
|
1000
|
+
const stateToken = await this.consumableTokenService.validateToken(stateValue);
|
|
1001
|
+
const stateMetadata = stateToken.metadata as Record<string, unknown> | undefined;
|
|
1002
|
+
const frontendServiceName = stateMetadata?.frontendServiceName as string | undefined;
|
|
1003
|
+
errorReturnUrl = typeof stateMetadata?.returnUrl === 'string'
|
|
1004
|
+
? stateMetadata.returnUrl
|
|
1005
|
+
: undefined;
|
|
1006
|
+
if (frontendServiceName) {
|
|
1007
|
+
errorRedirectUrl = this.resolveFrontendAppPublicUrlFromFrontendServiceName(frontendServiceName);
|
|
1008
|
+
}
|
|
1009
|
+
} catch {
|
|
1010
|
+
// State token invalid/expired — fall through to JSON fallback
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
return this.redirectToFrontendWithError(res, idpError, errorDescription, errorRedirectUrl, errorReturnUrl);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// 1. Extract code and state from query (GET) or body (POST)
|
|
1018
|
+
const code = (req.query.code as string) || req.body?.code;
|
|
1019
|
+
const state = (req.query.state as string) || req.body?.state;
|
|
1020
|
+
|
|
1021
|
+
if (!code || !state) {
|
|
1022
|
+
return this.redirectToFrontendWithError(res, AuthRedirectErrorCode.MISSING_PARAMS, 'Missing code or state parameter');
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
// Hoisted so the catch block can use it for error redirects
|
|
1026
|
+
let frontendUrl: string | undefined;
|
|
1027
|
+
let callbackReturnUrl: string | undefined;
|
|
1028
|
+
|
|
1029
|
+
try {
|
|
1030
|
+
// 2. Handle callback — validate state, exchange code, extract profile
|
|
1031
|
+
const callbackParams = {
|
|
1032
|
+
code,
|
|
1033
|
+
state,
|
|
1034
|
+
body: req.method === 'POST' ? req.body : undefined, // Apple form_post: body contains `user` JSON
|
|
1035
|
+
};
|
|
1036
|
+
const { normalizedProfile, connection, stateMetadata } = await this.oauth2Service.handleCallback(callbackParams);
|
|
1037
|
+
|
|
1038
|
+
// Resolve the frontend URL from the state token's frontendServiceName field.
|
|
1039
|
+
// This is the frontend that initiated the OAuth2 flow — redirects must go back there.
|
|
1040
|
+
frontendUrl = stateMetadata.frontendServiceName
|
|
1041
|
+
? this.resolveFrontendAppPublicUrlFromFrontendServiceName(stateMetadata.frontendServiceName)
|
|
1042
|
+
: undefined;
|
|
1043
|
+
callbackReturnUrl = stateMetadata.returnUrl;
|
|
1044
|
+
|
|
1045
|
+
// 3. Provision or link user
|
|
1046
|
+
const { userId, isNewUser } = await this.oauth2Service.provisionOrLinkUser(normalizedProfile, connection);
|
|
1047
|
+
|
|
1048
|
+
const frontendServiceName = stateMetadata.frontendServiceName;
|
|
1049
|
+
if (frontendServiceName) {
|
|
1050
|
+
const authenticatedUser = await this.userLookup.findUserById(ec, userId);
|
|
1051
|
+
const authenticatedUserType = authenticatedUser?.userTypes?.[0];
|
|
1052
|
+
const userManagement = authenticatedUserType
|
|
1053
|
+
? this.appConfigService.getFrontendServiceUserManagementEntry(frontendServiceName, authenticatedUserType)
|
|
1054
|
+
: null;
|
|
1055
|
+
|
|
1056
|
+
if (!authenticatedUserType || !userManagement?.auth) {
|
|
1057
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHORIZATION, undefined, {
|
|
1058
|
+
customMessageReference: ErrorCustomMessageReference.AUTHORIZATION,
|
|
1059
|
+
context: {
|
|
1060
|
+
message:
|
|
1061
|
+
`Authentication is disabled for frontend service "${frontendServiceName}"` +
|
|
1062
|
+
(authenticatedUserType ? ` and user type "${authenticatedUserType}"` : ''),
|
|
1063
|
+
frontendServiceName,
|
|
1064
|
+
activeUserType: authenticatedUserType,
|
|
1065
|
+
},
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
const tokens = await this.tokenIssuer.issueTokensForUser(userId, undefined, {
|
|
1071
|
+
lastAuthenticatedAt: Math.floor(Date.now() / 1000),
|
|
1072
|
+
});
|
|
1073
|
+
|
|
1074
|
+
// 5. Create AUTH_CODE_EXCHANGE consumable token with JWT tokens as metadata
|
|
1075
|
+
const exchangeToken = await this.consumableTokenService.createToken({
|
|
1076
|
+
tokenType: CoreConsumableTokenTypes.AUTH_CODE_EXCHANGE,
|
|
1077
|
+
consumptionMode: ConsumableToken_ConsumptionMode.SINGLE_USE,
|
|
1078
|
+
expiresIn: { value: 5, unit: DurationUnit.MINUTES },
|
|
1079
|
+
userId: userId,
|
|
1080
|
+
resourceIdentifier: CoreResourceType.USERS,
|
|
1081
|
+
metadata: {
|
|
1082
|
+
accessToken: tokens.accessToken,
|
|
1083
|
+
refreshToken: tokens.refreshToken,
|
|
1084
|
+
expiresIn: tokens.expiresIn,
|
|
1085
|
+
providerRef: connection.providerRef,
|
|
1086
|
+
isNewUser: isNewUser,
|
|
1087
|
+
},
|
|
1088
|
+
});
|
|
1089
|
+
|
|
1090
|
+
// TRAP 13: Audit log OAuth2 login (audit stays in the route handler, not engine)
|
|
1091
|
+
const deviceInfo = {
|
|
1092
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
1093
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1094
|
+
};
|
|
1095
|
+
|
|
1096
|
+
await this.auditLogsService.logUserSSOLogin({
|
|
1097
|
+
userId: userId,
|
|
1098
|
+
email: normalizedProfile.email,
|
|
1099
|
+
providerRef: connection.providerRef,
|
|
1100
|
+
connectionType: connection.connectionType as SsoConnectionType,
|
|
1101
|
+
authSource: AuthSource.OIDC,
|
|
1102
|
+
organizationId: connection.organization?.organizationId,
|
|
1103
|
+
ipAddress: deviceInfo.ipAddress,
|
|
1104
|
+
userAgent: deviceInfo.userAgent,
|
|
1105
|
+
sessionId: `oauth2:${connection.providerRef}:${userId}`,
|
|
1106
|
+
});
|
|
1107
|
+
|
|
1108
|
+
this.logDebug('OAuth2 callback processed successfully', {
|
|
1109
|
+
providerRef: connection.providerRef,
|
|
1110
|
+
userId,
|
|
1111
|
+
isNewUser,
|
|
1112
|
+
});
|
|
1113
|
+
|
|
1114
|
+
// 6. Redirect to frontend with the one-time exchange code (Decision 7)
|
|
1115
|
+
this.redirectToFrontendWithCode(res, exchangeToken.token, frontendUrl, stateMetadata.returnUrl);
|
|
1116
|
+
|
|
1117
|
+
} catch (error) {
|
|
1118
|
+
// Redirect to frontend with error instead of returning JSON.
|
|
1119
|
+
// frontendUrl may be set if handleCallback succeeded but a later step failed.
|
|
1120
|
+
// If handleCallback itself failed, frontendUrl is undefined → JSON fallback.
|
|
1121
|
+
const message = error instanceof Error ? error.message : 'OAuth2 authentication failed';
|
|
1122
|
+
this.logDebug('OAuth2 callback failed', { error: message });
|
|
1123
|
+
return this.redirectToFrontendWithError(
|
|
1124
|
+
res,
|
|
1125
|
+
AuthRedirectErrorCode.OAUTH_FAILED,
|
|
1126
|
+
message,
|
|
1127
|
+
frontendUrl,
|
|
1128
|
+
callbackReturnUrl,
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* POST /auth/token/exchange
|
|
1135
|
+
* Body: { code: string }
|
|
1136
|
+
* Response: { accessToken, refreshToken, expiresIn }
|
|
1137
|
+
*
|
|
1138
|
+
* The frontend calls this after receiving the one-time code from the OAuth2 callback redirect.
|
|
1139
|
+
* Validates and consumes the AUTH_CODE_EXCHANGE consumable token, returns the JWT tokens.
|
|
1140
|
+
*
|
|
1141
|
+
* Decision 7: Tokens never appear in URL — only a one-time code.
|
|
1142
|
+
*/
|
|
1143
|
+
private async tokenExchange(req: Request, res: Response): Promise<void> {
|
|
1144
|
+
const { code } = TokenExchangeBodySchema.parse(req.body || {});
|
|
1145
|
+
|
|
1146
|
+
// Consume the token atomically (prevents race conditions vs separate validate+consume)
|
|
1147
|
+
let consumedToken;
|
|
1148
|
+
try {
|
|
1149
|
+
consumedToken = await this.consumableTokenService.consumeToken(code);
|
|
1150
|
+
} catch {
|
|
1151
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
1152
|
+
customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_INVALID_TOKEN,
|
|
1153
|
+
context: { message: 'Invalid or expired exchange code' },
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
// Defense-in-depth: verify the token type is AUTH_CODE_EXCHANGE (same pattern as Step 4 OAUTH2_STATE check)
|
|
1158
|
+
if (consumedToken.tokenType !== CoreConsumableTokenTypes.AUTH_CODE_EXCHANGE) {
|
|
1159
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
1160
|
+
customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_INVALID_TOKEN,
|
|
1161
|
+
context: { message: 'Invalid token type for code exchange' },
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
const metadata = consumedToken.metadata as Record<string, unknown>;
|
|
1166
|
+
|
|
1167
|
+
if (consumedToken.userId) {
|
|
1168
|
+
await this.handleAnonymousTranspositionForTokenExchange(req, consumedToken.userId);
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
this.jsonSuccess(res, {
|
|
1172
|
+
accessToken: metadata.accessToken,
|
|
1173
|
+
refreshToken: metadata.refreshToken,
|
|
1174
|
+
expiresIn: metadata.expiresIn,
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* POST /auth/logout
|
|
1180
|
+
* Body: { refreshToken: string }
|
|
1181
|
+
* Response: 204 No Content
|
|
1182
|
+
*
|
|
1183
|
+
* Revokes the refresh token. Accessible both with and without a valid JWT
|
|
1184
|
+
* (user's access token may be expired when they logout).
|
|
1185
|
+
*/
|
|
1186
|
+
private async logout(req: Request, res: Response): Promise<void> {
|
|
1187
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1188
|
+
const { refreshToken } = LogoutBodySchema.parse(req.body || {});
|
|
1189
|
+
|
|
1190
|
+
// Try to decode the refresh token to get identity for audit (best-effort, don't fail logout if decode fails)
|
|
1191
|
+
let logoutUserId: string | undefined;
|
|
1192
|
+
try {
|
|
1193
|
+
const decoded = await this.jwtService.verifyRefreshToken(refreshToken);
|
|
1194
|
+
if (typeof decoded === 'object' && decoded !== null) {
|
|
1195
|
+
const payload = decoded as Record<string, unknown>;
|
|
1196
|
+
logoutUserId = typeof payload.userId === 'string' ? payload.userId : undefined;
|
|
1197
|
+
}
|
|
1198
|
+
} catch { /* token may be expired — that's fine */ }
|
|
1199
|
+
|
|
1200
|
+
// Revoke the refresh token by adding its JTI to the Redis blacklist.
|
|
1201
|
+
// The token issuer's refreshAccessToken() checks this blacklist before issuing new tokens.
|
|
1202
|
+
await this.tokenIssuer.revokeRefreshToken(refreshToken);
|
|
1203
|
+
|
|
1204
|
+
// H5: Audit logout
|
|
1205
|
+
this.auditLogsService.logUserLogout({
|
|
1206
|
+
userId: logoutUserId || 'unknown',
|
|
1207
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
1208
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1209
|
+
}).catch(() => {}); // fire-and-forget
|
|
1210
|
+
|
|
1211
|
+
this.logDebug('Logout completed — refresh token revoked');
|
|
1212
|
+
|
|
1213
|
+
res.status(204).send();
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1217
|
+
// Password Reset Route Handlers (Step 7)
|
|
1218
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1219
|
+
|
|
1220
|
+
/**
|
|
1221
|
+
* POST /auth/password-reset/request → AuthPasswordResetService.requestPasswordReset
|
|
1222
|
+
*/
|
|
1223
|
+
private async passwordResetRequest(req: Request, res: Response): Promise<void> {
|
|
1224
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1225
|
+
const { email } = PasswordResetRequestDtoSchema.parse(req.body || {});
|
|
1226
|
+
|
|
1227
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
1228
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.RESET_EMAIL}${email.toLowerCase()}`, 3, 3600);
|
|
1229
|
+
if (ipAddress !== 'unknown') {
|
|
1230
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.RESET_IP}${ipAddress}`, 5, 3600);
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
const frontendUrl = this.resolveFrontendAppPublicUrl(req);
|
|
1234
|
+
const result = await this.passwordResetService.requestPasswordReset(ec, {
|
|
1235
|
+
email, frontendUrl, ipAddress, userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1236
|
+
});
|
|
1237
|
+
this.jsonSuccess(res, result);
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
/**
|
|
1241
|
+
* POST /auth/password-reset/complete → AuthPasswordResetService.completePasswordReset
|
|
1242
|
+
*/
|
|
1243
|
+
private async passwordResetComplete(req: Request, res: Response): Promise<void> {
|
|
1244
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1245
|
+
const { token, newPassword } = PasswordResetCompleteDtoSchema.parse(req.body || {});
|
|
1246
|
+
|
|
1247
|
+
const result = await this.passwordResetService.completePasswordReset(ec, {
|
|
1248
|
+
token, newPassword,
|
|
1249
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
1250
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1251
|
+
});
|
|
1252
|
+
this.jsonSuccess(res, result);
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1256
|
+
// Registration Route Handlers (Step 8) → AuthRegistrationService
|
|
1257
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1258
|
+
|
|
1259
|
+
/**
|
|
1260
|
+
* POST /auth/register → AuthRegistrationService.registerUser
|
|
1261
|
+
*/
|
|
1262
|
+
private async register(req: Request, res: Response): Promise<void> {
|
|
1263
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1264
|
+
const { email, firstName, lastName, password, organizationName } = UserRegisterApiDtoSchema.parse(req.body || {});
|
|
1265
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
1266
|
+
|
|
1267
|
+
if (ipAddress !== 'unknown') await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.REGISTER_IP}${ipAddress}`, 3, 60);
|
|
1268
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.REGISTER_EMAIL}${email.toLowerCase()}`, 3, 3600);
|
|
1269
|
+
|
|
1270
|
+
const frontendUrl = this.resolveFrontendAppPublicUrl(req);
|
|
1271
|
+
|
|
1272
|
+
// W3.4 + AUTH-10: Resolve activeUserType for registration context.
|
|
1273
|
+
// For registration, the header is the authoritative source since the user doesn't exist yet.
|
|
1274
|
+
// The registration service validates the resolved type allows registration (mode != disabled).
|
|
1275
|
+
// AUTH-10: Cross-validate Origin against the claimed frontend service to prevent user-type spoofing.
|
|
1276
|
+
const frontendServiceNameReg = req.headers[WildoHeaderKeys.FRONTEND_SERVICE_NAME] as string | undefined;
|
|
1277
|
+
this._validateFrontendAppOrigin(req, frontendServiceNameReg);
|
|
1278
|
+
const activeUserTypeReg = frontendServiceNameReg
|
|
1279
|
+
? this.appConfigService.resolveUserTypeFromFrontendServiceName(frontendServiceNameReg) ?? undefined
|
|
1280
|
+
: undefined;
|
|
1281
|
+
|
|
1282
|
+
const result = await this.registrationService.registerUser(ec,
|
|
1283
|
+
{ email, firstName, lastName, password, organizationName },
|
|
1284
|
+
{ frontendUrl, ipAddress, userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown', frontendServiceName: frontendServiceNameReg, activeUserType: activeUserTypeReg },
|
|
1285
|
+
);
|
|
1286
|
+
this.jsonSuccess(res, result);
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
/**
|
|
1290
|
+
* POST /auth/invitation/accept → AuthRegistrationService.acceptInvitation
|
|
1291
|
+
*/
|
|
1292
|
+
private async acceptInvitation(req: Request, res: Response): Promise<void> {
|
|
1293
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1294
|
+
const { invitationToken, firstName, lastName, password } = UserInvitationApiDtoSchema.parse(req.body || {});
|
|
1295
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
1296
|
+
|
|
1297
|
+
if (ipAddress !== 'unknown') {
|
|
1298
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.INVITATION_ACCEPT_IP}${ipAddress}`, 10, 60);
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
const result = await this.registrationService.acceptInvitation(ec, {
|
|
1302
|
+
invitationToken,
|
|
1303
|
+
firstName,
|
|
1304
|
+
lastName,
|
|
1305
|
+
password,
|
|
1306
|
+
ipAddress,
|
|
1307
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1308
|
+
});
|
|
1309
|
+
|
|
1310
|
+
if (result.accessToken && result.userId) {
|
|
1311
|
+
await this.handleAnonymousTranspositionForTokenExchange(req, result.userId);
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
this.jsonSuccess(res, result);
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
/**
|
|
1318
|
+
* POST /auth/invitation/reject → AuthRegistrationService.rejectInvitation
|
|
1319
|
+
*/
|
|
1320
|
+
private async rejectInvitation(req: Request, res: Response): Promise<void> {
|
|
1321
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1322
|
+
const { invitationToken, rejectionReason } = UserInvitationRejectApiDtoSchema.parse(req.body || {});
|
|
1323
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
1324
|
+
|
|
1325
|
+
if (ipAddress !== 'unknown') {
|
|
1326
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.INVITATION_REJECT_IP}${ipAddress}`, 10, 60);
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
const result = await this.registrationService.rejectInvitation(ec, {
|
|
1330
|
+
invitationToken,
|
|
1331
|
+
rejectionReason,
|
|
1332
|
+
});
|
|
1333
|
+
|
|
1334
|
+
this.jsonSuccess(res, result);
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
/**
|
|
1338
|
+
* POST /auth/verify-email → AuthRegistrationService.verifyEmail
|
|
1339
|
+
*/
|
|
1340
|
+
private async verifyEmail(req: Request, res: Response): Promise<void> {
|
|
1341
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1342
|
+
const { token, email } = EmailVerifyDtoSchema.parse(req.body || {});
|
|
1343
|
+
|
|
1344
|
+
const result = await this.registrationService.verifyEmail(ec, {
|
|
1345
|
+
token, email,
|
|
1346
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
1347
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1348
|
+
});
|
|
1349
|
+
|
|
1350
|
+
if (result.accessToken && result.userId) {
|
|
1351
|
+
await this.handleAnonymousTranspositionForTokenExchange(req, result.userId);
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
this.jsonSuccess(res, result);
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
/**
|
|
1358
|
+
* POST /auth/resend-verification → AuthRegistrationService.resendVerificationEmail
|
|
1359
|
+
*/
|
|
1360
|
+
private async resendVerificationEmail(req: Request, res: Response): Promise<void> {
|
|
1361
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1362
|
+
const { email } = z.object({
|
|
1363
|
+
email: z.string().email(),
|
|
1364
|
+
}).parse(req.body || {});
|
|
1365
|
+
|
|
1366
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
1367
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.RESEND_VERIF_EMAIL}${email.toLowerCase()}`, 3, 600);
|
|
1368
|
+
if (ipAddress !== 'unknown') await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.RESEND_VERIF_IP}${ipAddress}`, 5, 600);
|
|
1369
|
+
|
|
1370
|
+
const frontendUrl = this.resolveFrontendAppPublicUrl(req);
|
|
1371
|
+
const result = await this.registrationService.resendVerificationEmail(ec, {
|
|
1372
|
+
email, frontendUrl, ipAddress,
|
|
1373
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1374
|
+
});
|
|
1375
|
+
this.jsonSuccess(res, result);
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
/**
|
|
1379
|
+
* POST /auth/onboarding/complete-org → AuthRegistrationService.completeOrgOnboarding
|
|
1380
|
+
*/
|
|
1381
|
+
private async completeOrgOnboarding(req: Request, res: Response): Promise<void> {
|
|
1382
|
+
const clientIp = AuthControllerUtils.getClientIpFromRequest(req);
|
|
1383
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.ORG_ONBOARDING_IP}${clientIp}`, 10, 60);
|
|
1384
|
+
|
|
1385
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1386
|
+
const { sessionId, organizationName } = z.object({
|
|
1387
|
+
sessionId: z.string(),
|
|
1388
|
+
organizationName: z.string().min(1).max(200)
|
|
1389
|
+
.regex(/^[^<>"'`;{}()\\]+$/, 'Organization name contains disallowed characters'),
|
|
1390
|
+
}).parse(req.body || {});
|
|
1391
|
+
|
|
1392
|
+
const result = await this.registrationService.completeOrgOnboarding(ec, {
|
|
1393
|
+
sessionId,
|
|
1394
|
+
organizationName: organizationName.trim(),
|
|
1395
|
+
});
|
|
1396
|
+
this.jsonSuccess(res, result);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1400
|
+
// MFA: Email OTP Route Handlers (Step 10)
|
|
1401
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1402
|
+
|
|
1403
|
+
/**
|
|
1404
|
+
* POST /auth/mfa/email-otp/send
|
|
1405
|
+
* Body: { sessionId: string }
|
|
1406
|
+
* Response: { message: string }
|
|
1407
|
+
*
|
|
1408
|
+
* Generates a 6-digit OTP, stores as consumable token, sends email to user.
|
|
1409
|
+
* Must be called after first factor completion (session state = FIRST_FACTOR_COMPLETED).
|
|
1410
|
+
*/
|
|
1411
|
+
private async mfaEmailOTPSend(req: Request, res: Response): Promise<void> {
|
|
1412
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1413
|
+
const body = z.object({ sessionId: z.string().min(1) }).parse(req.body || {});
|
|
1414
|
+
|
|
1415
|
+
this.logDebug('MFA Email OTP send requested', { sessionId: body.sessionId });
|
|
1416
|
+
|
|
1417
|
+
// Orchestrator handles validation, rate limiting, OTP generation, and token storage.
|
|
1418
|
+
// It returns the OTP code and the user's email — we send the email here.
|
|
1419
|
+
const { otpToken, email, expiryMinutes } = await this.authService.sendEmailOTP(ec, body.sessionId);
|
|
1420
|
+
|
|
1421
|
+
// Send the OTP email
|
|
1422
|
+
try {
|
|
1423
|
+
const appIdentity = this.appConfigService.config.appIdentity;
|
|
1424
|
+
await this.emailService.send({
|
|
1425
|
+
templateRef: SystemEmailTemplateRef.EMAIL_OTP,
|
|
1426
|
+
locale: AvailableLanguage.EN,
|
|
1427
|
+
type: EmailTemplateType.TRANSACTIONAL,
|
|
1428
|
+
to: email,
|
|
1429
|
+
context: {
|
|
1430
|
+
currentObject: { email },
|
|
1431
|
+
objectContext: {
|
|
1432
|
+
primaryScopeContext: {
|
|
1433
|
+
appName: appIdentity.appName,
|
|
1434
|
+
applicationId: this.appConfigService.applicationId,
|
|
1435
|
+
},
|
|
1436
|
+
},
|
|
1437
|
+
userContext: { userId: '', email }, // userId not available in pre-auth flow; email is the key identifier
|
|
1438
|
+
additionalContext: { otpCode: otpToken, expiresInMinutes: expiryMinutes },
|
|
1439
|
+
},
|
|
1440
|
+
});
|
|
1441
|
+
this.logDebug('MFA Email OTP sent', { email });
|
|
1442
|
+
} catch (emailError) {
|
|
1443
|
+
this.logger.error('Failed to send MFA email OTP', {
|
|
1444
|
+
error: emailError instanceof Error ? emailError.message : String(emailError),
|
|
1445
|
+
});
|
|
1446
|
+
// Still return success — the OTP was generated and stored.
|
|
1447
|
+
// User can retry sending if email delivery fails.
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
// H5: Audit MFA email OTP sent
|
|
1451
|
+
this.auditLogsService.logUserMFAEmailOTPSent({
|
|
1452
|
+
email,
|
|
1453
|
+
sessionId: body.sessionId,
|
|
1454
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
1455
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1456
|
+
}).catch(() => {});
|
|
1457
|
+
|
|
1458
|
+
this.jsonSuccess(res, this.authResponseHelper.getAuthResponse(AuthResponseMessageRef.MFA_EMAIL_OTP_SENT));
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
/**
|
|
1462
|
+
* POST /auth/mfa/email-otp/verify
|
|
1463
|
+
* Body: { sessionId: string, code: string }
|
|
1464
|
+
* Response: AuthenticationResponse (from orchestrator)
|
|
1465
|
+
*
|
|
1466
|
+
* Verifies the submitted OTP code against stored consumable tokens.
|
|
1467
|
+
* On success, returns authentication result (may complete auth or require more factors).
|
|
1468
|
+
*/
|
|
1469
|
+
private async mfaEmailOTPVerify(req: Request, res: Response): Promise<void> {
|
|
1470
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1471
|
+
const body = z.object({
|
|
1472
|
+
sessionId: z.string().min(1),
|
|
1473
|
+
code: z.string().regex(/^\d{4,8}$/, { error: 'Invalid OTP code' }),
|
|
1474
|
+
}).parse(req.body || {});
|
|
1475
|
+
|
|
1476
|
+
this.logDebug('MFA Email OTP verify requested', { sessionId: body.sessionId });
|
|
1477
|
+
|
|
1478
|
+
// Build an EmailOTPAuthRequest and route through the main authenticate method
|
|
1479
|
+
// so that completion logic (token issuance) is handled uniformly.
|
|
1480
|
+
const authRequest = {
|
|
1481
|
+
sessionId: body.sessionId,
|
|
1482
|
+
method: AuthMethod.EMAIL_OTP as const,
|
|
1483
|
+
factorLevel: AuthFactorLevel.SECOND as const,
|
|
1484
|
+
token: body.code,
|
|
1485
|
+
rememberMe: false,
|
|
1486
|
+
requestedIntegrations: [],
|
|
1487
|
+
};
|
|
1488
|
+
|
|
1489
|
+
const result = await this.authService.authenticate(ec, authRequest);
|
|
1490
|
+
this.jsonSuccess(res, result);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1494
|
+
// MFA: TOTP Route Handlers (Step 11)
|
|
1495
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1496
|
+
|
|
1497
|
+
/**
|
|
1498
|
+
* POST /auth/mfa/totp/setup
|
|
1499
|
+
* Headers: Authorization: Bearer <accessToken>
|
|
1500
|
+
* Response: { secret: string, qrCodeUri: string, backupCodes: string[] }
|
|
1501
|
+
*
|
|
1502
|
+
* Uses `extractFromSessionOrJwt` — the caller may be fully authenticated (JWT)
|
|
1503
|
+
* or partially authenticated (MFA_REQUIRED / MFA_ENROLLMENT_REQUIRED session).
|
|
1504
|
+
* In the partial-auth path, identity is not yet fully proven, so we intentionally
|
|
1505
|
+
* use a pre-auth EC (no userId attribution). Security relies on the JWT guard /
|
|
1506
|
+
* session state validation in `extractFromSessionOrJwt`, not on the EC's role.
|
|
1507
|
+
*/
|
|
1508
|
+
private async mfaTOTPSetup(req: Request, res: Response): Promise<void> {
|
|
1509
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1510
|
+
const { userId, email } = await this.authJwtGuard.extractFromSessionOrJwt(ec, req);
|
|
1511
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.TOTP_SETUP}${userId}`, 5, 3600);
|
|
1512
|
+
|
|
1513
|
+
const result = await this.mfaService.setupTOTP(ec, {
|
|
1514
|
+
userId,
|
|
1515
|
+
email,
|
|
1516
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
1517
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1520
|
+
this.jsonSuccess(res, result);
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
/**
|
|
1524
|
+
* POST /auth/mfa/totp/verify-setup
|
|
1525
|
+
* Headers: Authorization: Bearer <accessToken>
|
|
1526
|
+
* Body: { code: string }
|
|
1527
|
+
* Response: { verified: boolean }
|
|
1528
|
+
*
|
|
1529
|
+
* Uses `extractFromSessionOrJwt` — caller may be partially authenticated
|
|
1530
|
+
* (mid-MFA enrollment). Pre-auth EC used intentionally: identity is not
|
|
1531
|
+
* fully proven until MFA setup completes. See mfaTOTPSetup JSDoc.
|
|
1532
|
+
*/
|
|
1533
|
+
private async mfaTOTPVerifySetup(req: Request, res: Response): Promise<void> {
|
|
1534
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1535
|
+
const { userId } = await this.authJwtGuard.extractFromSessionOrJwt(ec, req);
|
|
1536
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.TOTP_SETUP}${userId}`, 5, 3600);
|
|
1537
|
+
const body = z.object({
|
|
1538
|
+
code: z.string().regex(/^\d{6}$/, { error: 'Invalid TOTP code — must be 6 digits' }),
|
|
1539
|
+
}).parse(req.body || {});
|
|
1540
|
+
|
|
1541
|
+
const result = await this.mfaService.verifyTOTPSetup(ec, {
|
|
1542
|
+
userId,
|
|
1543
|
+
code: body.code,
|
|
1544
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
1545
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1546
|
+
});
|
|
1547
|
+
|
|
1548
|
+
this.jsonSuccess(res, result);
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
/**
|
|
1552
|
+
* POST /auth/mfa/totp/verify
|
|
1553
|
+
* Body: { sessionId: string, code: string }
|
|
1554
|
+
* Response: AuthenticationResponse (from orchestrator)
|
|
1555
|
+
*
|
|
1556
|
+
* Verifies a TOTP code during login MFA flow.
|
|
1557
|
+
* Routes through the main authenticate method for uniform completion logic.
|
|
1558
|
+
*/
|
|
1559
|
+
private async mfaTOTPVerify(req: Request, res: Response): Promise<void> {
|
|
1560
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1561
|
+
const body = z.object({
|
|
1562
|
+
sessionId: z.string().min(1),
|
|
1563
|
+
code: z.string().min(1, { error: 'TOTP code is required' }),
|
|
1564
|
+
}).parse(req.body || {});
|
|
1565
|
+
|
|
1566
|
+
this.logDebug('MFA TOTP verify requested', { sessionId: body.sessionId });
|
|
1567
|
+
|
|
1568
|
+
const authRequest = {
|
|
1569
|
+
sessionId: body.sessionId,
|
|
1570
|
+
method: AuthMethod.TOTP as const,
|
|
1571
|
+
factorLevel: AuthFactorLevel.SECOND as const,
|
|
1572
|
+
token: body.code,
|
|
1573
|
+
rememberMe: false,
|
|
1574
|
+
requestedIntegrations: [],
|
|
1575
|
+
};
|
|
1576
|
+
|
|
1577
|
+
const result = await this.authService.authenticate(ec, authRequest);
|
|
1578
|
+
this.jsonSuccess(res, result);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1582
|
+
// WebAuthn/Passkey Route Handlers (Phase G1)
|
|
1583
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1584
|
+
|
|
1585
|
+
/**
|
|
1586
|
+
* POST /auth/passkey/register/options
|
|
1587
|
+
* Headers: Authorization: Bearer <accessToken>
|
|
1588
|
+
* Response: PublicKeyCredentialCreationOptionsJSON
|
|
1589
|
+
*
|
|
1590
|
+
* Uses `extractFromSessionOrJwt` — caller may be partially authenticated
|
|
1591
|
+
* (mid-MFA enrollment, registering a passkey as their MFA method).
|
|
1592
|
+
* Pre-auth EC used intentionally: identity not fully proven until
|
|
1593
|
+
* MFA enrollment completes. See mfaTOTPSetup JSDoc.
|
|
1594
|
+
*/
|
|
1595
|
+
private async handlePasskeyRegisterOptions(req: Request, res: Response): Promise<void> {
|
|
1596
|
+
try {
|
|
1597
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1598
|
+
const { userId, email } = await this.authJwtGuard.extractFromSessionOrJwt(ec, req);
|
|
1599
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.PASSKEY_REGISTER}${userId}`, 10, 3600);
|
|
1600
|
+
const options = await this.webAuthnService.generateRegistrationOptions(ec, userId, email);
|
|
1601
|
+
this.jsonSuccess(res, options);
|
|
1602
|
+
} catch (error) {
|
|
1603
|
+
if (isWildoBackendError(error)) throw error;
|
|
1604
|
+
throw this.errorBuilder.buildError(ErrorType.INTERNAL, undefined, {
|
|
1605
|
+
context: { operation: AUTH_OPERATION.PASSKEY_REGISTER_OPTIONS },
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
/**
|
|
1611
|
+
* POST /auth/passkey/register/verify
|
|
1612
|
+
* Headers: Authorization: Bearer <accessToken>
|
|
1613
|
+
* Body: { response: RegistrationResponseJSON, name?: string }
|
|
1614
|
+
* Response: { registered: boolean, credential: { credentialId, name, createdAt } }
|
|
1615
|
+
*
|
|
1616
|
+
* Uses `extractFromSessionOrJwt` — caller may be partially authenticated
|
|
1617
|
+
* (mid-MFA enrollment). Pre-auth EC used intentionally: identity not fully
|
|
1618
|
+
* proven until MFA enrollment completes. See mfaTOTPSetup JSDoc.
|
|
1619
|
+
*/
|
|
1620
|
+
private async handlePasskeyRegisterVerify(req: Request, res: Response): Promise<void> {
|
|
1621
|
+
try {
|
|
1622
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1623
|
+
const { userId, email } = await this.authJwtGuard.extractFromSessionOrJwt(ec, req);
|
|
1624
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.PASSKEY_REGISTER}${userId}`, 10, 3600);
|
|
1625
|
+
const PasskeyRegisterVerifyBodySchema = z.object({
|
|
1626
|
+
response: z.object({
|
|
1627
|
+
id: z.string(),
|
|
1628
|
+
rawId: z.string(),
|
|
1629
|
+
response: z.object({
|
|
1630
|
+
attestationObject: z.string(),
|
|
1631
|
+
clientDataJSON: z.string(),
|
|
1632
|
+
}),
|
|
1633
|
+
authenticatorAttachment: z.enum(['cross-platform', 'platform'] as const).optional(),
|
|
1634
|
+
clientExtensionResults: z.record(z.string(), z.any()).default({}),
|
|
1635
|
+
type: z.literal('public-key'),
|
|
1636
|
+
}),
|
|
1637
|
+
name: z.string().max(100).optional(),
|
|
1638
|
+
});
|
|
1639
|
+
const { response, name } = PasskeyRegisterVerifyBodySchema.parse(req.body || {});
|
|
1640
|
+
const credential = await this.webAuthnService.verifyRegistrationResponse(ec, userId, response, name);
|
|
1641
|
+
|
|
1642
|
+
await this.auditLogsService.logUserPasskeyRegistered({
|
|
1643
|
+
userId: userId,
|
|
1644
|
+
email,
|
|
1645
|
+
credentialId: credential.credentialId,
|
|
1646
|
+
credentialName: credential.name,
|
|
1647
|
+
credentialDeviceType: credential.credentialDeviceType,
|
|
1648
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
1649
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1650
|
+
});
|
|
1651
|
+
|
|
1652
|
+
this.jsonSuccess(res, {
|
|
1653
|
+
registered: true,
|
|
1654
|
+
credential: {
|
|
1655
|
+
credentialId: credential.credentialId,
|
|
1656
|
+
name: credential.name,
|
|
1657
|
+
createdAt: credential.createdAt,
|
|
1658
|
+
},
|
|
1659
|
+
});
|
|
1660
|
+
} catch (error) {
|
|
1661
|
+
if (isWildoBackendError(error)) throw error;
|
|
1662
|
+
throw this.errorBuilder.buildError(ErrorType.INTERNAL, undefined, {
|
|
1663
|
+
context: { operation: AUTH_OPERATION.PASSKEY_REGISTER_VERIFY },
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
/**
|
|
1669
|
+
* POST /auth/passkey/authenticate/options
|
|
1670
|
+
* Body: { sessionId: string }
|
|
1671
|
+
* Response: PublicKeyCredentialRequestOptionsJSON
|
|
1672
|
+
*
|
|
1673
|
+
* Unauthenticated. Part of login flow. Generates authentication options for the session's user.
|
|
1674
|
+
*/
|
|
1675
|
+
private async handlePasskeyAuthOptions(req: Request, res: Response): Promise<void> {
|
|
1676
|
+
try {
|
|
1677
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1678
|
+
const { sessionId } = req.body;
|
|
1679
|
+
if (!sessionId) {
|
|
1680
|
+
throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
|
|
1681
|
+
context: { reason: 'sessionId is required' },
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
const session = await this.authService.getAuthenticationSessionState(ec, sessionId);
|
|
1686
|
+
if (!session) {
|
|
1687
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
1688
|
+
customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_SESSION_INVALID,
|
|
1689
|
+
context: { sessionId },
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
const validStatesForPasskeyAuth = new Set([
|
|
1694
|
+
AuthenticationSessionState.IDENTIFIED,
|
|
1695
|
+
AuthenticationSessionState.FIRST_FACTOR_IN_PROGRESS,
|
|
1696
|
+
AuthenticationSessionState.FIRST_FACTOR_COMPLETED,
|
|
1697
|
+
AuthenticationSessionState.MFA_REQUIRED,
|
|
1698
|
+
]);
|
|
1699
|
+
if (!validStatesForPasskeyAuth.has(session.state as AuthenticationSessionState)) {
|
|
1700
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
1701
|
+
context: { reason: 'Invalid session state for passkey authentication' },
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
const userId = session.userId;
|
|
1706
|
+
if (!userId) {
|
|
1707
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
1708
|
+
context: { reason: 'No user associated with session' },
|
|
1709
|
+
});
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
const options = await this.webAuthnService.generateAuthenticationOptions(ec, userId);
|
|
1713
|
+
this.jsonSuccess(res, options);
|
|
1714
|
+
} catch (error) {
|
|
1715
|
+
if (isWildoBackendError(error)) throw error;
|
|
1716
|
+
throw this.errorBuilder.buildError(ErrorType.INTERNAL, undefined, {
|
|
1717
|
+
context: { operation: AUTH_OPERATION.PASSKEY_AUTH_OPTIONS },
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
/**
|
|
1723
|
+
* POST /auth/passkey/authenticate/verify
|
|
1724
|
+
* Body: { sessionId: string, response: AuthenticationResponseJSON, factorLevel?: AuthFactorLevel }
|
|
1725
|
+
* Response: AuthenticationResponse (from orchestrator)
|
|
1726
|
+
*
|
|
1727
|
+
* Unauthenticated. Routes through authService.authenticate() for uniform completion logic.
|
|
1728
|
+
*/
|
|
1729
|
+
private async handlePasskeyAuthVerify(req: Request, res: Response): Promise<void> {
|
|
1730
|
+
try {
|
|
1731
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
1732
|
+
const PasskeyAuthVerifyBodySchema = z.object({
|
|
1733
|
+
sessionId: z.string().min(1),
|
|
1734
|
+
response: z.object({
|
|
1735
|
+
id: z.string(),
|
|
1736
|
+
rawId: z.string(),
|
|
1737
|
+
response: z.object({
|
|
1738
|
+
authenticatorData: z.string(),
|
|
1739
|
+
clientDataJSON: z.string(),
|
|
1740
|
+
signature: z.string(),
|
|
1741
|
+
userHandle: z.string().optional(),
|
|
1742
|
+
}),
|
|
1743
|
+
authenticatorAttachment: z.enum(['cross-platform', 'platform'] as const).optional(),
|
|
1744
|
+
clientExtensionResults: z.record(z.string(), z.any()).default({}),
|
|
1745
|
+
type: z.literal('public-key'),
|
|
1746
|
+
}),
|
|
1747
|
+
factorLevel: z.string().optional(),
|
|
1748
|
+
});
|
|
1749
|
+
const { sessionId, response, factorLevel } = PasskeyAuthVerifyBodySchema.parse(req.body || {});
|
|
1750
|
+
|
|
1751
|
+
const authResponse = await this.authService.authenticate(ec, {
|
|
1752
|
+
sessionId,
|
|
1753
|
+
method: AuthMethod.PASSKEY,
|
|
1754
|
+
factorLevel: (factorLevel as AuthFactorLevel) || AuthFactorLevel.FIRST,
|
|
1755
|
+
response,
|
|
1756
|
+
rememberMe: false,
|
|
1757
|
+
requestedIntegrations: [],
|
|
1758
|
+
});
|
|
1759
|
+
await this.handleAnonymousTransposition(req, authResponse);
|
|
1760
|
+
this.jsonSuccess(res, authResponse);
|
|
1761
|
+
} catch (error) {
|
|
1762
|
+
if (isWildoBackendError(error)) throw error;
|
|
1763
|
+
throw this.errorBuilder.buildError(ErrorType.INTERNAL, undefined, {
|
|
1764
|
+
context: { operation: AUTH_OPERATION.PASSKEY_AUTH_VERIFY },
|
|
1765
|
+
});
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
/**
|
|
1770
|
+
* GET /auth/passkey/list
|
|
1771
|
+
* Headers: Authorization: Bearer <accessToken>
|
|
1772
|
+
* Response: { credentials: PasskeyCredentialEntry[] } (safe fields only)
|
|
1773
|
+
*
|
|
1774
|
+
* JWT-authenticated. Lists registered passkeys for the authenticated user.
|
|
1775
|
+
*/
|
|
1776
|
+
private async handlePasskeyList(req: Request, res: Response): Promise<void> {
|
|
1777
|
+
try {
|
|
1778
|
+
const preAuthEc = await this._getPreAuthExecutionContext();
|
|
1779
|
+
const { userId } = await this.authJwtGuard.extractAuthenticatedUser(preAuthEc, req);
|
|
1780
|
+
const ec = await this._getAuthenticatedExecutionContext(userId);
|
|
1781
|
+
const credentials = await this.webAuthnService.getCredentials(ec, userId);
|
|
1782
|
+
|
|
1783
|
+
const safeCredentials = credentials.map((c) => ({
|
|
1784
|
+
credentialId: c.credentialId,
|
|
1785
|
+
name: c.name,
|
|
1786
|
+
createdAt: c.createdAt,
|
|
1787
|
+
lastUsedAt: c.lastUsedAt,
|
|
1788
|
+
credentialDeviceType: c.credentialDeviceType,
|
|
1789
|
+
credentialBackedUp: c.credentialBackedUp,
|
|
1790
|
+
}));
|
|
1791
|
+
this.jsonSuccess(res, { credentials: safeCredentials });
|
|
1792
|
+
} catch (error) {
|
|
1793
|
+
if (isWildoBackendError(error)) throw error;
|
|
1794
|
+
throw this.errorBuilder.buildError(ErrorType.INTERNAL, undefined, {
|
|
1795
|
+
context: { operation: AUTH_OPERATION.PASSKEY_LIST },
|
|
1796
|
+
});
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
/**
|
|
1801
|
+
* POST /auth/passkey/remove
|
|
1802
|
+
* Headers: Authorization: Bearer <accessToken>
|
|
1803
|
+
* Body: { credentialId: string }
|
|
1804
|
+
* Response: { removed: boolean }
|
|
1805
|
+
*
|
|
1806
|
+
* JWT-authenticated. Removes a passkey from the authenticated user.
|
|
1807
|
+
*/
|
|
1808
|
+
private async handlePasskeyRemove(req: Request, res: Response): Promise<void> {
|
|
1809
|
+
try {
|
|
1810
|
+
const preAuthEc = await this._getPreAuthExecutionContext();
|
|
1811
|
+
const { userId, email } = await this.authJwtGuard.extractAuthenticatedUser(preAuthEc, req);
|
|
1812
|
+
const ec = await this._getAuthenticatedExecutionContext(userId);
|
|
1813
|
+
const { credentialId } = req.body;
|
|
1814
|
+
if (!credentialId) {
|
|
1815
|
+
throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
|
|
1816
|
+
context: { reason: 'credentialId is required' },
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
await this.methodManagementService.enforceUserMethodRemovalAllowed(ec, userId);
|
|
1820
|
+
|
|
1821
|
+
const credentials = await this.webAuthnService.getCredentials(ec, userId);
|
|
1822
|
+
const target = credentials.find((c) => c.credentialId === credentialId);
|
|
1823
|
+
|
|
1824
|
+
// D9 safety check: count password + passkeys + identity links
|
|
1825
|
+
const authMethodCounts = await this.methodManagementService.countAuthMethods(ec, userId);
|
|
1826
|
+
if (authMethodCounts.total <= 1) {
|
|
1827
|
+
throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
|
|
1828
|
+
context: { reason: 'Cannot remove your only authentication method' },
|
|
1829
|
+
});
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
await this.webAuthnService.removeCredential(ec, userId, credentialId);
|
|
1833
|
+
|
|
1834
|
+
await this.auditLogsService.logUserPasskeyRemoved({
|
|
1835
|
+
userId: userId,
|
|
1836
|
+
email,
|
|
1837
|
+
credentialId,
|
|
1838
|
+
credentialName: target?.name || 'Unknown',
|
|
1839
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
1840
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
1841
|
+
});
|
|
1842
|
+
|
|
1843
|
+
this.jsonSuccess(res, { removed: true });
|
|
1844
|
+
} catch (error) {
|
|
1845
|
+
if (isWildoBackendError(error)) throw error;
|
|
1846
|
+
throw this.errorBuilder.buildError(ErrorType.INTERNAL, undefined, {
|
|
1847
|
+
context: { operation: AUTH_OPERATION.PASSKEY_REMOVE },
|
|
1848
|
+
});
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
/**
|
|
1853
|
+
* POST /auth/passkey/rename
|
|
1854
|
+
* Headers: Authorization: Bearer <accessToken>
|
|
1855
|
+
* Body: { credentialId: string, name: string }
|
|
1856
|
+
* Response: { renamed: boolean }
|
|
1857
|
+
*
|
|
1858
|
+
* JWT-authenticated. Renames a passkey for the authenticated user.
|
|
1859
|
+
*/
|
|
1860
|
+
private async handlePasskeyRename(req: Request, res: Response): Promise<void> {
|
|
1861
|
+
try {
|
|
1862
|
+
const preAuthEc = await this._getPreAuthExecutionContext();
|
|
1863
|
+
const { userId } = await this.authJwtGuard.extractAuthenticatedUser(preAuthEc, req);
|
|
1864
|
+
const ec = await this._getAuthenticatedExecutionContext(userId);
|
|
1865
|
+
const { credentialId, name } = req.body;
|
|
1866
|
+
if (!credentialId || !name) {
|
|
1867
|
+
throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
|
|
1868
|
+
context: { reason: 'credentialId and name are required' },
|
|
1869
|
+
});
|
|
1870
|
+
}
|
|
1871
|
+
await this.webAuthnService.renameCredential(ec, userId, credentialId, name);
|
|
1872
|
+
this.jsonSuccess(res, { renamed: true });
|
|
1873
|
+
} catch (error) {
|
|
1874
|
+
if (isWildoBackendError(error)) throw error;
|
|
1875
|
+
throw this.errorBuilder.buildError(ErrorType.INTERNAL, undefined, {
|
|
1876
|
+
context: { operation: AUTH_OPERATION.PASSKEY_RENAME },
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
|
|
1882
|
+
/**
|
|
1883
|
+
* Pre-auth EC for operations where the caller is not yet authenticated.
|
|
1884
|
+
* Uses PUBLIC_EXECUTION with APP_PUBLIC (minimal privilege, no initiator).
|
|
1885
|
+
* Primary intent: user identification/lookup across auth handlers.
|
|
1886
|
+
*
|
|
1887
|
+
* Also used as the bootstrap EC for JWT/session extraction calls
|
|
1888
|
+
* (`extractAuthenticatedUser`, `extractFromSessionOrJwt`) since identity
|
|
1889
|
+
* is unknown at that point.
|
|
1890
|
+
*/
|
|
1891
|
+
private async _getPreAuthExecutionContext() {
|
|
1892
|
+
return this.authEcFactory.createForPreAuthOperation(this.authEcFactory.getUsersReadOperationPath());
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
/**
|
|
1896
|
+
* Authenticated EC for operations where the caller's identity has been
|
|
1897
|
+
* confirmed via JWT. Carries userId attribution for audit trail and
|
|
1898
|
+
* uses APP_USER role.
|
|
1899
|
+
*
|
|
1900
|
+
* Endpoints that call `extractAuthenticatedUser` (requiring a valid JWT)
|
|
1901
|
+
* should use this for all downstream service calls after extraction.
|
|
1902
|
+
*/
|
|
1903
|
+
private async _getAuthenticatedExecutionContext(userId: string) {
|
|
1904
|
+
return this.authEcFactory.createForAuthenticatedAuthOperation(userId, this.authEcFactory.getUsersReadOperationPath());
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1908
|
+
// Private: Frontend Redirect Helpers
|
|
1909
|
+
// ═══════════════════════════════════════════════════════════════
|
|
1910
|
+
|
|
1911
|
+
/**
|
|
1912
|
+
* Redirect to the frontend callback page with the one-time exchange code.
|
|
1913
|
+
* URL: {frontendUrl}/auth/callback?code={exchangeCode}
|
|
1914
|
+
*
|
|
1915
|
+
* @param frontendUrl - The resolved frontend publicUrl from the OAuth2 state token.
|
|
1916
|
+
* If undefined (state token didn't carry frontendServiceName — legacy flows), throws.
|
|
1917
|
+
*/
|
|
1918
|
+
private redirectToFrontendWithCode(
|
|
1919
|
+
res: Response,
|
|
1920
|
+
exchangeCode: string,
|
|
1921
|
+
frontendUrl?: string,
|
|
1922
|
+
returnUrl?: string,
|
|
1923
|
+
): void {
|
|
1924
|
+
if (!frontendUrl) {
|
|
1925
|
+
throw this.errorBuilder.buildError(ErrorType.INTERNAL, undefined, {
|
|
1926
|
+
context: { message: 'Cannot redirect: frontendServiceName was not stored in OAuth2 state token. The originating frontend is unknown.' },
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1929
|
+
const searchParams = new URLSearchParams({
|
|
1930
|
+
code: exchangeCode,
|
|
1931
|
+
});
|
|
1932
|
+
if (returnUrl) {
|
|
1933
|
+
searchParams.set('redirect', returnUrl);
|
|
1934
|
+
}
|
|
1935
|
+
const redirectUrl = `${frontendUrl}/auth/callback?${searchParams.toString()}`;
|
|
1936
|
+
res.redirect(302, redirectUrl);
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
/**
|
|
1940
|
+
* Redirect to the frontend login page with an error.
|
|
1941
|
+
* URL: {frontendUrl}/login?error={error}&reason={description}
|
|
1942
|
+
*
|
|
1943
|
+
* TRAP 6: Error redirect goes to login page (not generic error page)
|
|
1944
|
+
* so the user can retry.
|
|
1945
|
+
*
|
|
1946
|
+
* If frontendUrl is undefined (state token didn't carry frontendServiceName, or error
|
|
1947
|
+
* occurred before state could be read), falls back to a plain JSON error
|
|
1948
|
+
* since we can't redirect to an unknown frontend.
|
|
1949
|
+
*/
|
|
1950
|
+
private redirectToFrontendWithError(
|
|
1951
|
+
res: Response,
|
|
1952
|
+
error: string,
|
|
1953
|
+
description: string,
|
|
1954
|
+
frontendUrl?: string,
|
|
1955
|
+
returnUrl?: string,
|
|
1956
|
+
): void {
|
|
1957
|
+
if (!frontendUrl) {
|
|
1958
|
+
res.status(400).json({ error, error_description: description });
|
|
1959
|
+
return;
|
|
1960
|
+
}
|
|
1961
|
+
const searchParams = new URLSearchParams({
|
|
1962
|
+
error,
|
|
1963
|
+
reason: description,
|
|
1964
|
+
});
|
|
1965
|
+
if (returnUrl) {
|
|
1966
|
+
searchParams.set('redirect', returnUrl);
|
|
1967
|
+
}
|
|
1968
|
+
const redirectUrl = `${frontendUrl}/login?${searchParams.toString()}`;
|
|
1969
|
+
res.redirect(302, redirectUrl);
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
private validateFrontendReturnUrl(returnUrl: string, frontendUrl: string): void {
|
|
1973
|
+
if (returnUrl.startsWith('/') && !returnUrl.startsWith('//')) {
|
|
1974
|
+
return;
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
const allowedOrigins = new Set<string>();
|
|
1978
|
+
try {
|
|
1979
|
+
allowedOrigins.add(new URL(frontendUrl).origin);
|
|
1980
|
+
} catch {
|
|
1981
|
+
// frontendUrl comes from validated config, but keep the helper defensive.
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
for (const frontendServiceName of Object.keys(this.appConfigService.config.frontendServices ?? {})) {
|
|
1985
|
+
const publicUrl = AuthControllerUtils.lookupFrontendPublicUrl(
|
|
1986
|
+
this.appConfigService.config,
|
|
1987
|
+
frontendServiceName,
|
|
1988
|
+
);
|
|
1989
|
+
if (!publicUrl) {
|
|
1990
|
+
continue;
|
|
1991
|
+
}
|
|
1992
|
+
allowedOrigins.add(new URL(publicUrl).origin);
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
try {
|
|
1996
|
+
const parsed = new URL(returnUrl);
|
|
1997
|
+
if (allowedOrigins.has(parsed.origin)) {
|
|
1998
|
+
return;
|
|
1999
|
+
}
|
|
2000
|
+
} catch {
|
|
2001
|
+
// Invalid absolute URL — reject below.
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
|
|
2005
|
+
customMessageReference: ErrorCustomMessageReference.VALIDATION,
|
|
2006
|
+
context: {
|
|
2007
|
+
message: 'Invalid returnUrl: must be a relative path or an allowed frontend origin',
|
|
2008
|
+
returnUrl,
|
|
2009
|
+
},
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
/**
|
|
2014
|
+
* Resolve the public URL of the frontend app that initiated this request.
|
|
2015
|
+
*
|
|
2016
|
+
* Reads the X-Frontend-Service-Name header (a configured frontend service identity),
|
|
2017
|
+
* then looks up the
|
|
2018
|
+
* corresponding publicUrl from the configured runtime endpoints.
|
|
2019
|
+
*
|
|
2020
|
+
* Fail-fast: throws if the header is missing, the frontend service is unknown,
|
|
2021
|
+
* or no publicUrl is configured for that frontend service.
|
|
2022
|
+
*/
|
|
2023
|
+
private resolveFrontendAppPublicUrl(req: Request): string {
|
|
2024
|
+
const frontendServiceName = req.headers[WildoHeaderKeys.FRONTEND_SERVICE_NAME] as string | undefined;
|
|
2025
|
+
|
|
2026
|
+
if (!frontendServiceName) {
|
|
2027
|
+
throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
|
|
2028
|
+
context: {
|
|
2029
|
+
message: 'X-Frontend-Service-Name header is required. The frontend must identify itself.',
|
|
2030
|
+
header: WildoHeaderKeys.FRONTEND_SERVICE_NAME,
|
|
2031
|
+
},
|
|
2032
|
+
});
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
return this._lookupFrontendPublicUrl(frontendServiceName);
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
/**
|
|
2039
|
+
* Resolve the frontend service identity from a raw string (e.g., from state token metadata).
|
|
2040
|
+
* Returns the publicUrl for that frontend service. Throws if invalid or not configured.
|
|
2041
|
+
*/
|
|
2042
|
+
private resolveFrontendAppPublicUrlFromFrontendServiceName(frontendServiceName: string): string {
|
|
2043
|
+
return this._lookupFrontendPublicUrl(frontendServiceName);
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
/**
|
|
2047
|
+
* Core lookup: delegates to AuthControllerUtils.lookupFrontendPublicUrl (returns null on failure),
|
|
2048
|
+
* then throws if null. Preserves the original fail-fast behavior in the controller.
|
|
2049
|
+
*/
|
|
2050
|
+
private _lookupFrontendPublicUrl(frontendServiceName: string): string {
|
|
2051
|
+
const url = AuthControllerUtils.lookupFrontendPublicUrl(this.appConfigService.config, frontendServiceName);
|
|
2052
|
+
if (!url) {
|
|
2053
|
+
throw this.errorBuilder.buildError(ErrorType.INTERNAL, undefined, {
|
|
2054
|
+
context: {
|
|
2055
|
+
message: `Cannot resolve publicUrl for frontend service "${frontendServiceName}".`,
|
|
2056
|
+
frontendServiceName,
|
|
2057
|
+
},
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
return url;
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
/**
|
|
2064
|
+
* AUTH-10: Cross-validate X-Frontend-Service-Name header against the browser Origin header.
|
|
2065
|
+
*
|
|
2066
|
+
* The Origin header is browser-enforced (forbidden header per Fetch spec) and cannot
|
|
2067
|
+
* be spoofed by client-side JavaScript. If the Origin doesn't match the configured
|
|
2068
|
+
* publicUrl for the claimed frontend service, the request is rejected.
|
|
2069
|
+
*
|
|
2070
|
+
* Non-browser clients (curl, Postman, mobile SDKs) do not send the Origin header,
|
|
2071
|
+
* so this validation is skipped for them. This is acceptable because:
|
|
2072
|
+
* - Rate limiting gates all registration/identify endpoints
|
|
2073
|
+
* - Registration policy enforcement (mode, password policy) applies regardless
|
|
2074
|
+
* - The DB override in the orchestrator protects known users independently
|
|
2075
|
+
* If non-browser registration restriction is needed, use invitation tokens or API keys.
|
|
2076
|
+
*/
|
|
2077
|
+
private _validateFrontendAppOrigin(req: Request, claimedFrontendServiceName: string | undefined): void {
|
|
2078
|
+
if (!claimedFrontendServiceName) return;
|
|
2079
|
+
|
|
2080
|
+
const configuredUrl = AuthControllerUtils.lookupFrontendPublicUrl(this.appConfigService.config, claimedFrontendServiceName);
|
|
2081
|
+
if (!configuredUrl) {
|
|
2082
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHORIZATION, undefined, {
|
|
2083
|
+
customMessageReference: ErrorCustomMessageReference.AUTHORIZATION,
|
|
2084
|
+
context: {
|
|
2085
|
+
message:
|
|
2086
|
+
`Unknown or unbound frontend service identity "${claimedFrontendServiceName}". ` +
|
|
2087
|
+
`Declare it in frontendServices and materialize runtime.endPoints.${claimedFrontendServiceName}.publicUrl before using it at runtime.`,
|
|
2088
|
+
frontendServiceName: claimedFrontendServiceName,
|
|
2089
|
+
},
|
|
2090
|
+
});
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
// Origin absent → non-browser client or same-origin; skip (see JSDoc for rationale)
|
|
2094
|
+
const origin = req.headers[WildoHeaderKeys.ORIGIN] as string | undefined;
|
|
2095
|
+
if (!origin) return;
|
|
2096
|
+
|
|
2097
|
+
try {
|
|
2098
|
+
const configuredOrigin = new URL(configuredUrl).origin;
|
|
2099
|
+
if (origin !== configuredOrigin) {
|
|
2100
|
+
this.logDebug('Origin mismatch — X-Frontend-Service-Name header does not match request Origin', {
|
|
2101
|
+
claimedFrontendServiceName,
|
|
2102
|
+
requestOrigin: origin,
|
|
2103
|
+
configuredOrigin,
|
|
2104
|
+
});
|
|
2105
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHORIZATION, undefined, {
|
|
2106
|
+
customMessageReference: ErrorCustomMessageReference.AUTHORIZATION,
|
|
2107
|
+
context: { message: 'Request origin does not match the claimed frontend service identity.' },
|
|
2108
|
+
});
|
|
2109
|
+
}
|
|
2110
|
+
} catch (e) {
|
|
2111
|
+
if (isWildoBackendError(e)) throw e;
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2116
|
+
// Magic Link Route Handlers (Phase G2)
|
|
2117
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2118
|
+
|
|
2119
|
+
/**
|
|
2120
|
+
* POST /auth/magic-link/send
|
|
2121
|
+
* Body: { email: string }
|
|
2122
|
+
* Response: { message: string }
|
|
2123
|
+
*
|
|
2124
|
+
* Generates a magic link token and sends an email containing the link.
|
|
2125
|
+
* Always returns success to prevent email enumeration.
|
|
2126
|
+
*/
|
|
2127
|
+
private async magicLinkSend(req: Request, res: Response): Promise<void> {
|
|
2128
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
2129
|
+
const body = MagicLinkSendRequestSchema.parse(req.body || {});
|
|
2130
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
2131
|
+
const userAgent = req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown';
|
|
2132
|
+
|
|
2133
|
+
this.logDebug('Magic link send requested', { email: body.email });
|
|
2134
|
+
|
|
2135
|
+
// IP-based rate limit to prevent email flooding from a single source
|
|
2136
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.MAGIC_LINK_SEND_IP}${ipAddress}`, 10, 3600);
|
|
2137
|
+
|
|
2138
|
+
const result = await this.authService.sendMagicLink(ec, body, { ipAddress, userAgent });
|
|
2139
|
+
|
|
2140
|
+
if (result.token && result.email) {
|
|
2141
|
+
try {
|
|
2142
|
+
const frontendUrl = this.resolveFrontendAppPublicUrl(req);
|
|
2143
|
+
const magicLinkUrl = `${frontendUrl}/auth/magic-link/verify?token=${encodeURIComponent(result.token)}&email=${encodeURIComponent(result.email)}`;
|
|
2144
|
+
|
|
2145
|
+
const appIdentity = this.appConfigService.config.appIdentity;
|
|
2146
|
+
await this.emailService.send({
|
|
2147
|
+
templateRef: SystemEmailTemplateRef.MAGIC_LINK,
|
|
2148
|
+
locale: AvailableLanguage.EN,
|
|
2149
|
+
type: EmailTemplateType.TRANSACTIONAL,
|
|
2150
|
+
to: result.email,
|
|
2151
|
+
context: {
|
|
2152
|
+
currentObject: { email: result.email },
|
|
2153
|
+
objectContext: {
|
|
2154
|
+
primaryScopeContext: {
|
|
2155
|
+
appName: appIdentity.appName,
|
|
2156
|
+
applicationId: this.appConfigService.applicationId,
|
|
2157
|
+
},
|
|
2158
|
+
},
|
|
2159
|
+
userContext: { userId: result.userId || 'unknown', email: result.email },
|
|
2160
|
+
additionalContext: { magicLinkUrl, tokenValue: result.token, expiresInMinutes: result.expiresInMinutes },
|
|
2161
|
+
},
|
|
2162
|
+
});
|
|
2163
|
+
} catch (error) {
|
|
2164
|
+
this.logger.error('Failed to send magic link email', {
|
|
2165
|
+
email: result.email,
|
|
2166
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2167
|
+
});
|
|
2168
|
+
// Don't reveal email delivery failure (anti-enumeration)
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
this.jsonSuccess(res, this.authResponseHelper.getAuthResponse(AuthResponseMessageRef.MAGIC_LINK_SENT));
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
/**
|
|
2176
|
+
* POST /auth/magic-link/verify
|
|
2177
|
+
* Body: { token: string, email: string }
|
|
2178
|
+
* Response: AuthenticationResponse
|
|
2179
|
+
*
|
|
2180
|
+
* Validates a magic link token and returns auth tokens on success.
|
|
2181
|
+
* Email is included for defense-in-depth constant-time comparison against token metadata.
|
|
2182
|
+
* This is a standalone auth endpoint (not dispatched through authenticate()).
|
|
2183
|
+
*/
|
|
2184
|
+
private async magicLinkVerify(req: Request, res: Response): Promise<void> {
|
|
2185
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
2186
|
+
const body = MagicLinkVerifyRequestSchema.parse(req.body || {});
|
|
2187
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
2188
|
+
const userAgent = req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown';
|
|
2189
|
+
|
|
2190
|
+
// IP-based rate limit for resource protection
|
|
2191
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.MAGIC_LINK_VERIFY_IP}${ipAddress}`, 20, 60);
|
|
2192
|
+
|
|
2193
|
+
this.logDebug('Magic link verify requested');
|
|
2194
|
+
|
|
2195
|
+
const authResponse = await this.authService.verifyMagicLink(ec, body, { ipAddress, userAgent });
|
|
2196
|
+
|
|
2197
|
+
await this.handleAnonymousTransposition(req, authResponse);
|
|
2198
|
+
this.jsonSuccess(res, authResponse);
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2202
|
+
// SMS OTP Route Handlers (Phase G2)
|
|
2203
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2204
|
+
|
|
2205
|
+
/**
|
|
2206
|
+
* POST /auth/sms-otp/send
|
|
2207
|
+
* Body: { sessionId: string, phoneNumber?: string }
|
|
2208
|
+
* Response: { message: string }
|
|
2209
|
+
*
|
|
2210
|
+
* Generates an OTP code and sends it via SMS.
|
|
2211
|
+
* Requires an active auth session. Can be used for first or second factor.
|
|
2212
|
+
*/
|
|
2213
|
+
private async smsOTPSend(req: Request, res: Response): Promise<void> {
|
|
2214
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
2215
|
+
const body = z.object({
|
|
2216
|
+
sessionId: z.string().min(1),
|
|
2217
|
+
phoneNumber: z.string().regex(/^\+?[1-9]\d{1,14}$/, { error: 'Invalid phone number' }).optional(),
|
|
2218
|
+
}).parse(req.body || {});
|
|
2219
|
+
|
|
2220
|
+
this.logDebug('SMS OTP send requested', { sessionId: body.sessionId });
|
|
2221
|
+
|
|
2222
|
+
// IP-based rate limit to prevent SMS pump fraud from a single source
|
|
2223
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
2224
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.SMS_OTP_SEND_IP}${ipAddress}`, 5, 3600);
|
|
2225
|
+
|
|
2226
|
+
const result = await this.authService.sendSMSOTP(ec, body.sessionId, body.phoneNumber);
|
|
2227
|
+
|
|
2228
|
+
const appIdentity = this.appConfigService.config.appIdentity;
|
|
2229
|
+
const smsResult = await this.smsService.send(
|
|
2230
|
+
result.targetPhone,
|
|
2231
|
+
this.authResponseHelper.getSmsLabel(BackendSmsMessageRef.OTP_VERIFICATION_CODE, { appName: appIdentity.appName, code: result.otpCode }),
|
|
2232
|
+
);
|
|
2233
|
+
if (!smsResult.success) {
|
|
2234
|
+
this.logger.error('SMS OTP delivery failed', {
|
|
2235
|
+
sessionId: body.sessionId,
|
|
2236
|
+
error: smsResult.error,
|
|
2237
|
+
});
|
|
2238
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
2239
|
+
context: { message: this.authResponseHelper.getSmsLabel(BackendSmsMessageRef.VERIFICATION_SEND_FAILED) },
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
this.jsonSuccess(res, { message: this.authResponseHelper.getSmsLabel(BackendSmsMessageRef.VERIFICATION_SENT) });
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2247
|
+
// Phone Verification Route Handlers (Phase G2)
|
|
2248
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2249
|
+
|
|
2250
|
+
/**
|
|
2251
|
+
* POST /auth/phone/verify/send
|
|
2252
|
+
* Body: { phoneNumber: string, sessionId?: string }
|
|
2253
|
+
* Response: { message: string }
|
|
2254
|
+
*
|
|
2255
|
+
* Sends a verification code to prove phone number ownership.
|
|
2256
|
+
* Used during account setup, not authentication.
|
|
2257
|
+
*/
|
|
2258
|
+
private async phoneVerifySend(req: Request, res: Response): Promise<void> {
|
|
2259
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
2260
|
+
const body = PhoneVerifySendRequestSchema.parse(req.body || {});
|
|
2261
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
2262
|
+
|
|
2263
|
+
await this.authJwtGuard.extractFromSessionOrJwt(ec, req);
|
|
2264
|
+
|
|
2265
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.PHONE_VERIFY_SEND}${body.phoneNumber}`, 3, 300);
|
|
2266
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.PHONE_VERIFY_SEND_IP}${ipAddress}`, 5, 3600);
|
|
2267
|
+
|
|
2268
|
+
const { otpCode } = await this.phoneVerificationService.createVerificationCode(ec, {
|
|
2269
|
+
phoneNumber: body.phoneNumber,
|
|
2270
|
+
ipAddress,
|
|
2271
|
+
});
|
|
2272
|
+
|
|
2273
|
+
const appIdentity = this.appConfigService.config.appIdentity;
|
|
2274
|
+
const smsResult = await this.smsService.send(
|
|
2275
|
+
body.phoneNumber,
|
|
2276
|
+
this.authResponseHelper.getSmsLabel(BackendSmsMessageRef.PHONE_VERIFICATION_CODE, { appName: appIdentity.appName, code: otpCode, expiry: '10' }),
|
|
2277
|
+
);
|
|
2278
|
+
if (!smsResult.success) {
|
|
2279
|
+
this.logger.error('Phone verification SMS delivery failed', { phoneNumber: body.phoneNumber, error: smsResult.error });
|
|
2280
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
2281
|
+
context: { message: this.authResponseHelper.getSmsLabel(BackendSmsMessageRef.VERIFICATION_SEND_FAILED) },
|
|
2282
|
+
});
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
this.jsonSuccess(res, { message: this.authResponseHelper.getSmsLabel(BackendSmsMessageRef.PHONE_VERIFICATION_SENT) });
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
/**
|
|
2289
|
+
* POST /auth/phone/verify/confirm
|
|
2290
|
+
* Body: { phoneNumber: string, code: string }
|
|
2291
|
+
* Response: { verified: boolean }
|
|
2292
|
+
*
|
|
2293
|
+
* Confirms phone ownership by validating the submitted code.
|
|
2294
|
+
* On success, marks the phone as verified on the user's credentials.
|
|
2295
|
+
*/
|
|
2296
|
+
private async phoneVerifyConfirm(req: Request, res: Response): Promise<void> {
|
|
2297
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
2298
|
+
const body = PhoneVerifyConfirmRequestSchema.parse(req.body || {});
|
|
2299
|
+
|
|
2300
|
+
const { userId } = await this.authJwtGuard.extractFromSessionOrJwt(ec, req);
|
|
2301
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.PHONE_VERIFY_CONFIRM}${body.phoneNumber}`, 5, 300);
|
|
2302
|
+
|
|
2303
|
+
const result = await this.phoneVerificationService.confirmVerification(ec, {
|
|
2304
|
+
phoneNumber: body.phoneNumber,
|
|
2305
|
+
code: body.code,
|
|
2306
|
+
userId,
|
|
2307
|
+
ipAddress: AuthControllerUtils.getClientIpFromRequest(req),
|
|
2308
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
2309
|
+
});
|
|
2310
|
+
|
|
2311
|
+
this.jsonSuccess(res, result);
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
/**
|
|
2315
|
+
* POST /auth/native-token/exchange
|
|
2316
|
+
* Body: { provider: 'apple' | 'google', identityToken: string, userType?: 'user' }
|
|
2317
|
+
* Response: { accessToken, refreshToken?, expiresIn?, isNewUser }
|
|
2318
|
+
*
|
|
2319
|
+
* Exchanges a native Apple/Google SDK identity token for a Wildo JWT.
|
|
2320
|
+
* The identity token is verified against the IdP's JWKS before provisioning.
|
|
2321
|
+
*/
|
|
2322
|
+
private async nativeTokenExchange(req: Request, res: Response): Promise<void> {
|
|
2323
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
2324
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.NATIVE_EXCHANGE_IP}${ipAddress}`, 10, 60);
|
|
2325
|
+
|
|
2326
|
+
const body = NativeTokenExchangeRequestSchema.parse(req.body || {});
|
|
2327
|
+
const { provider, identityToken, nonce } = body;
|
|
2328
|
+
|
|
2329
|
+
const appConfig = this.appConfigService.config;
|
|
2330
|
+
const providerConfig = appConfig.externalProvidersConfigurations?.[provider]?.sso_oauth2 as
|
|
2331
|
+
Record<string, unknown> | undefined;
|
|
2332
|
+
const nativeClientIds = (providerConfig?.nativeClientIds as string[] | undefined) || [];
|
|
2333
|
+
|
|
2334
|
+
if (nativeClientIds.length === 0) {
|
|
2335
|
+
throw this.errorBuilder.buildError(ErrorType.CONFIGURATION, undefined, {
|
|
2336
|
+
customMessageReference: ErrorCustomMessageReference.APP_CONFIGURATION_NOT_INITIALIZED,
|
|
2337
|
+
context: { message: `Native SDK token exchange not configured for provider '${provider}'. Set nativeClientIds in externalProvidersConfigurations.` },
|
|
2338
|
+
});
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
try {
|
|
2342
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
2343
|
+
const { provisionResult, normalizedProfile } = await this.oauth2Service.exchangeNativeToken(
|
|
2344
|
+
provider,
|
|
2345
|
+
identityToken,
|
|
2346
|
+
nativeClientIds,
|
|
2347
|
+
nonce,
|
|
2348
|
+
);
|
|
2349
|
+
|
|
2350
|
+
const deviceInfo = {
|
|
2351
|
+
ipAddress,
|
|
2352
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
2353
|
+
};
|
|
2354
|
+
|
|
2355
|
+
// Resolve activeUserType hint from X-Frontend-Service-Name header.
|
|
2356
|
+
// The orchestrator overrides with the DB-stored userTypes[0] for the provisioned user.
|
|
2357
|
+
// Cross-validate Origin against the claimed frontend service (defense-in-depth).
|
|
2358
|
+
const nativeFrontendServiceName = req.headers[WildoHeaderKeys.FRONTEND_SERVICE_NAME] as string | undefined;
|
|
2359
|
+
this._validateFrontendAppOrigin(req, nativeFrontendServiceName);
|
|
2360
|
+
const nativeActiveUserType = nativeFrontendServiceName
|
|
2361
|
+
? this.appConfigService.resolveUserTypeFromFrontendServiceName(nativeFrontendServiceName) ?? undefined
|
|
2362
|
+
: undefined;
|
|
2363
|
+
|
|
2364
|
+
const result = await this.authService.handleNativeSDKFirstFactor(
|
|
2365
|
+
ec,
|
|
2366
|
+
provisionResult.userId,
|
|
2367
|
+
normalizedProfile.email,
|
|
2368
|
+
deviceInfo,
|
|
2369
|
+
nativeActiveUserType,
|
|
2370
|
+
nativeFrontendServiceName,
|
|
2371
|
+
);
|
|
2372
|
+
|
|
2373
|
+
await this.auditLogsService.logUserSSOLogin({
|
|
2374
|
+
userId: provisionResult.userId,
|
|
2375
|
+
email: normalizedProfile.email,
|
|
2376
|
+
providerRef: provider,
|
|
2377
|
+
connectionType: SsoConnectionType.SOCIAL,
|
|
2378
|
+
authSource: AuthSource.OIDC,
|
|
2379
|
+
ipAddress: deviceInfo.ipAddress,
|
|
2380
|
+
userAgent: deviceInfo.userAgent,
|
|
2381
|
+
sessionId: result.mfaRequired ? result.sessionId : `native-sdk:${provider}:${provisionResult.userId}`,
|
|
2382
|
+
});
|
|
2383
|
+
|
|
2384
|
+
if (result.mfaRequired === true) {
|
|
2385
|
+
this.jsonSuccess(res, {
|
|
2386
|
+
mfaRequired: true,
|
|
2387
|
+
sessionId: result.sessionId,
|
|
2388
|
+
enrolledMethods: result.enrolledMethods,
|
|
2389
|
+
isNewUser: provisionResult.isNewUser,
|
|
2390
|
+
});
|
|
2391
|
+
} else {
|
|
2392
|
+
await this.handleAnonymousTranspositionForTokenExchange(req, provisionResult.userId);
|
|
2393
|
+
this.jsonSuccess(res, {
|
|
2394
|
+
accessToken: result.tokens.accessToken,
|
|
2395
|
+
refreshToken: result.tokens.refreshToken,
|
|
2396
|
+
expiresIn: result.tokens.expiresIn,
|
|
2397
|
+
isNewUser: provisionResult.isNewUser,
|
|
2398
|
+
});
|
|
2399
|
+
}
|
|
2400
|
+
} catch (error) {
|
|
2401
|
+
if (isWildoBackendError(error)) throw error;
|
|
2402
|
+
|
|
2403
|
+
this.logger.warn('Native token exchange failed', {
|
|
2404
|
+
provider,
|
|
2405
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2406
|
+
ipAddress,
|
|
2407
|
+
});
|
|
2408
|
+
|
|
2409
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
2410
|
+
customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_INVALID_TOKEN,
|
|
2411
|
+
context: { message: 'Invalid or expired identity token' },
|
|
2412
|
+
});
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2417
|
+
// W7.3b: One-Off Session Token Handlers
|
|
2418
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2419
|
+
|
|
2420
|
+
private async createOneOffToken(req: Request, res: Response): Promise<void> {
|
|
2421
|
+
const preAuthEc = await this._getPreAuthExecutionContext();
|
|
2422
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
2423
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.ONE_OFF_CREATE_IP}${ipAddress}`, 30, 60);
|
|
2424
|
+
|
|
2425
|
+
const caller = await this.authJwtGuard.extractAuthenticatedUser(preAuthEc, req);
|
|
2426
|
+
const ec = await this._getAuthenticatedExecutionContext(caller.userId);
|
|
2427
|
+
const body = CreateOneOffTokenRequestSchema.parse(req.body || {});
|
|
2428
|
+
|
|
2429
|
+
const callerUser = await this.userLookup.findUserById(ec, caller.userId);
|
|
2430
|
+
const callerRoles = callerUser?.appRoles || [];
|
|
2431
|
+
const isAdmin = callerRoles.includes(CORE_APP_ROLES.APP_ADMIN_SUPER_ADMIN);
|
|
2432
|
+
if (!isAdmin) {
|
|
2433
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHORIZATION, undefined, {
|
|
2434
|
+
customMessageReference: ErrorCustomMessageReference.AUTHORIZATIONS_ACCESS_DENIED,
|
|
2435
|
+
context: { message: 'Only super-admin users can create one-off session tokens.' },
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
if (caller.userId === body.userId) {
|
|
2440
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHORIZATION, undefined, {
|
|
2441
|
+
customMessageReference: ErrorCustomMessageReference.AUTHORIZATIONS_ACCESS_DENIED,
|
|
2442
|
+
context: { message: 'Cannot create one-off token targeting self.' },
|
|
2443
|
+
});
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
const targetUser = await this.userLookup.findUserById(ec, body.userId);
|
|
2447
|
+
if (!targetUser) {
|
|
2448
|
+
throw this.errorBuilder.buildError(ErrorType.NOT_FOUND, undefined, {
|
|
2449
|
+
customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_USER_NOT_FOUND,
|
|
2450
|
+
context: { userId: body.userId },
|
|
2451
|
+
});
|
|
2452
|
+
}
|
|
2453
|
+
if (targetUser.status !== UserStatus.ACTIVE) {
|
|
2454
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHORIZATION, undefined, {
|
|
2455
|
+
customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_USER_NOT_ACTIVE,
|
|
2456
|
+
context: { userId: body.userId },
|
|
2457
|
+
});
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
const userType = targetUser.userTypes?.[0];
|
|
2461
|
+
if (!userType) {
|
|
2462
|
+
throw this.errorBuilder.buildError(ErrorType.CONFIGURATION, undefined, {
|
|
2463
|
+
customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_USER_TYPE_MISMATCH,
|
|
2464
|
+
context: { userId: body.userId, message: 'Target user has no assigned user type.' },
|
|
2465
|
+
});
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
const appConfig = this.appConfigService.config;
|
|
2469
|
+
const userTypeConfig = appConfig?.userTypes?.[userType];
|
|
2470
|
+
if (!userTypeConfig?.auth?.oneOffSessionAllowed) {
|
|
2471
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHORIZATION, undefined, {
|
|
2472
|
+
customMessageReference: ErrorCustomMessageReference.FEATURE_NOT_AVAILABLE,
|
|
2473
|
+
context: { message: `One-off sessions not allowed for user type "${userType}".` },
|
|
2474
|
+
});
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
const expiresIn = body.expiresIn;
|
|
2478
|
+
const durationMs =
|
|
2479
|
+
expiresIn.unit === 'minutes' ? expiresIn.value * 60 * 1000
|
|
2480
|
+
: expiresIn.unit === 'hours' ? expiresIn.value * 3600 * 1000
|
|
2481
|
+
: expiresIn.value * 86400 * 1000;
|
|
2482
|
+
|
|
2483
|
+
const organizationId = req.params.organizationId as string | undefined;
|
|
2484
|
+
const applicationId = req.params.applicationId as string | undefined;
|
|
2485
|
+
|
|
2486
|
+
const tokenResult = await this.consumableTokenService.createToken({
|
|
2487
|
+
tokenType: body.tokenType as string,
|
|
2488
|
+
consumptionMode: body.consumptionMode,
|
|
2489
|
+
expiresIn: { value: durationMs, unit: DurationUnit.MILLISECONDS },
|
|
2490
|
+
organizationId,
|
|
2491
|
+
userId: body.userId,
|
|
2492
|
+
resourceIdentifier: body.resourceIdentifier,
|
|
2493
|
+
relatedId: body.relatedId,
|
|
2494
|
+
metadata: { ...body.metadata, ...(applicationId ? { applicationId } : {}) },
|
|
2495
|
+
roles: (targetUser.appRoles || []).map(role => ({
|
|
2496
|
+
roles: [role],
|
|
2497
|
+
relatedPrimaryScope: ResourcePrimaryScope.APPLICATION,
|
|
2498
|
+
})),
|
|
2499
|
+
maxUses: body.maxUses,
|
|
2500
|
+
createsOneOffSession: true,
|
|
2501
|
+
consumeAt: body.consumeAt,
|
|
2502
|
+
targeting: body.targeting,
|
|
2503
|
+
});
|
|
2504
|
+
|
|
2505
|
+
try {
|
|
2506
|
+
await this.auditLogsService.logGenericEvent({
|
|
2507
|
+
userId: caller.userId,
|
|
2508
|
+
organizationId,
|
|
2509
|
+
riskLevel: ResourceOperationRiskLevel.MEDIUM,
|
|
2510
|
+
eventType: CoreAuditableEventType.ONE_OFF_TOKEN_CREATED,
|
|
2511
|
+
eventData: {
|
|
2512
|
+
tokenId: tokenResult._id,
|
|
2513
|
+
tokenType: body.tokenType,
|
|
2514
|
+
targetUserId: body.userId,
|
|
2515
|
+
consumeAt: body.consumeAt,
|
|
2516
|
+
callerUserId: caller.userId,
|
|
2517
|
+
ipAddress,
|
|
2518
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
2519
|
+
},
|
|
2520
|
+
});
|
|
2521
|
+
} catch (error) {
|
|
2522
|
+
this.logger.warn('Audit log failed for one-off token creation', { error, tokenId: tokenResult._id });
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
this.jsonSuccess(res, {
|
|
2526
|
+
tokenValue: tokenResult.token,
|
|
2527
|
+
tokenId: tokenResult._id,
|
|
2528
|
+
expiresAt: tokenResult.expiresAt,
|
|
2529
|
+
});
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
private async exchangeOneOffToken(req: Request, res: Response): Promise<void> {
|
|
2533
|
+
const ipAddress = AuthControllerUtils.getClientIpFromRequest(req);
|
|
2534
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.ONE_OFF_EXCHANGE_IP}${ipAddress}`, 10, 60);
|
|
2535
|
+
await this.rateLimitService.checkRateLimit(`${AUTH_REDIS_KEYS.ONE_OFF_EXCHANGE_HOUR_IP}${ipAddress}`, 100, 3600);
|
|
2536
|
+
|
|
2537
|
+
const body = OneOffSessionExchangeBodySchema.parse(req.body || {});
|
|
2538
|
+
|
|
2539
|
+
const consumableToken = await this.consumableTokenService.validateToken(body.token);
|
|
2540
|
+
|
|
2541
|
+
if (!consumableToken.createsOneOffSession) {
|
|
2542
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
2543
|
+
customMessageReference: ErrorCustomMessageReference.CONSUMABLE_TOKEN_TYPE_MISMATCH,
|
|
2544
|
+
context: { message: 'Token is not a one-off session token.' },
|
|
2545
|
+
});
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
if (!consumableToken.userId) {
|
|
2549
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
2550
|
+
customMessageReference: ErrorCustomMessageReference.CONSUMABLE_TOKEN_CONTEXT_MISMATCH,
|
|
2551
|
+
context: { message: 'Token has no target user.' },
|
|
2552
|
+
});
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2555
|
+
const ec = await this._getPreAuthExecutionContext();
|
|
2556
|
+
|
|
2557
|
+
const targetUser = await this.userLookup.findUserById(ec, consumableToken.userId);
|
|
2558
|
+
if (!targetUser || targetUser.status !== UserStatus.ACTIVE) {
|
|
2559
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
2560
|
+
customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_USER_NOT_ACTIVE,
|
|
2561
|
+
context: { userId: consumableToken.userId },
|
|
2562
|
+
});
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
const userType = targetUser.userTypes?.[0];
|
|
2566
|
+
if (!userType) {
|
|
2567
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
|
|
2568
|
+
customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_USER_TYPE_MISMATCH,
|
|
2569
|
+
context: { userId: consumableToken.userId },
|
|
2570
|
+
});
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
const appConfig = this.appConfigService.config;
|
|
2574
|
+
const userTypeConfig = appConfig?.userTypes?.[userType];
|
|
2575
|
+
if (!userTypeConfig?.auth?.oneOffSessionAllowed) {
|
|
2576
|
+
throw this.errorBuilder.buildError(ErrorType.AUTHORIZATION, undefined, {
|
|
2577
|
+
customMessageReference: ErrorCustomMessageReference.FEATURE_NOT_AVAILABLE,
|
|
2578
|
+
context: { message: `One-off sessions no longer allowed for user type "${userType}".` },
|
|
2579
|
+
});
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
let consumableTokenValue: string | undefined;
|
|
2583
|
+
if (consumableToken.consumeAt === 'EXCHANGE') {
|
|
2584
|
+
await this.consumableTokenService.consumeToken(body.token);
|
|
2585
|
+
} else {
|
|
2586
|
+
consumableTokenValue = body.token;
|
|
2587
|
+
}
|
|
2588
|
+
|
|
2589
|
+
const tokens = await this.tokenIssuer.issueTokensForUser(
|
|
2590
|
+
consumableToken.userId,
|
|
2591
|
+
undefined,
|
|
2592
|
+
{ sessionType: SessionType.ONE_OFF, activeUserType: userType },
|
|
2593
|
+
{
|
|
2594
|
+
skipSessionTracking: true,
|
|
2595
|
+
refreshTokenExpiresAt: consumableToken.expiresAt,
|
|
2596
|
+
},
|
|
2597
|
+
);
|
|
2598
|
+
|
|
2599
|
+
try {
|
|
2600
|
+
await this.auditLogsService.logGenericEvent({
|
|
2601
|
+
userId: consumableToken.userId,
|
|
2602
|
+
organizationId: consumableToken.organizationId,
|
|
2603
|
+
riskLevel: ResourceOperationRiskLevel.MEDIUM,
|
|
2604
|
+
eventType: CoreAuditableEventType.ONE_OFF_TOKEN_EXCHANGED,
|
|
2605
|
+
eventData: {
|
|
2606
|
+
tokenId: consumableToken._id,
|
|
2607
|
+
tokenType: consumableToken.tokenType,
|
|
2608
|
+
consumeAt: consumableToken.consumeAt,
|
|
2609
|
+
consumed: consumableToken.consumeAt === 'EXCHANGE',
|
|
2610
|
+
ipAddress,
|
|
2611
|
+
userAgent: req.headers[WildoHeaderKeys.USER_AGENT] || 'unknown',
|
|
2612
|
+
},
|
|
2613
|
+
});
|
|
2614
|
+
} catch (error) {
|
|
2615
|
+
this.logger.warn('Audit log failed for one-off token exchange', { error, tokenId: consumableToken._id });
|
|
2616
|
+
}
|
|
2617
|
+
|
|
2618
|
+
this.jsonSuccess(res, {
|
|
2619
|
+
accessToken: tokens.accessToken,
|
|
2620
|
+
refreshToken: tokens.refreshToken,
|
|
2621
|
+
sessionType: SessionType.ONE_OFF,
|
|
2622
|
+
...(consumableTokenValue ? {
|
|
2623
|
+
consumableTokenValue,
|
|
2624
|
+
tokenExpiresAt: consumableToken.expiresAt.toISOString(),
|
|
2625
|
+
} : {}),
|
|
2626
|
+
context: {
|
|
2627
|
+
tokenId: consumableToken._id,
|
|
2628
|
+
tokenType: consumableToken.tokenType,
|
|
2629
|
+
targeting: consumableToken.targeting,
|
|
2630
|
+
organizationId: consumableToken.organizationId,
|
|
2631
|
+
applicationId: (consumableToken.metadata as Record<string, unknown> | undefined)?.applicationId as string | undefined,
|
|
2632
|
+
userId: consumableToken.userId,
|
|
2633
|
+
},
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2636
|
+
|
|
2637
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2638
|
+
// W7.3a: Anonymous Session Transposition on Login/Register
|
|
2639
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2640
|
+
|
|
2641
|
+
/**
|
|
2642
|
+
* Called after a successful authentication. If the request carries an
|
|
2643
|
+
* anonymous session token, verifies it and transposes ownership of
|
|
2644
|
+
* anonymous resources to the newly authenticated user.
|
|
2645
|
+
*
|
|
2646
|
+
* Errors are swallowed to avoid blocking the auth response.
|
|
2647
|
+
*/
|
|
2648
|
+
private async handleAnonymousTransposition(req: Request, authResult: AuthenticationResponse): Promise<void> {
|
|
2649
|
+
if (!authResult.success || !authResult.user?._id) return;
|
|
2650
|
+
|
|
2651
|
+
const anonymousToken = req.headers[WildoHeaderKeys.ANONYMOUS_SESSION] as string | undefined;
|
|
2652
|
+
if (!anonymousToken) return;
|
|
2653
|
+
|
|
2654
|
+
try {
|
|
2655
|
+
const { anonymousUserId } = this.anonymousSessionService.verifySessionToken(anonymousToken);
|
|
2656
|
+
const userType = this.resolveUserTypeFromRequest(req)
|
|
2657
|
+
?? authResult.user.userTypes?.[0]
|
|
2658
|
+
?? 'default';
|
|
2659
|
+
|
|
2660
|
+
const result = await this.anonymousSessionService.transposeOwnership(
|
|
2661
|
+
anonymousUserId,
|
|
2662
|
+
authResult.user._id,
|
|
2663
|
+
userType,
|
|
2664
|
+
);
|
|
2665
|
+
|
|
2666
|
+
this.logDebug('Anonymous session transposition completed', {
|
|
2667
|
+
anonymousUserId,
|
|
2668
|
+
userId: authResult.user._id,
|
|
2669
|
+
userType,
|
|
2670
|
+
status: result.status,
|
|
2671
|
+
transposedTypes: result.transposedTypes,
|
|
2672
|
+
failedCount: result.failedTypes.length,
|
|
2673
|
+
});
|
|
2674
|
+
} catch (error) {
|
|
2675
|
+
this.logger.warn('Anonymous session transposition failed (non-blocking)', {
|
|
2676
|
+
userId: authResult.user._id,
|
|
2677
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2678
|
+
});
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
/**
|
|
2683
|
+
* Simplified transposition for OAuth2 token exchange, where we have a userId
|
|
2684
|
+
* but no AuthenticationResponse. Uses header-resolved userType.
|
|
2685
|
+
*/
|
|
2686
|
+
private async handleAnonymousTranspositionForTokenExchange(req: Request, userId: string): Promise<void> {
|
|
2687
|
+
const anonymousToken = req.headers[WildoHeaderKeys.ANONYMOUS_SESSION] as string | undefined;
|
|
2688
|
+
if (!anonymousToken) return;
|
|
2689
|
+
|
|
2690
|
+
try {
|
|
2691
|
+
const { anonymousUserId } = this.anonymousSessionService.verifySessionToken(anonymousToken);
|
|
2692
|
+
const userType = this.resolveUserTypeFromRequest(req) ?? 'default';
|
|
2693
|
+
|
|
2694
|
+
const result = await this.anonymousSessionService.transposeOwnership(anonymousUserId, userId, userType);
|
|
2695
|
+
|
|
2696
|
+
this.logDebug('Anonymous session transposition completed (token exchange)', {
|
|
2697
|
+
anonymousUserId, userId, userType, status: result.status,
|
|
2698
|
+
transposedTypes: result.transposedTypes, failedCount: result.failedTypes.length,
|
|
2699
|
+
});
|
|
2700
|
+
} catch (error) {
|
|
2701
|
+
this.logger.warn('Anonymous session transposition failed in token exchange (non-blocking)', {
|
|
2702
|
+
userId, error: error instanceof Error ? error.message : String(error),
|
|
2703
|
+
});
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
|
|
2707
|
+
private resolveUserTypeFromRequest(req: Request): string | undefined {
|
|
2708
|
+
const frontendServiceName = req.headers[WildoHeaderKeys.FRONTEND_SERVICE_NAME] as string | undefined;
|
|
2709
|
+
if (!frontendServiceName) return undefined;
|
|
2710
|
+
return this.appConfigService.resolveUserTypeFromFrontendServiceName(frontendServiceName) ?? undefined;
|
|
2711
|
+
}
|
|
2712
|
+
}
|