@wildo-ai/saas-backend-lib 1.1.2 → 1.1.3
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/applications/services/worker-remote-client-factory.backend.service.d.ts.map +1 -1
- package/dist/esm/applications/services/worker-remote-client-factory.backend.service.js +19 -1
- package/dist/esm/applications/services/worker-remote-client-factory.backend.service.js.map +1 -1
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.d.ts.map +1 -1
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.js +4 -0
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.js.map +1 -1
- package/dist/esm/base-classes/services/batches/child-lifecycle-teardown.batch.backend.service.d.ts +35 -0
- package/dist/esm/base-classes/services/batches/child-lifecycle-teardown.batch.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/batches/child-lifecycle-teardown.batch.backend.service.js +111 -0
- package/dist/esm/base-classes/services/batches/child-lifecycle-teardown.batch.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.d.ts +50 -0
- package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.d.ts.map +1 -0
- package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.js +199 -0
- package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.js.map +1 -0
- package/dist/esm/base-classes/services/batches/engine-custom-batch-manifests.d.ts +111 -0
- package/dist/esm/base-classes/services/batches/engine-custom-batch-manifests.d.ts.map +1 -1
- package/dist/esm/base-classes/services/batches/engine-custom-batch-manifests.js +140 -0
- package/dist/esm/base-classes/services/batches/engine-custom-batch-manifests.js.map +1 -1
- package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.js +27 -6
- package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.d.ts +124 -13
- package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.js +207 -21
- package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.d.ts +60 -8
- package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.js +174 -26
- package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.d.ts +47 -4
- package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.js +96 -29
- package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.d.ts +55 -0
- package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.d.ts.map +1 -0
- package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.js +114 -0
- package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.js.map +1 -0
- package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.d.ts +89 -14
- package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.js +84 -11
- package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/infrastructure-tier-contract.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/infrastructure-tier-contract.backend.js +9 -1
- package/dist/esm/base-classes/services/repositories/infrastructure-tier-contract.backend.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.d.ts +49 -0
- package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.js +171 -18
- package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.js +23 -3
- package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.js +20 -0
- package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.d.ts +22 -0
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js +4 -1
- package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.d.ts +11 -0
- package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.js +39 -5
- package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.js.map +1 -1
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts +181 -2
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js +529 -41
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/services/system-access.backend.service.d.ts +36 -3
- package/dist/esm/base-classes/services/services/system-access.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/system-access.backend.service.js +70 -8
- package/dist/esm/base-classes/services/services/system-access.backend.service.js.map +1 -1
- package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.d.ts +28 -0
- package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.js +90 -0
- package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.js.map +1 -0
- package/dist/esm/billing/batches/usage-flush.batch.backend.service.d.ts +44 -0
- package/dist/esm/billing/batches/usage-flush.batch.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/batches/usage-flush.batch.backend.service.js +99 -0
- package/dist/esm/billing/batches/usage-flush.batch.backend.service.js.map +1 -0
- package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.d.ts +91 -0
- package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.d.ts.map +1 -0
- package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.js +152 -0
- package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.js.map +1 -0
- package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.d.ts +186 -0
- package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.d.ts.map +1 -0
- package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.js +474 -0
- package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.js.map +1 -0
- package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.d.ts +100 -0
- package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.js +209 -6
- package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.js.map +1 -1
- package/dist/esm/billing/services/back-office/usage-metering.backend.service.d.ts +200 -4
- package/dist/esm/billing/services/back-office/usage-metering.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/back-office/usage-metering.backend.service.js +593 -64
- package/dist/esm/billing/services/back-office/usage-metering.backend.service.js.map +1 -1
- package/dist/esm/billing/services/billing-adapter-registry.backend.d.ts +36 -0
- package/dist/esm/billing/services/billing-adapter-registry.backend.d.ts.map +1 -0
- package/dist/esm/billing/services/billing-adapter-registry.backend.js +83 -0
- package/dist/esm/billing/services/billing-adapter-registry.backend.js.map +1 -0
- package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.d.ts +9 -0
- package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.d.ts.map +1 -1
- package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.js +11 -1
- package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.js.map +1 -1
- package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.js +48 -7
- package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.d.ts +38 -1
- package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.d.ts.map +1 -1
- package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.js +67 -2
- package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.js.map +1 -1
- package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.d.ts +30 -1
- package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.d.ts.map +1 -1
- package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.js +43 -1
- package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.js.map +1 -1
- package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.d.ts +11 -3
- package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.js +30 -16
- package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.js +104 -25
- package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.d.ts +18 -1
- package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.js +106 -2
- package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.js.map +1 -1
- package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.d.ts +52 -0
- package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.d.ts.map +1 -0
- package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js +74 -0
- package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js.map +1 -0
- package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.d.ts +104 -11
- package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.js +260 -26
- package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.js.map +1 -1
- package/dist/esm/billing/testing/mock-billing-provider.d.ts +30 -1
- package/dist/esm/billing/testing/mock-billing-provider.d.ts.map +1 -1
- package/dist/esm/billing/testing/mock-billing-provider.js +25 -0
- package/dist/esm/billing/testing/mock-billing-provider.js.map +1 -1
- package/dist/esm/compliance/audit-trails/batches/audit-logs-archive.batch.backend.service.js +11 -4
- package/dist/esm/compliance/audit-trails/batches/audit-logs-archive.batch.backend.service.js.map +1 -1
- package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.d.ts +225 -13
- package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.js +340 -62
- package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.js.map +1 -1
- package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.d.ts +244 -7
- package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.js +386 -5
- package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.js.map +1 -1
- package/dist/esm/compliance/audit-trails/services/composite-audit-log-sink.backend.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/composite-audit-log-sink.backend.js +7 -1
- package/dist/esm/compliance/audit-trails/services/composite-audit-log-sink.backend.js.map +1 -1
- package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.d.ts +6 -2
- package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.js +31 -9
- package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.d.ts +42 -0
- package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.js +57 -1
- package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.js.map +1 -1
- package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.d.ts +110 -0
- package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.d.ts.map +1 -0
- package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.js +192 -0
- package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.js.map +1 -0
- package/dist/esm/compliance/audit-trails/services/utils/ocsf-activity-mapping.backend.utils.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/utils/ocsf-activity-mapping.backend.utils.js +31 -0
- package/dist/esm/compliance/audit-trails/services/utils/ocsf-activity-mapping.backend.utils.js.map +1 -1
- package/dist/esm/config/bootstrap/application-runtime-profile.backend.d.ts +5 -0
- package/dist/esm/config/bootstrap/application-runtime-profile.backend.d.ts.map +1 -1
- package/dist/esm/config/bootstrap/application-runtime-profile.backend.js +6 -0
- package/dist/esm/config/bootstrap/application-runtime-profile.backend.js.map +1 -1
- package/dist/esm/config/models/app-config.backend.schemas.d.ts +142 -46
- package/dist/esm/config/models/app-config.backend.schemas.d.ts.map +1 -1
- package/dist/esm/config/models/app-config.backend.schemas.js +121 -12
- package/dist/esm/config/models/app-config.backend.schemas.js.map +1 -1
- package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.d.ts +38 -15
- package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.d.ts.map +1 -1
- package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.js +17 -2
- package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.js.map +1 -1
- package/dist/esm/config/services/app-configuration-loader.backend.service.d.ts +0 -1
- package/dist/esm/config/services/app-configuration-loader.backend.service.d.ts.map +1 -1
- package/dist/esm/config/services/app-configuration-loader.backend.service.js +68 -76
- package/dist/esm/config/services/app-configuration-loader.backend.service.js.map +1 -1
- package/dist/esm/config/services/app-configuration.backend.service.d.ts.map +1 -1
- package/dist/esm/config/services/app-configuration.backend.service.js +23 -1
- package/dist/esm/config/services/app-configuration.backend.service.js.map +1 -1
- package/dist/esm/config/services/app-configuration.backend.utils.d.ts +33 -0
- package/dist/esm/config/services/app-configuration.backend.utils.d.ts.map +1 -1
- package/dist/esm/config/services/app-configuration.backend.utils.js +39 -1
- package/dist/esm/config/services/app-configuration.backend.utils.js.map +1 -1
- package/dist/esm/config/services/application-startup-config-validator.backend.service.d.ts +25 -0
- package/dist/esm/config/services/application-startup-config-validator.backend.service.d.ts.map +1 -1
- package/dist/esm/config/services/application-startup-config-validator.backend.service.js +41 -1
- package/dist/esm/config/services/application-startup-config-validator.backend.service.js.map +1 -1
- package/dist/esm/databases/services/postgresql-schema-plan-diff.backend.d.ts.map +1 -1
- package/dist/esm/databases/services/postgresql-schema-plan-diff.backend.js +48 -0
- package/dist/esm/databases/services/postgresql-schema-plan-diff.backend.js.map +1 -1
- package/dist/esm/errors/services/error-builder.backend.service.d.ts +13 -1
- package/dist/esm/errors/services/error-builder.backend.service.d.ts.map +1 -1
- package/dist/esm/errors/services/error-builder.backend.service.js +13 -1
- package/dist/esm/errors/services/error-builder.backend.service.js.map +1 -1
- package/dist/esm/errors/services/error-handler.backend.service.d.ts +70 -7
- package/dist/esm/errors/services/error-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/errors/services/error-handler.backend.service.js +129 -8
- package/dist/esm/errors/services/error-handler.backend.service.js.map +1 -1
- package/dist/esm/errors/services/rate-limit.backend.service.d.ts +66 -0
- package/dist/esm/errors/services/rate-limit.backend.service.d.ts.map +1 -1
- package/dist/esm/errors/services/rate-limit.backend.service.js +102 -25
- package/dist/esm/errors/services/rate-limit.backend.service.js.map +1 -1
- package/dist/esm/errors/utils/error-log-level-classification.backend.utils.d.ts +5 -0
- package/dist/esm/errors/utils/error-log-level-classification.backend.utils.d.ts.map +1 -1
- package/dist/esm/errors/utils/error-log-level-classification.backend.utils.js +25 -0
- package/dist/esm/errors/utils/error-log-level-classification.backend.utils.js.map +1 -1
- package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.d.ts +33 -0
- package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.d.ts.map +1 -1
- package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.js +40 -0
- package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.js.map +1 -1
- package/dist/esm/external-data/external-data-pipeline-run.backend.service.d.ts +59 -2
- package/dist/esm/external-data/external-data-pipeline-run.backend.service.d.ts.map +1 -1
- package/dist/esm/external-data/external-data-pipeline-run.backend.service.js +52 -17
- package/dist/esm/external-data/external-data-pipeline-run.backend.service.js.map +1 -1
- package/dist/esm/external-providers/models/provider-selection-resolution-evidence.backend.definitions.d.ts +4 -2
- package/dist/esm/external-providers/models/provider-selection-resolution-evidence.backend.definitions.d.ts.map +1 -1
- package/dist/esm/external-providers/models/provider-selection-resolution-evidence.backend.definitions.js.map +1 -1
- package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.d.ts +256 -0
- package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.d.ts.map +1 -0
- package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.js +333 -0
- package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.js.map +1 -0
- package/dist/esm/external-providers/operations/provider-operation-request.backend.d.ts +56 -0
- package/dist/esm/external-providers/operations/provider-operation-request.backend.d.ts.map +1 -0
- package/dist/esm/external-providers/operations/provider-operation-request.backend.js +211 -0
- package/dist/esm/external-providers/operations/provider-operation-request.backend.js.map +1 -0
- package/dist/esm/external-providers/operations/provider-request-signing.backend.d.ts +45 -0
- package/dist/esm/external-providers/operations/provider-request-signing.backend.d.ts.map +1 -0
- package/dist/esm/external-providers/operations/provider-request-signing.backend.js +216 -0
- package/dist/esm/external-providers/operations/provider-request-signing.backend.js.map +1 -0
- package/dist/esm/external-providers/operations/provider-rest-call-client.backend.d.ts +56 -0
- package/dist/esm/external-providers/operations/provider-rest-call-client.backend.d.ts.map +1 -0
- package/dist/esm/external-providers/operations/provider-rest-call-client.backend.js +78 -0
- package/dist/esm/external-providers/operations/provider-rest-call-client.backend.js.map +1 -0
- package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.d.ts +1 -1
- package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.js +2 -2
- package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.js.map +1 -1
- package/dist/esm/external-providers/services/backend-provider-loader.backend.service.d.ts +89 -0
- package/dist/esm/external-providers/services/backend-provider-loader.backend.service.d.ts.map +1 -0
- package/dist/esm/external-providers/services/backend-provider-loader.backend.service.js +164 -0
- package/dist/esm/external-providers/services/backend-provider-loader.backend.service.js.map +1 -0
- package/dist/esm/external-providers/services/backend-provider-registry.backend.service.d.ts +26 -27
- package/dist/esm/external-providers/services/backend-provider-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/backend-provider-registry.backend.service.js +50 -64
- package/dist/esm/external-providers/services/backend-provider-registry.backend.service.js.map +1 -1
- package/dist/esm/external-providers/services/document-extraction.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/document-extraction.backend.service.js +3 -3
- package/dist/esm/external-providers/services/document-extraction.backend.service.js.map +1 -1
- package/dist/esm/external-providers/services/embeddings.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/embeddings.backend.service.js +4 -4
- package/dist/esm/external-providers/services/embeddings.backend.service.js.map +1 -1
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +292 -7
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +533 -45
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
- package/dist/esm/external-providers/services/frontend-bootstrap.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/frontend-bootstrap.backend.service.js +25 -2
- package/dist/esm/external-providers/services/frontend-bootstrap.backend.service.js.map +1 -1
- package/dist/esm/files/controllers/file.controller.d.ts.map +1 -1
- package/dist/esm/files/controllers/file.controller.js +21 -13
- package/dist/esm/files/controllers/file.controller.js.map +1 -1
- package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.js +39 -15
- package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.js.map +1 -1
- package/dist/esm/files/services/file-scanning.backend.service.d.ts +94 -9
- package/dist/esm/files/services/file-scanning.backend.service.d.ts.map +1 -1
- package/dist/esm/files/services/file-scanning.backend.service.js +197 -17
- package/dist/esm/files/services/file-scanning.backend.service.js.map +1 -1
- package/dist/esm/files/services/file-text-extraction.backend.service.d.ts +60 -1
- package/dist/esm/files/services/file-text-extraction.backend.service.d.ts.map +1 -1
- package/dist/esm/files/services/file-text-extraction.backend.service.js +167 -8
- package/dist/esm/files/services/file-text-extraction.backend.service.js.map +1 -1
- package/dist/esm/files/services/file-upload-grant.backend.service.d.ts +53 -2
- package/dist/esm/files/services/file-upload-grant.backend.service.d.ts.map +1 -1
- package/dist/esm/files/services/file-upload-grant.backend.service.js +127 -3
- package/dist/esm/files/services/file-upload-grant.backend.service.js.map +1 -1
- package/dist/esm/files/services/files.backend.service.d.ts +68 -0
- package/dist/esm/files/services/files.backend.service.d.ts.map +1 -1
- package/dist/esm/files/services/files.backend.service.js +175 -5
- package/dist/esm/files/services/files.backend.service.js.map +1 -1
- package/dist/esm/files/storage/application-storage-key.backend.utils.d.ts +109 -0
- package/dist/esm/files/storage/application-storage-key.backend.utils.d.ts.map +1 -0
- package/dist/esm/files/storage/application-storage-key.backend.utils.js +123 -0
- package/dist/esm/files/storage/application-storage-key.backend.utils.js.map +1 -0
- package/dist/esm/files/storage/file-storage-provider.types.d.ts +16 -10
- package/dist/esm/files/storage/file-storage-provider.types.d.ts.map +1 -1
- package/dist/esm/files/storage/file-storage-provider.types.js.map +1 -1
- package/dist/esm/files/storage/local-directory-storage-provider.backend.service.d.ts +67 -8
- package/dist/esm/files/storage/local-directory-storage-provider.backend.service.d.ts.map +1 -1
- package/dist/esm/files/storage/local-directory-storage-provider.backend.service.js +101 -28
- package/dist/esm/files/storage/local-directory-storage-provider.backend.service.js.map +1 -1
- package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.d.ts.map +1 -1
- package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.js +8 -55
- package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.js.map +1 -1
- package/dist/esm/files/utils/file-field-schema-path.backend.utils.d.ts.map +1 -1
- package/dist/esm/files/utils/file-field-schema-path.backend.utils.js +20 -0
- package/dist/esm/files/utils/file-field-schema-path.backend.utils.js.map +1 -1
- package/dist/esm/files/utils/office-document-text-extraction.backend.utils.d.ts +86 -0
- package/dist/esm/files/utils/office-document-text-extraction.backend.utils.d.ts.map +1 -0
- package/dist/esm/files/utils/office-document-text-extraction.backend.utils.js +288 -0
- package/dist/esm/files/utils/office-document-text-extraction.backend.utils.js.map +1 -0
- package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.d.ts +15 -0
- package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.js +76 -5
- package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/a2a/controllers/a2a.controller.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a/controllers/a2a.controller.js +6 -1
- package/dist/esm/flows-actors/a2a/controllers/a2a.controller.js.map +1 -1
- package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.d.ts +60 -0
- package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.js +63 -0
- package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.js.map +1 -1
- package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.d.ts +74 -0
- package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.js +196 -40
- package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.d.ts +7 -1
- package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.js +53 -1
- package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.d.ts +18 -0
- package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.js +18 -0
- package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/a2a/services/a2a.backend.service.d.ts +12 -7
- package/dist/esm/flows-actors/a2a/services/a2a.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a/services/a2a.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.d.ts +0 -13
- package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.d.ts.map +1 -1
- package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.js +14 -22
- package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.js.map +1 -1
- package/dist/esm/flows-actors/models/core-facets.backend.definitions.d.ts +8 -3
- package/dist/esm/flows-actors/models/core-facets.backend.definitions.d.ts.map +1 -1
- package/dist/esm/flows-actors/models/core-facets.backend.definitions.js +25 -15
- package/dist/esm/flows-actors/models/core-facets.backend.definitions.js.map +1 -1
- package/dist/esm/flows-actors/models/flows-actors.backend.schemas.d.ts +13 -1
- package/dist/esm/flows-actors/models/flows-actors.backend.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/models/flows-actors.backend.schemas.js.map +1 -1
- package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts +88 -8
- package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts.map +1 -1
- package/dist/esm/flows-actors/models/function-tools.backend.definitions.js +333 -31
- package/dist/esm/flows-actors/models/function-tools.backend.definitions.js.map +1 -1
- package/dist/esm/flows-actors/models/market-generation.actors-system.backend.definitions.d.ts.map +1 -1
- package/dist/esm/flows-actors/models/market-generation.actors-system.backend.definitions.js +4 -2
- package/dist/esm/flows-actors/models/market-generation.actors-system.backend.definitions.js.map +1 -1
- package/dist/esm/flows-actors/models/mcp-client.backend.definitions.d.ts +113 -0
- package/dist/esm/flows-actors/models/mcp-client.backend.definitions.d.ts.map +1 -0
- package/dist/esm/flows-actors/models/mcp-client.backend.definitions.js +62 -0
- package/dist/esm/flows-actors/models/mcp-client.backend.definitions.js.map +1 -0
- package/dist/esm/flows-actors/services/actors-system.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/actors-system.backend.service.js +0 -2
- package/dist/esm/flows-actors/services/actors-system.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/agents.backend.service.d.ts +28 -1
- package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/agents.backend.service.js +204 -18
- package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts +5 -1
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.js +79 -16
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts +34 -5
- package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/flows-actors-registry.service.js +154 -20
- package/dist/esm/flows-actors/services/flows-actors-registry.service.js.map +1 -1
- package/dist/esm/flows-actors/services/flows.backend.services.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/flows.backend.services.js +27 -23
- package/dist/esm/flows-actors/services/flows.backend.services.js.map +1 -1
- package/dist/esm/flows-actors/services/llm-observability-agent-call-trace-sink.backend.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/llm-observability-agent-call-trace-sink.backend.js +7 -1
- package/dist/esm/flows-actors/services/llm-observability-agent-call-trace-sink.backend.js.map +1 -1
- package/dist/esm/flows-actors/services/mcp-client.backend.service.d.ts +90 -0
- package/dist/esm/flows-actors/services/mcp-client.backend.service.d.ts.map +1 -0
- package/dist/esm/flows-actors/services/mcp-client.backend.service.js +368 -0
- package/dist/esm/flows-actors/services/mcp-client.backend.service.js.map +1 -0
- package/dist/esm/flows-actors/services/prompt-compiler.backend.service.d.ts +9 -5
- package/dist/esm/flows-actors/services/prompt-compiler.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/prompt-compiler.backend.service.js +12 -17
- package/dist/esm/flows-actors/services/prompt-compiler.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts.map +1 -1
- package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js +8 -4
- package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
- package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.d.ts +0 -207
- package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.d.ts.map +1 -1
- package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.js +8 -243
- package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.js.map +1 -1
- package/dist/esm/flows-actors/utils/meta-workflow-structured-generation-plan.backend.utils.d.ts.map +1 -1
- package/dist/esm/flows-actors/utils/meta-workflow-structured-generation-plan.backend.utils.js.map +1 -1
- package/dist/esm/guidance/services/milestone-evaluator.backend.service.d.ts +9 -14
- package/dist/esm/guidance/services/milestone-evaluator.backend.service.d.ts.map +1 -1
- package/dist/esm/guidance/services/milestone-evaluator.backend.service.js +18 -89
- package/dist/esm/guidance/services/milestone-evaluator.backend.service.js.map +1 -1
- package/dist/esm/guidance/services/progression-state-store.backend.service.d.ts +86 -0
- package/dist/esm/guidance/services/progression-state-store.backend.service.d.ts.map +1 -0
- package/dist/esm/guidance/services/progression-state-store.backend.service.js +155 -0
- package/dist/esm/guidance/services/progression-state-store.backend.service.js.map +1 -0
- package/dist/esm/i18n/controllers/i18n-controller.backend.service.d.ts +10 -0
- package/dist/esm/i18n/controllers/i18n-controller.backend.service.d.ts.map +1 -1
- package/dist/esm/i18n/controllers/i18n-controller.backend.service.js +55 -5
- package/dist/esm/i18n/controllers/i18n-controller.backend.service.js.map +1 -1
- package/dist/esm/index.d.ts +11 -4
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +31 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/inject/models/container.d.ts.map +1 -1
- package/dist/esm/inject/models/container.js +78 -10
- package/dist/esm/inject/models/container.js.map +1 -1
- package/dist/esm/inject/models/service-types.d.ts +17 -3
- package/dist/esm/inject/models/service-types.d.ts.map +1 -1
- package/dist/esm/inject/models/service-types.js +19 -3
- package/dist/esm/inject/models/service-types.js.map +1 -1
- package/dist/esm/mcp/controllers/mcp.controller.d.ts.map +1 -1
- package/dist/esm/mcp/controllers/mcp.controller.js +20 -0
- package/dist/esm/mcp/controllers/mcp.controller.js.map +1 -1
- package/dist/esm/mcp/services/mcp-server.backend.service.d.ts +56 -1
- package/dist/esm/mcp/services/mcp-server.backend.service.d.ts.map +1 -1
- package/dist/esm/mcp/services/mcp-server.backend.service.js +107 -11
- package/dist/esm/mcp/services/mcp-server.backend.service.js.map +1 -1
- package/dist/esm/mcp/services/mcp-tool-adapter.backend.service.d.ts.map +1 -1
- package/dist/esm/mcp/services/mcp-tool-adapter.backend.service.js +22 -0
- package/dist/esm/mcp/services/mcp-tool-adapter.backend.service.js.map +1 -1
- package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.d.ts.map +1 -1
- package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.js +49 -4
- package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.js.map +1 -1
- package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.d.ts +66 -0
- package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.d.ts.map +1 -0
- package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.js +199 -0
- package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.js.map +1 -0
- package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.d.ts +149 -13
- package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.d.ts.map +1 -1
- package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.js +411 -19
- package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.js.map +1 -1
- package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.d.ts +11 -2
- package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.js.map +1 -1
- package/dist/esm/monitoring/logger/models/logger.backend.schemas.d.ts +28 -9
- package/dist/esm/monitoring/logger/models/logger.backend.schemas.d.ts.map +1 -1
- package/dist/esm/monitoring/logger/models/logger.backend.schemas.js +30 -10
- package/dist/esm/monitoring/logger/models/logger.backend.schemas.js.map +1 -1
- package/dist/esm/monitoring/logger/services/logger.service.d.ts +12 -0
- package/dist/esm/monitoring/logger/services/logger.service.d.ts.map +1 -1
- package/dist/esm/monitoring/logger/services/logger.service.js +52 -11
- package/dist/esm/monitoring/logger/services/logger.service.js.map +1 -1
- package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.d.ts +62 -0
- package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.d.ts.map +1 -0
- package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.js +78 -0
- package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.js.map +1 -0
- package/dist/esm/monitoring/observability/audit-observation-emission.backend.d.ts +309 -0
- package/dist/esm/monitoring/observability/audit-observation-emission.backend.d.ts.map +1 -0
- package/dist/esm/monitoring/observability/audit-observation-emission.backend.js +385 -0
- package/dist/esm/monitoring/observability/audit-observation-emission.backend.js.map +1 -0
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts +1 -0
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.js.map +1 -1
- package/dist/esm/monitoring/observability/services/metrics.service.d.ts +21 -0
- package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/services/metrics.service.js +38 -0
- package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -1
- package/dist/esm/notifications/email/models/email-context-provider.interface.d.ts +0 -80
- package/dist/esm/notifications/email/models/email-context-provider.interface.d.ts.map +0 -1
- package/dist/esm/notifications/email/models/email-context-provider.interface.js +0 -25
- package/dist/esm/notifications/email/models/email-context-provider.interface.js.map +0 -1
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.d.ts +0 -49
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.d.ts.map +0 -1
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.js +0 -141
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.js.map +0 -1
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.d.ts +0 -37
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.d.ts.map +0 -1
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.js +0 -121
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.js.map +0 -1
- package/dist/esm/notifications/email/services/email-template-registry.backend.service.d.ts +66 -1
- package/dist/esm/notifications/email/services/email-template-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/email/services/email-template-registry.backend.service.js +105 -10
- package/dist/esm/notifications/email/services/email-template-registry.backend.service.js.map +1 -1
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.d.ts +0 -58
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.d.ts.map +0 -1
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.js +0 -223
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.js.map +0 -1
- package/dist/esm/notifications/email/services/email-template-validator.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/email/services/email-template-validator.backend.service.js +10 -1
- package/dist/esm/notifications/email/services/email-template-validator.backend.service.js.map +1 -1
- package/dist/esm/notifications/email/services/email.backend.service.d.ts +60 -4
- package/dist/esm/notifications/email/services/email.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/email/services/email.backend.service.js +145 -43
- package/dist/esm/notifications/email/services/email.backend.service.js.map +1 -1
- package/dist/esm/notifications/email/utils/color-conversion.utils.d.ts +0 -1
- package/dist/esm/notifications/email/utils/color-conversion.utils.d.ts.map +1 -1
- package/dist/esm/notifications/email/utils/color-conversion.utils.js.map +1 -1
- package/dist/esm/notifications/services/notification-badge.backend.service.d.ts +142 -21
- package/dist/esm/notifications/services/notification-badge.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/services/notification-badge.backend.service.js +283 -58
- package/dist/esm/notifications/services/notification-badge.backend.service.js.map +1 -1
- package/dist/esm/notifications/services/notifications-dispatcher.backend.service.d.ts +99 -13
- package/dist/esm/notifications/services/notifications-dispatcher.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/services/notifications-dispatcher.backend.service.js +422 -66
- package/dist/esm/notifications/services/notifications-dispatcher.backend.service.js.map +1 -1
- package/dist/esm/notifications/sms/services/sms.backend.service.d.ts +2 -2
- package/dist/esm/notifications/sms/services/sms.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/sms/services/sms.backend.service.js +5 -5
- package/dist/esm/notifications/sms/services/sms.backend.service.js.map +1 -1
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts +117 -5
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js +164 -6
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.d.ts +0 -6
- package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.js +46 -1
- package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.js.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.js +16 -6
- package/dist/esm/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.js.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.js +12 -12
- package/dist/esm/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.d.ts +16 -0
- package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.js +18 -0
- package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.js.map +1 -1
- package/dist/esm/organizations/batches/organization-purge.batch.backend.service.d.ts +2 -2
- package/dist/esm/organizations/batches/organization-purge.batch.backend.service.js +2 -2
- package/dist/esm/organizations/batches/organization-purge.batch.backend.service.js.map +1 -1
- package/dist/esm/organizations/services/organization-custom-implementation.backend.service.d.ts.map +1 -1
- package/dist/esm/organizations/services/organization-custom-implementation.backend.service.js +63 -2
- package/dist/esm/organizations/services/organization-custom-implementation.backend.service.js.map +1 -1
- package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.d.ts +66 -0
- package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.d.ts.map +1 -0
- package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.js +257 -0
- package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.js.map +1 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.binding.d.ts +12 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.binding.d.ts.map +1 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.binding.js +47 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.binding.js.map +1 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.interface.d.ts +87 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.interface.d.ts.map +1 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.interface.js +1 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.interface.js.map +1 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.options.d.ts +31 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.options.d.ts.map +1 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.options.js +13 -0
- package/dist/esm/queue/adapters/queue-adapter.backend.options.js.map +1 -0
- package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.d.ts +19 -25
- package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.js +33 -0
- package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.js.map +1 -1
- package/dist/esm/queue/domain-queue-consumer.backend.service.d.ts +2 -2
- package/dist/esm/queue/domain-queue-consumer.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/domain-queue-consumer.backend.service.js +1 -4
- package/dist/esm/queue/domain-queue-consumer.backend.service.js.map +1 -1
- package/dist/esm/queue/job-consumer.backend.service.d.ts +2 -2
- package/dist/esm/queue/job-consumer.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/job-consumer.backend.service.js +1 -4
- package/dist/esm/queue/job-consumer.backend.service.js.map +1 -1
- package/dist/esm/queue/job-executor.backend.service.d.ts +2 -2
- package/dist/esm/queue/job-executor.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/job-executor.backend.service.js +1 -4
- package/dist/esm/queue/job-executor.backend.service.js.map +1 -1
- package/dist/esm/queue/queue-monitoring.backend.service.d.ts +8 -4
- package/dist/esm/queue/queue-monitoring.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/queue-monitoring.backend.service.js +25 -17
- package/dist/esm/queue/queue-monitoring.backend.service.js.map +1 -1
- package/dist/esm/queue/queue-worker-initializer.backend.service.d.ts +16 -1
- package/dist/esm/queue/queue-worker-initializer.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/queue-worker-initializer.backend.service.js +16 -1
- package/dist/esm/queue/queue-worker-initializer.backend.service.js.map +1 -1
- package/dist/esm/queue/queue.backend.service.d.ts +3 -3
- package/dist/esm/queue/queue.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/queue.backend.service.js +26 -4
- package/dist/esm/queue/queue.backend.service.js.map +1 -1
- package/dist/esm/queue/worker-shutdown-manager.backend.service.d.ts +2 -2
- package/dist/esm/queue/worker-shutdown-manager.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/worker-shutdown-manager.backend.service.js +18 -3
- package/dist/esm/queue/worker-shutdown-manager.backend.service.js.map +1 -1
- package/dist/esm/rag/utils/rag-chunking.backend.utils.d.ts +50 -25
- package/dist/esm/rag/utils/rag-chunking.backend.utils.d.ts.map +1 -1
- package/dist/esm/rag/utils/rag-chunking.backend.utils.js +147 -39
- package/dist/esm/rag/utils/rag-chunking.backend.utils.js.map +1 -1
- package/dist/esm/rag/utils/rag-context-assembly.backend.utils.d.ts +12 -3
- package/dist/esm/rag/utils/rag-context-assembly.backend.utils.d.ts.map +1 -1
- package/dist/esm/rag/utils/rag-context-assembly.backend.utils.js +12 -3
- package/dist/esm/rag/utils/rag-context-assembly.backend.utils.js.map +1 -1
- package/dist/esm/requests/service/websocket.service.d.ts +9 -0
- package/dist/esm/requests/service/websocket.service.d.ts.map +1 -1
- package/dist/esm/requests/service/websocket.service.js +32 -8
- package/dist/esm/requests/service/websocket.service.js.map +1 -1
- package/dist/esm/resources/models/custom-service-implementations.backend.definition.d.ts.map +1 -1
- package/dist/esm/resources/models/custom-service-implementations.backend.definition.js +14 -2
- package/dist/esm/resources/models/custom-service-implementations.backend.definition.js.map +1 -1
- package/dist/esm/resources/models/resources-operations.backend.definitions.d.ts.map +1 -1
- package/dist/esm/resources/models/resources-operations.backend.definitions.js +2 -0
- package/dist/esm/resources/models/resources-operations.backend.definitions.js.map +1 -1
- package/dist/esm/resources/models/resources-relationships.backend.definitions.d.ts.map +1 -1
- package/dist/esm/resources/models/resources-relationships.backend.definitions.js +14 -0
- package/dist/esm/resources/models/resources-relationships.backend.definitions.js.map +1 -1
- package/dist/esm/resources/models/resources-types.backend.schemas.d.ts +2 -1
- package/dist/esm/resources/models/resources-types.backend.schemas.d.ts.map +1 -1
- package/dist/esm/resources/models/resources-types.backend.schemas.js +8 -0
- package/dist/esm/resources/models/resources-types.backend.schemas.js.map +1 -1
- package/dist/esm/resources/services/resources-registry.backend.service.d.ts +60 -5
- package/dist/esm/resources/services/resources-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/resources/services/resources-registry.backend.service.js +90 -6
- package/dist/esm/resources/services/resources-registry.backend.service.js.map +1 -1
- package/dist/esm/runtime/controllers/health-controller.backend.service.d.ts +36 -3
- package/dist/esm/runtime/controllers/health-controller.backend.service.d.ts.map +1 -1
- package/dist/esm/runtime/controllers/health-controller.backend.service.js +32 -10
- package/dist/esm/runtime/controllers/health-controller.backend.service.js.map +1 -1
- package/dist/esm/runtime/domain-module.backend.definitions.d.ts +24 -0
- package/dist/esm/runtime/domain-module.backend.definitions.d.ts.map +1 -1
- package/dist/esm/runtime/domain-module.backend.definitions.js +24 -0
- package/dist/esm/runtime/domain-module.backend.definitions.js.map +1 -1
- package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.d.ts +51 -0
- package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.d.ts.map +1 -1
- package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.js.map +1 -1
- package/dist/esm/runtime/services/http-server.backend.service.d.ts +26 -0
- package/dist/esm/runtime/services/http-server.backend.service.d.ts.map +1 -1
- package/dist/esm/runtime/services/http-server.backend.service.js +181 -1
- package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -1
- package/dist/esm/runtime/services/start-application.backend.service.d.ts +19 -1
- package/dist/esm/runtime/services/start-application.backend.service.d.ts.map +1 -1
- package/dist/esm/runtime/services/start-application.backend.service.js +261 -77
- package/dist/esm/runtime/services/start-application.backend.service.js.map +1 -1
- package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.d.ts +15 -0
- package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.js +28 -0
- package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.d.ts +5 -1
- package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.js +24 -4
- package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.js +29 -4
- package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.d.ts +114 -0
- package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.js +354 -3
- package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/models/cimd.backend.schemas.d.ts +1 -0
- package/dist/esm/security/authentications/models/cimd.backend.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/models/cimd.backend.schemas.js +22 -0
- package/dist/esm/security/authentications/models/cimd.backend.schemas.js.map +1 -1
- package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.d.ts +15 -0
- package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.js.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.d.ts +0 -2
- package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.js +23 -14
- package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.js.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.d.ts +0 -1
- package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.js +15 -12
- package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.d.ts +113 -3
- package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.js +207 -30
- package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.d.ts +95 -2
- package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.js +153 -9
- package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/anonymous-session.backend.service.d.ts +190 -0
- package/dist/esm/security/authentications/services/anonymous-session.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/anonymous-session.backend.service.js +377 -53
- package/dist/esm/security/authentications/services/anonymous-session.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.js +68 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.d.ts +41 -0
- package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.js +202 -23
- package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.js +42 -1
- package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.js +34 -4
- package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.d.ts +29 -5
- package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.js +77 -5
- package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.d.ts +17 -1
- package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.js +49 -17
- package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.d.ts +43 -1
- package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.js +277 -97
- package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.d.ts +28 -5
- package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.js +72 -12
- package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.js +3 -0
- package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.js.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts +28 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js +283 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.d.ts +4 -3
- package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.js +4 -3
- package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.d.ts +35 -0
- package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.js +111 -21
- package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.d.ts +14 -1
- package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.js +49 -8
- package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/utils/auth-policy-resolution.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/utils/auth-policy-resolution.backend.utils.js +4 -0
- package/dist/esm/security/authentications/services/utils/auth-policy-resolution.backend.utils.js.map +1 -1
- package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.js +6 -0
- package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.d.ts +37 -1
- package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.js +51 -0
- package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.js.map +1 -1
- package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.d.ts +41 -0
- package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.js +45 -0
- package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.js.map +1 -1
- package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.d.ts +116 -0
- package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.d.ts.map +1 -0
- package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.js +162 -0
- package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.js.map +1 -0
- package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.d.ts +20 -20
- package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.js +27 -28
- package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.js.map +1 -1
- package/dist/esm/security/authorizations/platform-access-grant-custom-implementation.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authorizations/platform-access-grant-custom-implementation.backend.service.js +77 -3
- package/dist/esm/security/authorizations/platform-access-grant-custom-implementation.backend.service.js.map +1 -1
- package/dist/esm/security/authorizations/role-ceiling.backend.utils.d.ts +4 -0
- package/dist/esm/security/authorizations/role-ceiling.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/role-ceiling.backend.utils.js +4 -0
- package/dist/esm/security/authorizations/role-ceiling.backend.utils.js.map +1 -1
- package/dist/esm/security/authorizations/role-conferral.backend.utils.d.ts +93 -0
- package/dist/esm/security/authorizations/role-conferral.backend.utils.d.ts.map +1 -0
- package/dist/esm/security/authorizations/role-conferral.backend.utils.js +95 -0
- package/dist/esm/security/authorizations/role-conferral.backend.utils.js.map +1 -0
- package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.d.ts +124 -1
- package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.d.ts.map +1 -1
- package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.js +142 -5
- package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.js.map +1 -1
- package/dist/esm/security/authorizations/services/authorizations.backend.service.d.ts +74 -8
- package/dist/esm/security/authorizations/services/authorizations.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authorizations/services/authorizations.backend.service.js +175 -19
- package/dist/esm/security/authorizations/services/authorizations.backend.service.js.map +1 -1
- package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts +6 -14
- package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js +13 -22
- package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js.map +1 -1
- package/dist/esm/security/connected-accounts/connection-target-authorization.backend.d.ts +60 -0
- package/dist/esm/security/connected-accounts/connection-target-authorization.backend.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/connection-target-authorization.backend.js +79 -0
- package/dist/esm/security/connected-accounts/connection-target-authorization.backend.js.map +1 -0
- package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.d.ts +161 -0
- package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.js +512 -0
- package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.js.map +1 -0
- package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.d.ts +59 -0
- package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.js +22 -0
- package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.js.map +1 -0
- package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.d.ts +44 -0
- package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.js +20 -0
- package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.js.map +1 -0
- package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.d.ts +191 -0
- package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.js +385 -0
- package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.js.map +1 -0
- package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.d.ts +41 -0
- package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.js +358 -0
- package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.d.ts +160 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.js +266 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.js.map +1 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.d.ts +111 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.js +107 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.js.map +1 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.d.ts +54 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.js +153 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.js.map +1 -0
- package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.d.ts +195 -0
- package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.js +387 -0
- package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.js.map +1 -0
- package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.d.ts +45 -0
- package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.js +291 -0
- package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.js.map +1 -0
- package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.d.ts +62 -0
- package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.js +29 -0
- package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.js.map +1 -0
- package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.d.ts +127 -0
- package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.js +277 -0
- package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.js.map +1 -0
- package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.d.ts +66 -0
- package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.js +75 -0
- package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.js.map +1 -0
- package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.d.ts +21 -3
- package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.d.ts.map +1 -1
- package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.js +26 -16
- package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.js.map +1 -1
- package/dist/esm/security/credential-rotation-grace.backend.utils.d.ts +9 -4
- package/dist/esm/security/credential-rotation-grace.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/credential-rotation-grace.backend.utils.js +9 -4
- package/dist/esm/security/credential-rotation-grace.backend.utils.js.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.d.ts +26 -0
- package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.js +43 -0
- package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.js.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts +8 -1
- package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js +49 -0
- package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/security/scim/controllers/scim.backend.controller.d.ts.map +1 -1
- package/dist/esm/security/scim/controllers/scim.backend.controller.js +17 -5
- package/dist/esm/security/scim/controllers/scim.backend.controller.js.map +1 -1
- package/dist/esm/security/scim/models/scim-protocol.backend.schemas.d.ts +67 -29
- package/dist/esm/security/scim/models/scim-protocol.backend.schemas.d.ts.map +1 -1
- package/dist/esm/security/scim/models/scim-protocol.backend.schemas.js +47 -25
- package/dist/esm/security/scim/models/scim-protocol.backend.schemas.js.map +1 -1
- package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.d.ts +10 -2
- package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.js +10 -2
- package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.js.map +1 -1
- package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.d.ts +143 -0
- package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.d.ts.map +1 -0
- package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.js +258 -0
- package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.js.map +1 -0
- package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.d.ts +39 -0
- package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.d.ts.map +1 -0
- package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.js +159 -0
- package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +11 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.backend.service.js","sourceRoot":"","sources":["../../../../../src/errors/services/rate-limit.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Rate Limit Backend Service — CORE-9\n *\n * Single source of truth for controller-level rate limit checks. Three public\n * surfaces, layered:\n *\n * 1. `checkRateLimit(key, max, windowSeconds, organizationId?, messageOverride?, options?)`\n * — low-level primitive (fixed window via atomic Redis INCR+EXPIRE). The K-3\n * ESCAPE-HATCH surface, reserved for the FOUR engine-side call sites\n * (post-PR-8 + Step 7 F-23 sub-PR a + lockout modernization) where the\n * bucket key is NOT cheaply\n * derivable from HTTP-layer inputs:\n * - `AuthenticationOrchestrator.sendSMSOTP` (DB-resolved phone number),\n * - `AuthenticationOrchestrator.authenticatePassword` per-email + per-IP\n * (session-stored email + identify-time IP),\n * - `AuthenticationOrchestrator.sendEmailOTP` (session-resolved\n * userId; migrated from `redisService.incrementRateLimit` in Step 7),\n * - `AuthenticationOrchestrator.authenticatePassword` global lockout\n * counter (per-session email before `verifyPassword(...)`).\n * The lockout caller uses the `options` bridge added in Step 3.1 to swap\n * the thrown\n * error envelope from a 429 `RATE_LIMIT` to a 401 `AUTHENTICATION` +\n * `AUTHENTICATION_ACCOUNT_LOCKED`. The optional `messageOverride`\n * parameter preserves domain-specific UX (canonical use: the OTP-\n * specific phrasing the email-OTP site shipped pre-migration; the\n * lockout site's existing \"Account temporarily locked...\" phrasing).\n * The optional `options` parameter (`errorType` / `customMessageReference`\n * / `contextExtra`) lets the lockout-style caller mint a non-RATE_LIMIT\n * error envelope without forking the primitive; when omitted, behavior\n * is byte-identical to the pre-bridge call shape. Every other\n * rate-limited site reaches for `checkPolicy` or the resource-operation\n * `rateLimit?` field.\n *\n * 2. `checkPolicy(req, res, policy, scopeKey, organizationId?, clientIdOverride?)`\n * — declarative consumer for custom controllers (auth, SCIM, marketing\n * public endpoints). Issues one `RedisService.incrementRateLimit` call\n * per declared window (NOT a `checkRateLimit` call — `checkPolicy` needs\n * the post-increment count to compute `remaining` for headers, and must\n * always increment every window so quota accounting stays consistent\n * across windows; `checkRateLimit` would short-circuit the loop on the\n * first trip) and writes `X-RateLimit-*` headers from the tightest\n * active window. `clientIdOverride` swaps the default IP-keyed bucket\n * for an authenticated subject identifier (`token._id`, `userId`,\n * normalized email/phone) so IP rotation can't bypass per-subject caps.\n *\n * 3. `checkPolicyForVariant(req, res, variant)` — pre-flight consumer used\n * by `ControllerResourceBackendService.doOperation` BEFORE\n * execution-context creation, validation, and authorization. Early-returns\n * when the variant declares no `rateLimit?` policy (zero Redis traffic\n * on the no-policy fast path).\n *\n * Fail-closed (C-3): the underlying `RedisService.incrementRateLimit` throws\n * `ErrorType.DATABASE` when Redis is unavailable. Both `checkPolicy` and\n * `checkPolicyForVariant` propagate that error rather than silently passing\n * traffic. The global HTTP limiter\n * (`http-server.backend.service.ts:setupRateLimit`) keeps its in-memory\n * fail-open Map as the safety net at the perimeter — the per-endpoint\n * surface is the security boundary, not the noisy-neighbor preventer.\n *\n * @see `.cursor/plans/rate-limit-system-unification.md` (K-3, K-4, K-6, C-2, C-3)\n */\n\nimport 'reflect-metadata';\nimport { injectable, inject } from 'inversify';\nimport type { Request, Response } from 'express';\nimport {\n ErrorCustomMessageReference,\n ErrorType,\n ResourceOperationVariantType,\n WildoHeaderKeys,\n type RateLimitConfiguration,\n type ResourceType,\n} from '@wildo-ai/saas-models';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport { RedisService } from '~wildo-backend-lib/databases/services/redis.service';\nimport { getClientIpFromRequest } from '~wildo-backend-lib/runtime/utils/request-client-ip.utils';\nimport { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport { resolveRateLimitEnvironmentMultiplier } from '~wildo-backend-lib/errors/utils/rate-limit-environment-relaxation.backend.utils';\nimport { ErrorBuilderBackendService } from './error-builder.backend.service';\n\n/**\n * Per-window enforcement record built from `RateLimitConfiguration`.\n *\n * - `name` is the Redis key suffix (`minute` / `hour` / `day`) and the\n * identifier used in JSDoc/log lines.\n * - `seconds` is the fixed-window length passed to `incrementRateLimit`.\n * Used as a fallback when Redis cannot report the remaining TTL.\n */\ninterface PolicyWindow {\n /**\n * Used as the trailing segment of the Redis key\n * (`<scope>:<clientId>:<name>`). Canonical names are `'minute'`,\n * `'hour'`, `'day'`. Custom windows derived from\n * `RateLimitConfiguration.customWindows` use `'custom:<seconds>s'`\n * (e.g. `'custom:300s'` for the 5-minute phone-verify window) — the\n * seconds value is embedded so two custom windows of different lengths\n * never collide on the same Redis key, and operators tailing Redis\n * traffic can read the window length straight from the key.\n */\n readonly name: string;\n readonly max: number;\n readonly seconds: number;\n}\n\n@injectable()\nexport class RateLimitBackendService {\n constructor(\n @inject(SAAS_SERVICE_TYPES.RedisService) private readonly redisService: RedisService,\n @inject(SAAS_SERVICE_TYPES.ErrorBuilderService) private readonly errorBuilder: ErrorBuilderBackendService,\n @inject(SAAS_SERVICE_TYPES.AppConfigService) private readonly appConfigService: AppConfigurationService,\n ) {}\n\n /**\n * Low-level primitive: increment count for `key`, throw if exceeded.\n *\n * The K-3 escape-hatch surface — used directly only when the bucket key\n * is NOT cheaply derivable from HTTP-layer inputs. FOUR canonical sites\n * use this surface today (`sendSMSOTP` keying on a DB-resolved phone\n * number; `authenticatePassword` per-email + per-IP keying on a session-\n * stored email + IP captured at identify time; `sendEmailOTP`\n * keying on a session-resolved userId, preserving its OTP-specific 429\n * message via `messageOverride`; and the `authenticatePassword`\n * global lockout counter, using the `options` bridge added below to\n * swap the thrown error envelope\n * from a 429 `RATE_LIMIT` to a 401-shaped `AUTHENTICATION` +\n * `AUTHENTICATION_ACCOUNT_LOCKED` reference. Every other rate-limited\n * site should reach for `checkPolicy` (custom controllers) or the\n * resource-operation `rateLimit?` field (resource variants) instead —\n * those surfaces emit `X-RateLimit-*` headers and accept declarative\n * multi-window policies.\n *\n * @param key — identifier (e.g. `auth:reset:email:${email}`)\n * @param maxRequests — max allowed in window\n * @param windowSeconds — window duration in seconds\n * @param organizationId — optional tenant scope (folded into the Redis key)\n * @param messageOverride — optional custom error message for the\n * response. Defaults to the generic `'Too many requests. Please try\n * again later.'`. Pass a domain-specific message when the call site\n * has UX context the generic message would lose (e.g. the email-OTP\n * send cap migrated from `redisService.incrementRateLimit` in Step 7\n * F-23 sub-PR a — the original site shipped `'Too many OTP requests.\n * Please wait before requesting another code.'` so users understand\n * the wait is OTP-specific, not a global request cap; the lockout\n * site uses `'Account temporarily locked due to too many failed\n * attempts. Please try again later.'` to preserve its existing UX).\n * @param options — bridge parameters for callers that need to swap the\n * thrown error envelope (the K-3 escape-hatch's escape-hatch). Added\n * in the lockout-state-machine-modernization plan (Step 3.1) so the\n * global lockout counter — semantically a per-email cap, but\n * user-facing as an account-locked state — can ship the same\n * `ErrorType.AUTHENTICATION` + `AUTHENTICATION_ACCOUNT_LOCKED`\n * envelope its predecessor `_checkGlobalLockout` shipped, without\n * forking the primitive into two near-identical methods.\n * - `errorType` overrides the default `ErrorType.RATE_LIMIT` (the\n * lockout site uses `ErrorType.AUTHENTICATION` so it routes\n * through the same 401 handler chain as the existing\n * status-derived `AUTHENTICATION_ACCOUNT_LOCKED` throws).\n * - `customMessageReference` adds the `customMessageReference`\n * field to the built error (lockout uses\n * `AUTHENTICATION_ACCOUNT_LOCKED`). When omitted, the field is\n * not present in the built error options at all (preserves the\n * pre-bridge call shape for default K-3 sites).\n * - `contextExtra` adds extra fields to the error `context` (e.g.\n * `{ lockoutDurationMinutes: 30 }` for the lockout site).\n * Spread BEFORE the canonical `message` and `retryAfterSeconds`,\n * so those two always win on collision — use `messageOverride`\n * to swap the message, not `contextExtra.message`.\n * When `options` is omitted entirely (the only shape the 3 existing\n * K-3 sites use), the call is byte-identical to the pre-bridge\n * behavior: `ErrorType.RATE_LIMIT`, no `customMessageReference`,\n * bare `{ message, retryAfterSeconds }` context.\n */\n public async checkRateLimit(\n key: string,\n maxRequests: number,\n windowSeconds: number,\n organizationId?: string,\n messageOverride?: string,\n options?: {\n errorType?: ErrorType;\n customMessageReference?: ErrorCustomMessageReference;\n contextExtra?: Record<string, unknown>;\n },\n ): Promise<void> {\n const effectiveMaxRequests = maxRequests * this.resolveWindowMultiplier();\n const count = await this.redisService.incrementRateLimit(key, windowSeconds, organizationId);\n if (count > effectiveMaxRequests) {\n const retryAfterSeconds = await this.resolveRateLimitTtl(key, organizationId, windowSeconds);\n // Conditionally include `customMessageReference` so the built error\n // options object is byte-identical to the pre-bridge shape when\n // `options` is omitted (the default K-3 callers' contract).\n const buildOptions: {\n customMessageReference?: ErrorCustomMessageReference;\n context: Record<string, unknown>;\n } = {\n context: {\n ...options?.contextExtra,\n message: messageOverride ?? 'Too many requests. Please try again later.',\n retryAfterSeconds,\n },\n };\n if (options?.customMessageReference !== undefined) {\n buildOptions.customMessageReference = options.customMessageReference;\n }\n throw this.errorBuilder.buildError(\n options?.errorType ?? ErrorType.RATE_LIMIT,\n undefined,\n buildOptions,\n );\n }\n }\n\n /**\n * @wildo_source:part:start saas.backend.rate-limit-service.check-policy facet:layer:backend facet:family:rate-limit\n *\n * Declarative multi-window policy enforcement.\n *\n * Increments one Redis counter per declared window (so window accounting\n * stays consistent — a request that trips the per-minute window still\n * counts against the per-hour quota), then:\n *\n * - Writes `X-RateLimit-Limit` / `X-RateLimit-Remaining` / `X-RateLimit-Reset`\n * headers from the **tightest active window** (the one with the fewest\n * `remaining` slots). Matches the existing system-1 header contract (K-6).\n * - On 429, throws `ErrorType.RATE_LIMIT` with `retryAfterSeconds` from\n * the **latest tripped window**. Declared windows are AND-ed, so a retry\n * cannot succeed until every tripped counter has reset.\n *\n * Client identifier (the per-bucket key suffix, what makes one client's\n * counter independent from another's) defaults to `getClientIpFromRequest(req)`\n * — the canonical pre-auth identity at the controller seam, consistent\n * with the global HTTP limiter (system 1) which also keys on raw IP by\n * construction. Custom controllers that have already resolved a more\n * appropriate identity can pass `clientIdOverride` to bypass IP\n * derivation entirely:\n * - SCIM controller — `clientIdOverride: token._id` (per-token quota,\n * independent of which IP the IdP is calling from today).\n * - Authenticated user actions — `clientIdOverride: userId` (one user,\n * one bucket across all their devices/IPs — credential-stuffing-style\n * IP rotation can't bypass the per-user cap).\n * - Email-keyed flows (password reset, magic link) — `clientIdOverride:\n * email` (one email address, one bucket across all originating IPs).\n * The default IP-keyed mode is correct for pre-auth flows where no\n * better identity exists yet (the resource-controller pre-flight seam\n * via `checkPolicyForVariant`, anonymous-session init, etc.).\n *\n * `requestsPerMinute` / `requestsPerHour` / `requestsPerDay` AND any\n * entries in `customWindows` (D-3, Option A — for the rare endpoint\n * whose business semantics genuinely don't fit a minute / hour / day\n * grid, e.g. the SMS phone-verify family on a 5-minute window tied to\n * the OTP TTL) are all honored at this seam.\n *\n * @param req — express request. Used for IP extraction when\n * `clientIdOverride` is omitted; not read otherwise. Always required\n * so future enhancements (e.g. surfacing the IP in error context for\n * audit) don't need a signature change.\n * @param res — express response (headers written as side-effect)\n * @param policy — the declarative policy. A policy with no enforced\n * windows (all of `requestsPerMinute / Hour / Day` undefined and\n * `customWindows` either undefined or empty) is a no-op (no-policy\n * fast path; zero Redis traffic).\n * @param scopeKey — author-supplied namespace (e.g. `auth:password_change`,\n * `resource:INBOUND_CONTACTS:CREATE`, `scim:token`). Composed with the\n * client identifier to form the Redis key:\n * `${scopeKey}:${clientId}:${windowName}`.\n * @param organizationId — optional tenant scope. Forwarded to the underlying\n * `RedisService.incrementRateLimit` so per-tenant quotas don't collide\n * across orgs. Omit for single-tenant or pre-auth policies (the resource\n * pre-flight seam can't resolve a tenant yet by construction — C-5).\n * @param clientIdOverride — optional explicit client identifier. When\n * provided, replaces `getClientIpFromRequest(req)` as the per-bucket\n * key suffix. Use whenever the caller has resolved an authenticated\n * subject identifier (token id, user id, email) so the bucket can't\n * be bypassed by IP rotation.\n *\n * @remarks Import from `@wildo-ai/saas-backend-lib`.\n */\n /** @wildo_source:part:end saas.backend.rate-limit-service.check-policy */\n public async checkPolicy(\n req: Request,\n res: Response,\n policy: RateLimitConfiguration,\n scopeKey: string,\n organizationId?: string,\n clientIdOverride?: string,\n ): Promise<void> {\n const windows = this.deriveWindows(policy);\n if (windows.length === 0) {\n return;\n }\n\n const clientId = clientIdOverride ?? getClientIpFromRequest(req);\n const identifier = `${scopeKey}:${clientId}`;\n\n // Track the tightest active window (fewest `remaining` slots) for\n // headers, and the latest tripped window for retry-after. Declared\n // windows are AND-ed, so recovery requires every exceeded window to\n // reset, not just the shortest one.\n let tightestActive: { max: number; remaining: number; resetSeconds: number } | undefined;\n let latestTripped: { retryAfterSeconds: number } | undefined;\n\n for (const window of windows) {\n const key = `${identifier}:${window.name}`;\n const count = await this.redisService.incrementRateLimit(key, window.seconds, organizationId);\n const resetSeconds = await this.resolveRateLimitTtl(key, organizationId, window.seconds);\n const remaining = Math.max(0, window.max - count);\n\n if (count > window.max) {\n if (!latestTripped || resetSeconds > latestTripped.retryAfterSeconds) {\n latestTripped = { retryAfterSeconds: resetSeconds };\n }\n }\n\n if (!tightestActive || remaining < tightestActive.remaining) {\n tightestActive = { max: window.max, remaining, resetSeconds };\n }\n }\n\n if (tightestActive) {\n // F-9 compare-and-set guard. Multiple `checkPolicy` invocations can\n // run on the same response within a single request lifecycle — the\n // canonical case is a resource operation that BOTH carries a\n // declarative `rateLimit?` on its variant (enforced by the\n // pre-flight `checkPolicyForVariant` seam) AND triggers a\n // service-level call that runs its own `checkPolicy` (e.g.\n // `INBOUND_CONTACTS.CREATE` for an anonymous user → the\n // 5/min contact-create policy fires first, then\n // `createAnonymousUser`'s 10/min session-init policy fires).\n // Without this guard the second call would overwrite the first's\n // headers and the response would advertise the LOOSER policy,\n // hiding the binding constraint from the client. Preserve the\n // tighter (smaller `remaining`) window across calls so the\n // headers always reflect the binding quota.\n const existingRemainingHeader = res.getHeader(WildoHeaderKeys.RATE_LIMIT_REMAINING);\n const existingRemainingCandidate = existingRemainingHeader === undefined\n ? undefined\n : Number(existingRemainingHeader);\n const existingRemaining = existingRemainingCandidate === undefined || Number.isFinite(existingRemainingCandidate)\n ? existingRemainingCandidate\n : undefined;\n if (existingRemaining === undefined || tightestActive.remaining < existingRemaining) {\n res.setHeader(WildoHeaderKeys.RATE_LIMIT_LIMIT, String(tightestActive.max));\n res.setHeader(WildoHeaderKeys.RATE_LIMIT_REMAINING, String(tightestActive.remaining));\n res.setHeader(WildoHeaderKeys.RATE_LIMIT_RESET, String(tightestActive.resetSeconds));\n }\n }\n\n if (latestTripped) {\n // RFC 6585 `Retry-After` header — standard cue for clients/proxies\n // that don't parse the JSON error body. Set BEFORE throw so Express's\n // error middleware (which writes the body via `res.status(429).json`)\n // preserves it on the outbound response. Kept as a literal string\n // rather than a `WildoHeaderKeys` constant because `Retry-After` is\n // an IANA-registered header, not a Wildo-custom one; callers that\n // search the codebase will find it by its canonical spelling.\n // Same F-9 compare-and-set discipline as the `X-RateLimit-*` headers\n // above: when multiple `checkPolicy` calls trip on the same\n // response, prefer the LARGER hint because all active quotas must\n // recover before the request can succeed.\n const existingRetryHeader = res.getHeader('Retry-After');\n const existingRetryCandidate = existingRetryHeader === undefined\n ? undefined\n : Number(existingRetryHeader);\n const existingRetry = existingRetryCandidate === undefined || Number.isFinite(existingRetryCandidate)\n ? existingRetryCandidate\n : undefined;\n if (existingRetry === undefined || latestTripped.retryAfterSeconds > existingRetry) {\n res.setHeader('Retry-After', String(latestTripped.retryAfterSeconds));\n }\n throw this.errorBuilder.buildError(ErrorType.RATE_LIMIT, undefined, {\n customMessageReference: ErrorCustomMessageReference.RATE_LIMIT,\n context: {\n // diagnostic (log-only)\n retryAfterSeconds: latestTripped.retryAfterSeconds,\n },\n });\n }\n }\n\n /**\n * Pre-flight enforcement for resource operations — the consumer behind\n * the `rateLimit?` field on `API_CALL` / `API_CALL_WITH_CALLBACK` variants.\n *\n * Called from `ControllerResourceBackendService.doOperation` BEFORE\n * execution-context creation, request-data validation, and authorization\n * (C-2). At this seam the authenticated identity is unknown by\n * construction, so the client identifier MUST be the IP — there is no\n * authenticated-user alternative.\n *\n * Early-returns (zero Redis traffic) when:\n * - The variant has no `rateLimit?` policy (the common case until\n * per-endpoint policies are adopted), OR\n * - The variant is not an HTTP variant (defensive guard — `doOperation`\n * today only routes API_CALL / API_CALL_WITH_CALLBACK, but the type\n * surface accepts the broader operation union).\n *\n * Auto-derives `scopeKey = resource:${resourceIdentifier}:${operationIdentifier}`\n * — keeps resource configurations free of bespoke Redis-key strings (K-4).\n *\n * @param req — express request\n * @param res — express response (for `X-RateLimit-*` header writes)\n * @param variant — the resolved operation about to execute\n */\n public async checkPolicyForVariant(\n req: Request,\n res: Response,\n variant: {\n readonly variantType: ResourceOperationVariantType;\n readonly resourceIdentifier: ResourceType;\n // The resolved operation type uses generic enum constraints\n // (`TCustomOperationEnum | TCoreOperationEnum`, both bounded by\n // `Record<string, string>`); at runtime the value is always a string\n // (the enum's value, not the enum object). `unknown` keeps the\n // structural surface broad enough to accept any operation variant\n // shape; the value is stringified for the Redis scope key.\n readonly operationIdentifier: unknown;\n readonly rateLimit?: RateLimitConfiguration;\n },\n ): Promise<void> {\n if (!variant.rateLimit) {\n return;\n }\n if (\n variant.variantType !== ResourceOperationVariantType.API_CALL\n && variant.variantType !== ResourceOperationVariantType.API_CALL_WITH_CALLBACK\n ) {\n return;\n }\n\n const scopeKey = `resource:${String(variant.resourceIdentifier)}:${String(variant.operationIdentifier)}`;\n await this.checkPolicy(req, res, variant.rateLimit, scopeKey);\n }\n\n /**\n * Build the enforced-window list from a declared policy. Includes\n * `customWindows` after the canonical three so AND-semantics treat\n * them identically to the named windows (D-3, Option A — custom\n * windows participate in the same `tightestActive` / `latestTripped`\n * picks as the canonical ones).\n *\n * Custom-window dedupe (F-16, PR 7-D-3 review fix): when an author\n * accidentally declares two `customWindows` entries with the same\n * `windowSeconds` (e.g. `[{ rpw: 3, ws: 300 }, { rpw: 5, ws: 300 }]`),\n * both would derive the SAME Redis key (`<scope>:<id>:custom:300s`)\n * and a single client request would silently double-increment the\n * counter, halving the effective cap. We resolve the misconfig\n * deterministically: keep the entry with the SMALLEST `requestsPerWindow`\n * (most restrictive interpretation = safest for the protected resource)\n * and emit a `console.warn` so authors see the misconfig in logs. Any\n * canonical-window collisions (e.g. `{ requestsPerMinute: 5,\n * customWindows: [{ rpw: 3, ws: 60 }] }`) are NOT deduped — they\n * derive different key suffixes (`:minute` vs `:custom:60s`) and\n * coexist correctly; the JSDoc on `RateLimitConfigurationSchema`\n * steers authors away from this awkward shape, but it isn't broken.\n */\n private deriveWindows(policy: RateLimitConfiguration): PolicyWindow[] {\n const multiplier = this.resolveWindowMultiplier();\n const windows: PolicyWindow[] = [];\n if (policy.requestsPerMinute !== undefined) {\n windows.push({ name: 'minute', max: policy.requestsPerMinute * multiplier, seconds: 60 });\n }\n if (policy.requestsPerHour !== undefined) {\n windows.push({ name: 'hour', max: policy.requestsPerHour * multiplier, seconds: 3600 });\n }\n if (policy.requestsPerDay !== undefined) {\n windows.push({ name: 'day', max: policy.requestsPerDay * multiplier, seconds: 86400 });\n }\n if (policy.customWindows && policy.customWindows.length > 0) {\n // Map by `windowSeconds`; on collision keep the smallest `max`\n // (most restrictive) and warn. Insertion order is preserved by\n // `Map`, so the canonical-then-custom emit order downstream is\n // unchanged for non-colliding cases.\n const byWindowSeconds = new Map<number, { max: number; seconds: number }>();\n for (const custom of policy.customWindows) {\n const existing = byWindowSeconds.get(custom.windowSeconds);\n if (existing === undefined) {\n byWindowSeconds.set(custom.windowSeconds, {\n max: custom.requestsPerWindow,\n seconds: custom.windowSeconds,\n });\n } else if (custom.requestsPerWindow < existing.max) {\n // eslint-disable-next-line no-console\n console.warn(\n '[rate-limit] Duplicate customWindows.windowSeconds detected; keeping the smaller (more restrictive) requestsPerWindow.',\n { windowSeconds: custom.windowSeconds, kept: custom.requestsPerWindow, dropped: existing.max },\n );\n byWindowSeconds.set(custom.windowSeconds, {\n max: custom.requestsPerWindow,\n seconds: custom.windowSeconds,\n });\n } else {\n // eslint-disable-next-line no-console\n console.warn(\n '[rate-limit] Duplicate customWindows.windowSeconds detected; keeping the smaller (more restrictive) requestsPerWindow.',\n { windowSeconds: custom.windowSeconds, kept: existing.max, dropped: custom.requestsPerWindow },\n );\n }\n }\n for (const [, custom] of byWindowSeconds) {\n windows.push({\n name: `custom:${custom.seconds}s`,\n max: custom.max * multiplier,\n seconds: custom.seconds,\n });\n }\n }\n return windows;\n }\n\n /**\n * Non-production window-max relaxation for every policy this service enforces\n * (register, login, MFA, magic-link, SCIM, marketing public endpoints, resource\n * `rateLimit?` variants — every `checkPolicy` / `checkPolicyForVariant` caller,\n * K-3/K-4).\n *\n * The branch itself lives in\n * {@link resolveRateLimitEnvironmentMultiplier} — this service is one of SIX\n * abuse-throttle sites in the engine and used to own a private copy of the\n * constant, which is exactly why the other five never got the relaxation. Do not\n * re-inline it here.\n */\n private resolveWindowMultiplier(): number {\n return resolveRateLimitEnvironmentMultiplier(this.appConfigService.applicationEnv);\n }\n\n private async resolveRateLimitTtl(\n identifier: string,\n organizationId: string | undefined,\n fallbackSeconds: number,\n ): Promise<number> {\n const getRateLimitTtl = (this.redisService as RedisService & {\n getRateLimitTtl?: (identifier: string, organizationId?: string) => Promise<number>;\n }).getRateLimitTtl;\n if (!getRateLimitTtl) {\n return fallbackSeconds;\n }\n\n try {\n const ttl = await getRateLimitTtl.call(this.redisService, identifier, organizationId);\n return ttl >= 0 ? ttl : fallbackSeconds;\n } catch {\n return fallbackSeconds;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"rate-limit.backend.service.js","sourceRoot":"","sources":["../../../../../src/errors/services/rate-limit.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Rate Limit Backend Service — CORE-9\n *\n * Single source of truth for controller-level rate limit checks. Three public\n * surfaces, layered:\n *\n * 1. `checkRateLimit(key, max, windowSeconds, organizationId?, messageOverride?, options?)`\n * — low-level primitive (fixed window via atomic Redis INCR+EXPIRE). The K-3\n * ESCAPE-HATCH surface, reserved for the FOUR engine-side call sites\n * (post-PR-8 + Step 7 F-23 sub-PR a + lockout modernization) where the\n * bucket key is NOT cheaply\n * derivable from HTTP-layer inputs:\n * - `AuthenticationOrchestrator.sendSMSOTP` (DB-resolved phone number),\n * - `AuthenticationOrchestrator.authenticatePassword` per-email + per-IP\n * (session-stored email + identify-time IP),\n * - `AuthenticationOrchestrator.sendEmailOTP` (session-resolved\n * userId; migrated from `redisService.incrementRateLimit` in Step 7),\n * - `AuthenticationOrchestrator.authenticatePassword` global lockout\n * counter (per-session email before `verifyPassword(...)`).\n * The lockout caller uses the `options` bridge added in Step 3.1 to swap\n * the thrown\n * error envelope from a 429 `RATE_LIMIT` to a 401 `AUTHENTICATION` +\n * `AUTHENTICATION_ACCOUNT_LOCKED`. The optional `messageOverride`\n * parameter preserves domain-specific UX (canonical use: the OTP-\n * specific phrasing the email-OTP site shipped pre-migration; the\n * lockout site's existing \"Account temporarily locked...\" phrasing).\n * The optional `options` parameter (`errorType` / `customMessageReference`\n * / `contextExtra`) lets the lockout-style caller mint a non-RATE_LIMIT\n * error envelope without forking the primitive; when omitted, behavior\n * is byte-identical to the pre-bridge call shape. Every other\n * rate-limited site reaches for `checkPolicy` or the resource-operation\n * `rateLimit?` field.\n *\n * 2. `checkPolicy(req, res, policy, scopeKey, organizationId?, clientIdOverride?)`\n * — declarative consumer for custom controllers (auth, SCIM, marketing\n * public endpoints). Issues one `RedisService.incrementRateLimit` call\n * per declared window (NOT a `checkRateLimit` call — `checkPolicy` needs\n * the post-increment count to compute `remaining` for headers, and must\n * always increment every window so quota accounting stays consistent\n * across windows; `checkRateLimit` would short-circuit the loop on the\n * first trip) and writes `X-RateLimit-*` headers from the tightest\n * active window. `clientIdOverride` swaps the default IP-keyed bucket\n * for an authenticated subject identifier (`token._id`, `userId`,\n * normalized email/phone) so IP rotation can't bypass per-subject caps.\n *\n * 3. `checkPolicyForVariant(req, res, variant)` — pre-flight consumer used\n * by `ControllerResourceBackendService.doOperation` BEFORE\n * execution-context creation, validation, and authorization. Early-returns\n * when the variant declares no `rateLimit?` policy (zero Redis traffic\n * on the no-policy fast path).\n *\n * Fail-closed (C-3): the underlying `RedisService.incrementRateLimit` throws\n * `ErrorType.DATABASE` when Redis is unavailable. Both `checkPolicy` and\n * `checkPolicyForVariant` propagate that error rather than silently passing\n * traffic. The global HTTP limiter\n * (`http-server.backend.service.ts:setupRateLimit`) keeps its in-memory\n * fail-open Map as the safety net at the perimeter — the per-endpoint\n * surface is the security boundary, not the noisy-neighbor preventer.\n *\n * @see `.cursor/plans/rate-limit-system-unification.md` (K-3, K-4, K-6, C-2, C-3)\n */\n\nimport 'reflect-metadata';\nimport { injectable, inject } from 'inversify';\nimport type { Request, Response } from 'express';\nimport {\n ErrorCustomMessageReference,\n ErrorType,\n ResourceOperationVariantType,\n WildoHeaderKeys,\n type RateLimitConfiguration,\n type ResourceType,\n} from '@wildo-ai/saas-models';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport { RedisService } from '~wildo-backend-lib/databases/services/redis.service';\nimport { getClientIpFromRequest } from '~wildo-backend-lib/runtime/utils/request-client-ip.utils';\nimport { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport { resolveRateLimitEnvironmentMultiplier } from '~wildo-backend-lib/errors/utils/rate-limit-environment-relaxation.backend.utils';\nimport { ErrorBuilderBackendService } from './error-builder.backend.service';\n\n/**\n * Per-window enforcement record built from `RateLimitConfiguration`.\n *\n * - `name` is the Redis key suffix (`minute` / `hour` / `day`) and the\n * identifier used in JSDoc/log lines.\n * - `seconds` is the fixed-window length passed to `incrementRateLimit`.\n * Used as a fallback when Redis cannot report the remaining TTL.\n */\ninterface PolicyWindow {\n /**\n * Used as the trailing segment of the Redis key\n * (`<scope>:<clientId>:<name>`). Canonical names are `'minute'`,\n * `'hour'`, `'day'`. Custom windows derived from\n * `RateLimitConfiguration.customWindows` use `'custom:<seconds>s'`\n * (e.g. `'custom:300s'` for the 5-minute phone-verify window) — the\n * seconds value is embedded so two custom windows of different lengths\n * never collide on the same Redis key, and operators tailing Redis\n * traffic can read the window length straight from the key.\n */\n readonly name: string;\n readonly max: number;\n readonly seconds: number;\n}\n\n@injectable()\nexport class RateLimitBackendService {\n constructor(\n @inject(SAAS_SERVICE_TYPES.RedisService) private readonly redisService: RedisService,\n @inject(SAAS_SERVICE_TYPES.ErrorBuilderService) private readonly errorBuilder: ErrorBuilderBackendService,\n @inject(SAAS_SERVICE_TYPES.AppConfigService) private readonly appConfigService: AppConfigurationService,\n ) {}\n\n /**\n * Low-level primitive: increment count for `key`, throw if exceeded.\n *\n * The K-3 escape-hatch surface — used directly only when the bucket key\n * is NOT cheaply derivable from HTTP-layer inputs. FOUR canonical sites\n * use this surface today (`sendSMSOTP` keying on a DB-resolved phone\n * number; `authenticatePassword` per-email + per-IP keying on a session-\n * stored email + IP captured at identify time; `sendEmailOTP`\n * keying on a session-resolved userId, preserving its OTP-specific 429\n * message via `messageOverride`; and the `authenticatePassword`\n * global lockout counter, using the `options` bridge added below to\n * swap the thrown error envelope\n * from a 429 `RATE_LIMIT` to a 401-shaped `AUTHENTICATION` +\n * `AUTHENTICATION_ACCOUNT_LOCKED` reference. Every other rate-limited\n * site should reach for `checkPolicy` (custom controllers) or the\n * resource-operation `rateLimit?` field (resource variants) instead —\n * those surfaces emit `X-RateLimit-*` headers and accept declarative\n * multi-window policies.\n *\n * @param key — identifier (e.g. `auth:reset:email:${email}`)\n * @param maxRequests — max allowed in window\n * @param windowSeconds — window duration in seconds\n * @param organizationId — optional tenant scope (folded into the Redis key)\n * @param messageOverride — optional custom error message for the\n * response. Defaults to the generic `'Too many requests. Please try\n * again later.'`. Pass a domain-specific message when the call site\n * has UX context the generic message would lose (e.g. the email-OTP\n * send cap migrated from `redisService.incrementRateLimit` in Step 7\n * F-23 sub-PR a — the original site shipped `'Too many OTP requests.\n * Please wait before requesting another code.'` so users understand\n * the wait is OTP-specific, not a global request cap; the lockout\n * site uses `'Account temporarily locked due to too many failed\n * attempts. Please try again later.'` to preserve its existing UX).\n * @param options — bridge parameters for callers that need to swap the\n * thrown error envelope (the K-3 escape-hatch's escape-hatch). Added\n * in the lockout-state-machine-modernization plan (Step 3.1) so the\n * global lockout counter — semantically a per-email cap, but\n * user-facing as an account-locked state — can ship the same\n * `ErrorType.AUTHENTICATION` + `AUTHENTICATION_ACCOUNT_LOCKED`\n * envelope its predecessor `_checkGlobalLockout` shipped, without\n * forking the primitive into two near-identical methods.\n * - `errorType` overrides the default `ErrorType.RATE_LIMIT` (the\n * lockout site uses `ErrorType.AUTHENTICATION` so it routes\n * through the same 401 handler chain as the existing\n * status-derived `AUTHENTICATION_ACCOUNT_LOCKED` throws).\n * - `customMessageReference` adds the `customMessageReference`\n * field to the built error (lockout uses\n * `AUTHENTICATION_ACCOUNT_LOCKED`). When omitted, the field is\n * not present in the built error options at all (preserves the\n * pre-bridge call shape for default K-3 sites).\n * - `contextExtra` adds extra fields to the error `context` (e.g.\n * `{ lockoutDurationMinutes: 30 }` for the lockout site).\n * Spread BEFORE the canonical `message` and `retryAfterSeconds`,\n * so those two always win on collision — use `messageOverride`\n * to swap the message, not `contextExtra.message`.\n * When `options` is omitted entirely (the only shape the 3 existing\n * K-3 sites use), the call is byte-identical to the pre-bridge\n * behavior: `ErrorType.RATE_LIMIT`, no `customMessageReference`,\n * bare `{ message, retryAfterSeconds }` context.\n */\n public async checkRateLimit(\n key: string,\n maxRequests: number,\n windowSeconds: number,\n organizationId?: string,\n messageOverride?: string,\n options?: {\n errorType?: ErrorType;\n customMessageReference?: ErrorCustomMessageReference;\n contextExtra?: Record<string, unknown>;\n },\n ): Promise<void> {\n const effectiveMaxRequests = maxRequests * this.resolveWindowMultiplier();\n const count = await this.redisService.incrementRateLimit(key, windowSeconds, organizationId);\n if (count > effectiveMaxRequests) {\n const retryAfterSeconds = await this.resolveRateLimitTtl(key, organizationId, windowSeconds);\n // Conditionally include `customMessageReference` so the built error\n // options object is byte-identical to the pre-bridge shape when\n // `options` is omitted (the default K-3 callers' contract).\n const buildOptions: {\n customMessageReference?: ErrorCustomMessageReference;\n context: Record<string, unknown>;\n } = {\n context: {\n ...options?.contextExtra,\n message: messageOverride ?? 'Too many requests. Please try again later.',\n retryAfterSeconds,\n },\n };\n if (options?.customMessageReference !== undefined) {\n buildOptions.customMessageReference = options.customMessageReference;\n }\n throw this.errorBuilder.buildError(\n options?.errorType ?? ErrorType.RATE_LIMIT,\n undefined,\n buildOptions,\n );\n }\n }\n\n /**\n * @wildo_source:part:start saas.backend.rate-limit-service.check-policy facet:layer:backend facet:family:rate-limit\n *\n * Declarative multi-window policy enforcement.\n *\n * Increments one Redis counter per declared window (so window accounting\n * stays consistent — a request that trips the per-minute window still\n * counts against the per-hour quota), then:\n *\n * - Writes `X-RateLimit-Limit` / `X-RateLimit-Remaining` / `X-RateLimit-Reset`\n * headers from the **tightest active window** (the one with the fewest\n * `remaining` slots). Matches the existing system-1 header contract (K-6).\n * - On 429, throws `ErrorType.RATE_LIMIT` with `retryAfterSeconds` from\n * the **latest tripped window**. Declared windows are AND-ed, so a retry\n * cannot succeed until every tripped counter has reset.\n *\n * Client identifier (the per-bucket key suffix, what makes one client's\n * counter independent from another's) defaults to `getClientIpFromRequest(req)`\n * — the canonical pre-auth identity at the controller seam, consistent\n * with the global HTTP limiter (system 1) which also keys on raw IP by\n * construction. Custom controllers that have already resolved a more\n * appropriate identity can pass `clientIdOverride` to bypass IP\n * derivation entirely:\n * - SCIM controller — `clientIdOverride: token._id` (per-token quota,\n * independent of which IP the IdP is calling from today).\n * - Authenticated user actions — `clientIdOverride: userId` (one user,\n * one bucket across all their devices/IPs — credential-stuffing-style\n * IP rotation can't bypass the per-user cap).\n * - Email-keyed flows (password reset, magic link) — `clientIdOverride:\n * email` (one email address, one bucket across all originating IPs).\n * The default IP-keyed mode is correct for pre-auth flows where no\n * better identity exists yet (the resource-controller pre-flight seam\n * via `checkPolicyForVariant`, anonymous-session init, etc.).\n *\n * `requestsPerMinute` / `requestsPerHour` / `requestsPerDay` AND any\n * entries in `customWindows` (D-3, Option A — for the rare endpoint\n * whose business semantics genuinely don't fit a minute / hour / day\n * grid, e.g. the SMS phone-verify family on a 5-minute window tied to\n * the OTP TTL) are all honored at this seam.\n *\n * @param req — express request. Used for IP extraction when\n * `clientIdOverride` is omitted; not read otherwise. Always required\n * so future enhancements (e.g. surfacing the IP in error context for\n * audit) don't need a signature change.\n * @param res — express response (headers written as side-effect)\n * @param policy — the declarative policy. A policy with no enforced\n * windows (all of `requestsPerMinute / Hour / Day` undefined and\n * `customWindows` either undefined or empty) is a no-op (no-policy\n * fast path; zero Redis traffic).\n * @param scopeKey — author-supplied namespace (e.g. `auth:password_change`,\n * `resource:INBOUND_CONTACTS:CREATE`, `scim:token`). Composed with the\n * client identifier to form the Redis key:\n * `${scopeKey}:${clientId}:${windowName}`.\n * @param organizationId — optional tenant scope. Forwarded to the underlying\n * `RedisService.incrementRateLimit` so per-tenant quotas don't collide\n * across orgs. Omit for single-tenant or pre-auth policies (the resource\n * pre-flight seam can't resolve a tenant yet by construction — C-5).\n * @param clientIdOverride — optional explicit client identifier. When\n * provided, replaces `getClientIpFromRequest(req)` as the per-bucket\n * key suffix. Use whenever the caller has resolved an authenticated\n * subject identifier (token id, user id, email) so the bucket can't\n * be bypassed by IP rotation.\n *\n * @remarks Import from `@wildo-ai/saas-backend-lib`.\n */\n /** @wildo_source:part:end saas.backend.rate-limit-service.check-policy */\n public async checkPolicy(\n req: Request,\n res: Response,\n policy: RateLimitConfiguration,\n scopeKey: string,\n organizationId?: string,\n clientIdOverride?: string,\n ): Promise<void> {\n const clientId = clientIdOverride ?? getClientIpFromRequest(req);\n const { tightestActive, latestTripped } = await this.evaluatePolicyWindows(policy, `${scopeKey}:${clientId}`, organizationId);\n\n if (tightestActive) {\n // F-9 compare-and-set guard. Multiple `checkPolicy` invocations can\n // run on the same response within a single request lifecycle — the\n // canonical case is a resource operation that BOTH carries a\n // declarative `rateLimit?` on its variant (enforced by the\n // pre-flight `checkPolicyForVariant` seam) AND triggers a\n // service-level call that runs its own `checkPolicy` (e.g.\n // `INBOUND_CONTACTS.CREATE` for an anonymous user → the\n // 5/min contact-create policy fires first, then\n // `createAnonymousUser`'s 10/min session-init policy fires).\n // Without this guard the second call would overwrite the first's\n // headers and the response would advertise the LOOSER policy,\n // hiding the binding constraint from the client. Preserve the\n // tighter (smaller `remaining`) window across calls so the\n // headers always reflect the binding quota.\n const existingRemainingHeader = res.getHeader(WildoHeaderKeys.RATE_LIMIT_REMAINING);\n const existingRemainingCandidate = existingRemainingHeader === undefined\n ? undefined\n : Number(existingRemainingHeader);\n const existingRemaining = existingRemainingCandidate === undefined || Number.isFinite(existingRemainingCandidate)\n ? existingRemainingCandidate\n : undefined;\n if (existingRemaining === undefined || tightestActive.remaining < existingRemaining) {\n res.setHeader(WildoHeaderKeys.RATE_LIMIT_LIMIT, String(tightestActive.max));\n res.setHeader(WildoHeaderKeys.RATE_LIMIT_REMAINING, String(tightestActive.remaining));\n res.setHeader(WildoHeaderKeys.RATE_LIMIT_RESET, String(tightestActive.resetSeconds));\n }\n }\n\n if (latestTripped) {\n // RFC 6585 `Retry-After` header — standard cue for clients/proxies\n // that don't parse the JSON error body. Set BEFORE throw so Express's\n // error middleware (which writes the body via `res.status(429).json`)\n // preserves it on the outbound response. Kept as a literal string\n // rather than a `WildoHeaderKeys` constant because `Retry-After` is\n // an IANA-registered header, not a Wildo-custom one; callers that\n // search the codebase will find it by its canonical spelling.\n // Same F-9 compare-and-set discipline as the `X-RateLimit-*` headers\n // above: when multiple `checkPolicy` calls trip on the same\n // response, prefer the LARGER hint because all active quotas must\n // recover before the request can succeed.\n const existingRetryHeader = res.getHeader('Retry-After');\n const existingRetryCandidate = existingRetryHeader === undefined\n ? undefined\n : Number(existingRetryHeader);\n const existingRetry = existingRetryCandidate === undefined || Number.isFinite(existingRetryCandidate)\n ? existingRetryCandidate\n : undefined;\n if (existingRetry === undefined || latestTripped.retryAfterSeconds > existingRetry) {\n res.setHeader('Retry-After', String(latestTripped.retryAfterSeconds));\n }\n throw this.errorBuilder.buildError(ErrorType.RATE_LIMIT, undefined, {\n customMessageReference: ErrorCustomMessageReference.RATE_LIMIT,\n context: {\n // diagnostic (log-only)\n retryAfterSeconds: latestTripped.retryAfterSeconds,\n },\n });\n }\n }\n\n /**\n * Enforce a declared policy for a caller that has NO express request/response —\n * the non-HTTP planes that dispatch a resource operation directly. There are TWO today, and\n * they do not share a core: the MCP `tools/call` plane\n * (`McpServerBackendService.assertOperationRateLimitPolicy`, plus any future transport that\n * re-uses that core) and the agent function-tool plane\n * (`assertDeclaredOperationRateLimit` in `function-tools.backend.definitions.ts`, reached from a\n * conversational turn and therefore from A2A). An earlier revision of this sentence named only\n * the first and framed the second as \"any future transport that re-uses\n * `McpServerBackendService`\" — which the function-tool plane does not, and that framing is part\n * of why it went unnoticed. Expect further planes, and expect them to arrive from elsewhere.\n *\n * ## Why a second entry point rather than a fabricated `req`/`res`\n *\n * {@link checkPolicy} is an HTTP-seam method in two load-bearing ways: it derives the\n * counter's client identifier from the request IP, and it publishes the outcome as\n * `X-RateLimit-*` / `Retry-After` RESPONSE HEADERS. Neither exists on a JSON-RPC tool\n * dispatch — the MCP core is deliberately transport-agnostic, so it holds no `res` to\n * write headers onto, and the IP is the wrong identity axis for a credentialed agent\n * anyway (see the subject-key discussion at the call site). Handing it a stub `req`/`res`\n * would make the throttle key on the literal string the IP extractor returns for a\n * request-shaped object it was never given — i.e. ONE bucket for every agent on the\n * planet, which is worse than no enforcement because it looks enforced.\n *\n * So the WINDOW ARITHMETIC is shared (`evaluatePolicyWindows` — the AND semantics, the\n * environment relaxation, the custom-window dedupe, the latest-tripped `Retry-After`\n * pick) and only the identity + reporting halves differ. There must never be a second\n * implementation of \"what does this policy mean\"; there are legitimately two answers to\n * \"who is the client, and how do we tell them\".\n *\n * ## Failure posture: the SAME as HTTP, deliberately\n *\n * A limiter outage propagates rather than being swallowed, exactly as it does for\n * {@link checkPolicy} / {@link checkPolicyForVariant}. An AUTHORED per-endpoint policy is\n * a statement the application made about that endpoint; degrading it to \"unbounded\" on\n * one plane and to a 500 on the other would make the same declaration mean two different\n * things. (Contrast `assertExternalTurnWithinRate`, the framework-default per-principal\n * abuse throttle, which fails OPEN — nobody declared it, so it must never be the reason\n * an external endpoint stops working.)\n *\n * @param policy — the declared policy. No enforced window ⇒ no-op, zero Redis traffic.\n * @param scopeKey — author-supplied namespace, composed with `subjectKey` into the Redis key.\n * @param subjectKey — WHO is counted. The caller owns this choice; it replaces the IP\n * that {@link checkPolicy} would derive, and it must be a server-verified identity —\n * never a value the caller (or a model) supplied.\n * @param organizationId — optional tenant scope forwarded to the Redis key namespace.\n * @throws RATE_LIMIT (429) carrying `context.retryAfterSeconds`, the same envelope the\n * HTTP seam throws, so one refusal vocabulary covers both planes.\n */\n public async checkPolicyForSubject(\n policy: RateLimitConfiguration,\n scopeKey: string,\n subjectKey: string,\n organizationId?: string,\n ): Promise<void> {\n const { latestTripped } = await this.evaluatePolicyWindows(policy, `${scopeKey}:${subjectKey}`, organizationId);\n if (!latestTripped) {\n return;\n }\n throw this.errorBuilder.buildError(ErrorType.RATE_LIMIT, undefined, {\n customMessageReference: ErrorCustomMessageReference.RATE_LIMIT,\n context: {\n // Diagnostic (log-only) on the HTTP seam; on a header-less plane it is ALSO the only\n // way the transport can learn the retry hint, so it is read back off the thrown error.\n retryAfterSeconds: latestTripped.retryAfterSeconds,\n },\n });\n }\n\n /**\n * Count one request against every window a policy declares, and report the two facts\n * every caller needs: the TIGHTEST still-active window (for `X-RateLimit-*`) and the\n * LATEST tripped one (for `Retry-After`).\n *\n * Extracted from {@link checkPolicy} when {@link checkPolicyForSubject} was added, so the\n * meaning of a declared policy has exactly one implementation. Declared windows are\n * AND-ed — recovery requires EVERY exceeded window to reset, not just the shortest — which\n * is why the retry hint is the latest reset rather than the first trip.\n *\n * A policy with no enforced window yields `{}` without touching Redis (the no-policy fast\n * path the resource-variant seam relies on, since most operations declare nothing).\n *\n * @param identifier — `${scopeKey}:${clientOrSubjectId}`; the window name is appended per key.\n */\n private async evaluatePolicyWindows(\n policy: RateLimitConfiguration,\n identifier: string,\n organizationId?: string,\n ): Promise<{\n tightestActive?: { max: number; remaining: number; resetSeconds: number };\n latestTripped?: { retryAfterSeconds: number };\n }> {\n const windows = this.deriveWindows(policy);\n if (windows.length === 0) {\n return {};\n }\n\n let tightestActive: { max: number; remaining: number; resetSeconds: number } | undefined;\n let latestTripped: { retryAfterSeconds: number } | undefined;\n\n for (const window of windows) {\n const key = `${identifier}:${window.name}`;\n const count = await this.redisService.incrementRateLimit(key, window.seconds, organizationId);\n const resetSeconds = await this.resolveRateLimitTtl(key, organizationId, window.seconds);\n const remaining = Math.max(0, window.max - count);\n\n if (count > window.max) {\n if (!latestTripped || resetSeconds > latestTripped.retryAfterSeconds) {\n latestTripped = { retryAfterSeconds: resetSeconds };\n }\n }\n\n if (!tightestActive || remaining < tightestActive.remaining) {\n tightestActive = { max: window.max, remaining, resetSeconds };\n }\n }\n\n return { tightestActive, latestTripped };\n }\n\n /**\n * Pre-flight enforcement for resource operations — the consumer behind\n * the `rateLimit?` field on `API_CALL` / `API_CALL_WITH_CALLBACK` variants.\n *\n * Called from `ControllerResourceBackendService.doOperation` BEFORE\n * execution-context creation, request-data validation, and authorization\n * (C-2). At this seam the authenticated identity is unknown by\n * construction, so the client identifier MUST be the IP — there is no\n * authenticated-user alternative.\n *\n * Early-returns (zero Redis traffic) when:\n * - The variant has no `rateLimit?` policy (the common case until\n * per-endpoint policies are adopted), OR\n * - The variant is not an HTTP variant (defensive guard — `doOperation`\n * today only routes API_CALL / API_CALL_WITH_CALLBACK, but the type\n * surface accepts the broader operation union).\n *\n * Auto-derives `scopeKey = resource:${resourceIdentifier}:${operationIdentifier}`\n * — keeps resource configurations free of bespoke Redis-key strings (K-4).\n *\n * @param req — express request\n * @param res — express response (for `X-RateLimit-*` header writes)\n * @param variant — the resolved operation about to execute\n */\n public async checkPolicyForVariant(\n req: Request,\n res: Response,\n variant: {\n readonly variantType: ResourceOperationVariantType;\n readonly resourceIdentifier: ResourceType;\n // The resolved operation type uses generic enum constraints\n // (`TCustomOperationEnum | TCoreOperationEnum`, both bounded by\n // `Record<string, string>`); at runtime the value is always a string\n // (the enum's value, not the enum object). `unknown` keeps the\n // structural surface broad enough to accept any operation variant\n // shape; the value is stringified for the Redis scope key.\n readonly operationIdentifier: unknown;\n readonly rateLimit?: RateLimitConfiguration;\n },\n ): Promise<void> {\n if (!variant.rateLimit) {\n return;\n }\n if (\n variant.variantType !== ResourceOperationVariantType.API_CALL\n && variant.variantType !== ResourceOperationVariantType.API_CALL_WITH_CALLBACK\n ) {\n return;\n }\n\n const scopeKey = `resource:${String(variant.resourceIdentifier)}:${String(variant.operationIdentifier)}`;\n await this.checkPolicy(req, res, variant.rateLimit, scopeKey);\n }\n\n /**\n * Build the enforced-window list from a declared policy. Includes\n * `customWindows` after the canonical three so AND-semantics treat\n * them identically to the named windows (D-3, Option A — custom\n * windows participate in the same `tightestActive` / `latestTripped`\n * picks as the canonical ones).\n *\n * Custom-window dedupe (F-16, PR 7-D-3 review fix): when an author\n * accidentally declares two `customWindows` entries with the same\n * `windowSeconds` (e.g. `[{ rpw: 3, ws: 300 }, { rpw: 5, ws: 300 }]`),\n * both would derive the SAME Redis key (`<scope>:<id>:custom:300s`)\n * and a single client request would silently double-increment the\n * counter, halving the effective cap. We resolve the misconfig\n * deterministically: keep the entry with the SMALLEST `requestsPerWindow`\n * (most restrictive interpretation = safest for the protected resource)\n * and emit a `console.warn` so authors see the misconfig in logs. Any\n * canonical-window collisions (e.g. `{ requestsPerMinute: 5,\n * customWindows: [{ rpw: 3, ws: 60 }] }`) are NOT deduped — they\n * derive different key suffixes (`:minute` vs `:custom:60s`) and\n * coexist correctly; the JSDoc on `RateLimitConfigurationSchema`\n * steers authors away from this awkward shape, but it isn't broken.\n */\n private deriveWindows(policy: RateLimitConfiguration): PolicyWindow[] {\n const multiplier = this.resolveWindowMultiplier();\n const windows: PolicyWindow[] = [];\n if (policy.requestsPerMinute !== undefined) {\n windows.push({ name: 'minute', max: policy.requestsPerMinute * multiplier, seconds: 60 });\n }\n if (policy.requestsPerHour !== undefined) {\n windows.push({ name: 'hour', max: policy.requestsPerHour * multiplier, seconds: 3600 });\n }\n if (policy.requestsPerDay !== undefined) {\n windows.push({ name: 'day', max: policy.requestsPerDay * multiplier, seconds: 86400 });\n }\n if (policy.customWindows && policy.customWindows.length > 0) {\n // Map by `windowSeconds`; on collision keep the smallest `max`\n // (most restrictive) and warn. Insertion order is preserved by\n // `Map`, so the canonical-then-custom emit order downstream is\n // unchanged for non-colliding cases.\n const byWindowSeconds = new Map<number, { max: number; seconds: number }>();\n for (const custom of policy.customWindows) {\n const existing = byWindowSeconds.get(custom.windowSeconds);\n if (existing === undefined) {\n byWindowSeconds.set(custom.windowSeconds, {\n max: custom.requestsPerWindow,\n seconds: custom.windowSeconds,\n });\n } else if (custom.requestsPerWindow < existing.max) {\n // eslint-disable-next-line no-console\n console.warn(\n '[rate-limit] Duplicate customWindows.windowSeconds detected; keeping the smaller (more restrictive) requestsPerWindow.',\n { windowSeconds: custom.windowSeconds, kept: custom.requestsPerWindow, dropped: existing.max },\n );\n byWindowSeconds.set(custom.windowSeconds, {\n max: custom.requestsPerWindow,\n seconds: custom.windowSeconds,\n });\n } else {\n // eslint-disable-next-line no-console\n console.warn(\n '[rate-limit] Duplicate customWindows.windowSeconds detected; keeping the smaller (more restrictive) requestsPerWindow.',\n { windowSeconds: custom.windowSeconds, kept: existing.max, dropped: custom.requestsPerWindow },\n );\n }\n }\n for (const [, custom] of byWindowSeconds) {\n windows.push({\n name: `custom:${custom.seconds}s`,\n max: custom.max * multiplier,\n seconds: custom.seconds,\n });\n }\n }\n return windows;\n }\n\n /**\n * Non-production window-max relaxation for every policy this service enforces\n * (register, login, MFA, magic-link, SCIM, marketing public endpoints, resource\n * `rateLimit?` variants — every `checkPolicy` / `checkPolicyForVariant` caller,\n * K-3/K-4).\n *\n * The branch itself lives in\n * {@link resolveRateLimitEnvironmentMultiplier} — this service is one of SIX\n * abuse-throttle sites in the engine and used to own a private copy of the\n * constant, which is exactly why the other five never got the relaxation. Do not\n * re-inline it here.\n */\n private resolveWindowMultiplier(): number {\n return resolveRateLimitEnvironmentMultiplier(this.appConfigService.applicationEnv);\n }\n\n private async resolveRateLimitTtl(\n identifier: string,\n organizationId: string | undefined,\n fallbackSeconds: number,\n ): Promise<number> {\n const getRateLimitTtl = (this.redisService as RedisService & {\n getRateLimitTtl?: (identifier: string, organizationId?: string) => Promise<number>;\n }).getRateLimitTtl;\n if (!getRateLimitTtl) {\n return fallbackSeconds;\n }\n\n try {\n const ttl = await getRateLimitTtl.call(this.redisService, identifier, organizationId);\n return ttl >= 0 ? ttl : fallbackSeconds;\n } catch {\n return fallbackSeconds;\n }\n }\n}\n"]}
|
|
@@ -142,6 +142,11 @@ export declare function projectWildoBackendErrorLogFields(error: WildoError_Back
|
|
|
142
142
|
* Spread it into a log context:
|
|
143
143
|
* `logger.warn(msg, { ...ctx, ...projectCaughtErrorLogFields(error) })`.
|
|
144
144
|
*
|
|
145
|
+
* Choosing `warn` there is safe BECAUSE of the level floor this projection attaches: if the swallowed
|
|
146
|
+
* value turns out to be a server fault, `LoggerService` emits the record at `error` regardless, and
|
|
147
|
+
* records what the call site asked for under `promotedFromLevel`. Pick the level that describes the
|
|
148
|
+
* expected case; the floor covers the unexpected one.
|
|
149
|
+
*
|
|
145
150
|
* For the same reason, never put a `ZodError`'s own `.message` in a log context
|
|
146
151
|
* — in Zod 4 it IS a `JSON.stringify` blob, so it hits the same double-escaping.
|
|
147
152
|
* Log the structured issues, and use `summarizeZodIssues` from
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-log-level-classification.backend.utils.d.ts","sourceRoot":"","sources":["../../../../../src/errors/utils/error-log-level-classification.backend.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"error-log-level-classification.backend.utils.d.ts","sourceRoot":"","sources":["../../../../../src/errors/utils/error-log-level-classification.backend.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAQpG;;;;;;;;;;GAUG;AACH,oBAAY,uBAAuB;IACjC,KAAK,UAAU;IACf,IAAI,SAAS;IACb,IAAI,SAAS;IACb,KAAK,UAAU;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,oCAAoC,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAEvF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,kBAAkB,GAAG,uBAAuB,CAsBlG;AAED;;;;GAIG;AACH,wBAAgB,oCAAoC,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAE5F;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWpG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2BnF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQ1D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKlE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,kBAAkB,EACzB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACpC,uBAAuB,CAqCzB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ErrorSeverity, isWildoBackendError } from '@wildo-ai/saas-models';
|
|
2
2
|
import { isExpiredJwtVerificationFailure } from '../../security/jwt/utils/jwt-verification-error-classification.backend.utils.js';
|
|
3
3
|
import { normalizeLogContext, normalizeLogValue, } from '../../monitoring/logger/utils/log-value-normalization.backend.utils.js';
|
|
4
|
+
import { LOG_SEVERITY_FLOOR_FIELD } from '../../monitoring/logger/utils/log-severity-floor.backend.utils.js';
|
|
4
5
|
/**
|
|
5
6
|
* Backend log severity for an error at a logging boundary.
|
|
6
7
|
*
|
|
@@ -166,6 +167,11 @@ export function projectWildoBackendErrorLogFields(error) {
|
|
|
166
167
|
* Spread it into a log context:
|
|
167
168
|
* `logger.warn(msg, { ...ctx, ...projectCaughtErrorLogFields(error) })`.
|
|
168
169
|
*
|
|
170
|
+
* Choosing `warn` there is safe BECAUSE of the level floor this projection attaches: if the swallowed
|
|
171
|
+
* value turns out to be a server fault, `LoggerService` emits the record at `error` regardless, and
|
|
172
|
+
* records what the call site asked for under `promotedFromLevel`. Pick the level that describes the
|
|
173
|
+
* expected case; the floor covers the unexpected one.
|
|
174
|
+
*
|
|
169
175
|
* For the same reason, never put a `ZodError`'s own `.message` in a log context
|
|
170
176
|
* — in Zod 4 it IS a `JSON.stringify` blob, so it hits the same double-escaping.
|
|
171
177
|
* Log the structured issues, and use `summarizeZodIssues` from
|
|
@@ -176,6 +182,25 @@ export function projectCaughtErrorLogFields(error) {
|
|
|
176
182
|
return normalizeLogContext({
|
|
177
183
|
...projectWildoBackendErrorLogFields(error),
|
|
178
184
|
...(typeof error.stack === 'string' ? { stack: error.stack } : {}),
|
|
185
|
+
/*
|
|
186
|
+
* The LEVEL this record must not fall below, carried so the sink can apply it.
|
|
187
|
+
*
|
|
188
|
+
* This projection is the catch-path one, and a catch path chooses its level BY HAND — 213
|
|
189
|
+
* emissions below `error` across 86 files, measured 2026-09-09 — which is exactly where
|
|
190
|
+
* `classifyBackendErrorLogSeverity` gets bypassed. A swallowed DATABASE or INTERNAL failure was
|
|
191
|
+
* emitted at `warn` while these very fields said `severity: CRITICAL`: greppable, and invisible
|
|
192
|
+
* to an alert keyed on level.
|
|
193
|
+
*
|
|
194
|
+
* Carrying the classifier's own answer adds no new judgement — every "stays at warn" case it
|
|
195
|
+
* documents is preserved — and `resolveEmittedLogLevel` only ever RAISES, so a call site that
|
|
196
|
+
* deliberately logs louder keeps its choice.
|
|
197
|
+
*
|
|
198
|
+
* Deliberately NOT added to `projectWildoBackendErrorLogFields`: both of its consumers already
|
|
199
|
+
* resolve the level on purpose (`logWildoBackendErrorAtClassifiedSeverity` emits AT the
|
|
200
|
+
* classification; a dead-lettered job owns a louder one), so a floor there would be a field that
|
|
201
|
+
* can never change an outcome.
|
|
202
|
+
*/
|
|
203
|
+
[LOG_SEVERITY_FLOOR_FIELD]: classifyBackendErrorLogSeverity(error),
|
|
179
204
|
});
|
|
180
205
|
}
|
|
181
206
|
return { error: normalizeLogValue(error) };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-log-level-classification.backend.utils.js","sourceRoot":"","sources":["../../../../../src/errors/utils/error-log-level-classification.backend.utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { ErrorSeverity, isWildoBackendError, type WildoError_Backend } from '@wildo-ai/saas-models';\nimport { isExpiredJwtVerificationFailure } from '~wildo-backend-lib/security/jwt/utils/jwt-verification-error-classification.backend.utils';\nimport {\n normalizeLogContext,\n normalizeLogValue,\n} from '~wildo-backend-lib/monitoring/logger/utils/log-value-normalization.backend.utils';\n\n/**\n * Backend log severity for an error at a logging boundary.\n *\n * Deliberately NOT the same axis as {@link ErrorSeverity} (the business/impact\n * severity carried on the error). This is the *operational* severity: \"does a\n * human operator need to look at this line?\" — the only question a log level\n * should answer.\n *\n * Values match {@link LevelledLogger} method names so dispatch is a direct\n * lookup, not a translation table.\n */\nexport enum BackendErrorLogSeverity {\n DEBUG = 'debug',\n INFO = 'info',\n WARN = 'warn',\n ERROR = 'error',\n}\n\n/**\n * Minimal structural logger contract the dispatch helper needs.\n *\n * Kept structural (not a dependency on the concrete `LoggerService`) so the\n * classification/dispatch layer stays free of DI wiring and is trivially\n * unit-testable with a stub. `LoggerService` satisfies this shape.\n */\nexport interface LevelledLogger {\n debug(message: string, context?: Record<string, unknown>): void;\n info(message: string, context?: Record<string, unknown>): void;\n warn(message: string, context?: Record<string, unknown>): void;\n error(message: string, errorOrContext?: unknown, context?: Record<string, unknown>): void;\n}\n\n/**\n * Expected, self-correcting client conditions that must never be logged as\n * faults.\n *\n * The canonical case: an **expired access token**. This is not an error — it is\n * a normal step in the token lifecycle. The frontend receives the 401, silently\n * calls `/refresh`, and retries. Logging it at `error` (with a stack trace, per\n * request, per expired session) is a category mistake that floods production\n * logs with non-actionable noise and inflates log-ingestion cost.\n *\n * This is the extension point for other genuinely self-healing conditions.\n * Add them here so every logging boundary agrees on what counts as \"expected\" —\n * do NOT special-case them at individual call sites.\n *\n * **Admission rule — both must hold before folding a condition in:**\n * 1. The client recovers with **zero human involvement** (transparent, no\n * banner, no user decision).\n * 2. The **retried request succeeds unchanged** — same payload, no lost work.\n *\n * Expired token is the textbook case (silent `/refresh` → identical retry\n * works). Deliberately EXCLUDED, with reasons, so nobody re-litigates them:\n * - **Malformed / bad-signature token** — a potential security signal; a spike\n * is credential-stuffing. Stays at `warn`.\n * - **`VERSION_CONFLICT`** (optimistic concurrency) — fails BOTH tests: it\n * surfaces a user-facing conflict banner (a human must reconcile) and a blind\n * retry would clobber the divergent remote state. It is a real concurrent-\n * edit event and a useful hot-row-contention signal. Stays at `warn`.\n * Only a future *transparent auto-merge* retry (no user involvement) would\n * qualify — the current user-mediated flow does not.\n */\nexport function isExpectedSelfHealingClientCondition(error: WildoError_Backend): boolean {\n return isExpiredJwtVerificationFailure(error);\n}\n\n/**\n * Map a backend error to the operational log severity it deserves.\n *\n * Big-tech observability practice: **log level reflects operator action, not\n * code path.** An exception used as control flow (expired token, validation\n * rejection, not-found) is not an `ERROR` just because it unwound the stack.\n *\n * The mapping is driven by the error's own declared contract — `statusCode` and\n * business {@link ErrorSeverity} from `ERROR_DEFINITIONS` — so new error types\n * inherit correct log levels for free:\n *\n * - **Expected self-healing client conditions** → `debug` (expired token, etc.).\n * Never a fault; keep them out of the error stream entirely — track via\n * metrics/counters and alert on *rate*, not individual events.\n * - **Server faults (5xx)** → `error`. A human must look (INTERNAL, DATABASE,\n * EXTERNAL_SERVICE, CONFIGURATION, UNKNOWN, uncaught/unhandled).\n * - **4xx client errors**, by business severity:\n * - `LOW` → `debug` — routine client mistakes (VALIDATION, NOT_FOUND,\n * feature-gating). The caller sent a bad request; that is not our fault.\n * - `MEDIUM` → `warn` — worth aggregate visibility but not a fault\n * (AUTHENTICATION/AUTHORIZATION failures, CONFLICT, RATE_LIMIT,\n * BUSINESS_RULE). A *spike* is the signal (e.g. credential stuffing) — the\n * rate alert fires, not the individual line.\n * - `HIGH`+ on a 4xx is unusual → `error`, so it is surfaced rather than\n * silently swallowed.\n */\nexport function classifyBackendErrorLogSeverity(error: WildoError_Backend): BackendErrorLogSeverity {\n if (isExpectedSelfHealingClientCondition(error)) {\n return BackendErrorLogSeverity.DEBUG;\n }\n\n const statusCode = typeof error.statusCode === 'number' ? error.statusCode : 500;\n\n // Server faults always warrant an operator's attention.\n if (statusCode >= 500) {\n return BackendErrorLogSeverity.ERROR;\n }\n\n // Remaining 4xx: the client's request was wrong. Business severity decides\n // how loud we are about it.\n switch (error.severity) {\n case ErrorSeverity.LOW:\n return BackendErrorLogSeverity.DEBUG;\n case ErrorSeverity.MEDIUM:\n return BackendErrorLogSeverity.WARN;\n default:\n return BackendErrorLogSeverity.ERROR;\n }\n}\n\n/**\n * A stack trace exists to locate an *unexpected* fault. Expected control-flow\n * exceptions (expired token, validation) have no fault to locate — the stack is\n * pure noise and, at scale, real ingestion cost. Attach it only for `error`.\n */\nexport function backendErrorLogSeverityIncludesStack(level: BackendErrorLogSeverity): boolean {\n return level === BackendErrorLogSeverity.ERROR;\n}\n\n/**\n * Canonical projection of a {@link WildoError_Backend} into flat, structured\n * log fields — the single source of truth for \"what error fields belong on a\n * log line\".\n *\n * Every field becomes a top-level, individually-queryable key (never a\n * pre-rendered blob). Optional fields are omitted when absent so log records\n * stay free of null keys. The stack is deliberately NOT included here: whether\n * to attach it is a per-boundary decision driven by the emitted level (see\n * {@link backendErrorLogSeverityIncludesStack}), so each boundary layers it on\n * top of this projection when appropriate.\n *\n * Used by {@link logWildoBackendErrorAtClassifiedSeverity} (HTTP, batch,\n * websocket-auth boundaries) AND directly by boundaries that own their own\n * operational severity and must NOT adopt the request-style classification —\n * e.g. a permanently dead-lettered queue job is operationally an `error`\n * regardless of the underlying error's business severity, so it keeps its\n * explicit level and merely reuses this projection to restore the full detail.\n */\nexport function projectWildoBackendErrorLogFields(error: WildoError_Backend): Record<string, unknown> {\n return {\n errorType: error.type,\n severity: error.severity,\n statusCode: error.statusCode,\n customMessageReference: error.customMessageReference,\n ...(error.operationPathKey ? { operationPath: error.operationPathKey } : {}),\n ...(error.correlationId ? { correlationId: error.correlationId } : {}),\n ...(error.backendActions?.length ? { backendActions: error.backendActions } : {}),\n ...(error.context ? { context: error.context } : {}),\n };\n}\n\n/**\n * Project ANY caught value into flat, structured, individually-queryable log\n * fields — the `catch (error)` counterpart to {@link projectWildoBackendErrorLogFields}.\n *\n * A `catch` binding is `unknown`, and the pervasive footgun is\n * `error instanceof Error ? error.message : JSON.stringify(error)`. A\n * {@link WildoError_Backend} is a **plain object, NOT an `Error` instance**, so\n * `instanceof Error` is `false` and every structured backend failure falls to the\n * `else` branch — silently collapsing to `String(error)` (`'[object Object]'`) or,\n * when the fallback is `JSON.stringify`, to a **doubly-escaped JSON string** crammed\n * under a single `error` key (Pino re-escapes the already-serialized blob → the fields\n * become un-greppable). This helper resolves the `WildoError_Backend | Error | unknown`\n * trichotomy once, emitting raw JSON in every case:\n *\n * - {@link WildoError_Backend} → the canonical flat projection (top-level queryable\n * keys) plus its carried `stack`. A best-effort catch swallows an *unexpected*\n * failure, so the stack (the fault locator) is always attached here — unlike the\n * classified HTTP boundary ({@link logWildoBackendErrorAtClassifiedSeverity}), which\n * gates the stack on the emitted level.\n * - native `Error` → a structured error object including non-enumerable\n * `name`/`message`/`stack`, `cause`, and extension fields such as Zod\n * `issues`.\n * - anything else → its JSON-native value under `error`; objects remain\n * objects, primitives retain their type, and cyclic references become an\n * explicit `[Circular]` marker.\n *\n * Spread it into a log context:\n * `logger.warn(msg, { ...ctx, ...projectCaughtErrorLogFields(error) })`.\n *\n * For the same reason, never put a `ZodError`'s own `.message` in a log context\n * — in Zod 4 it IS a `JSON.stringify` blob, so it hits the same double-escaping.\n * Log the structured issues, and use `summarizeZodIssues` from\n * `@wildo-ai/saas-models` when a human-readable one-liner is wanted alongside.\n */\nexport function projectCaughtErrorLogFields(error: unknown): Record<string, unknown> {\n if (isWildoBackendError(error)) {\n return normalizeLogContext({\n ...projectWildoBackendErrorLogFields(error),\n ...(typeof error.stack === 'string' ? { stack: error.stack } : {}),\n });\n }\n return { error: normalizeLogValue(error) };\n}\n\n/**\n * One-line human-readable description of ANY caught value.\n *\n * The string counterpart to {@link projectCaughtErrorLogFields}, for the narrow\n * cases where a caught error must become a plain `string` rather than structured\n * log fields — a persisted `failureReason` column, a batch summary's `error`\n * field, a DLQ record. Prefer the structured projection for LOGGING; reach for\n * this only when the destination's contract is genuinely `string`.\n *\n * It exists because the obvious inline form,\n * `err instanceof Error ? err.message : String(err)`, is wrong for the engine's\n * own error type: a {@link WildoError_Backend} is a plain object, NOT an `Error`,\n * so it takes the `String(...)` branch and every structured failure is persisted\n * as the literal `'[object Object]'` — unreadable, and identical for every\n * distinct fault.\n *\n * Resolution order for a `WildoError_Backend`: the human `context.message` when\n * present, else the stable `customMessageReference` code.\n */\nexport function describeCaughtError(error: unknown): string {\n if (isWildoBackendError(error)) {\n const detail = error.context?.message;\n return typeof detail === 'string' && detail.length > 0\n ? detail\n : String(error.customMessageReference);\n }\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * `\"<kind>: <message>\"` for ANY caught value — {@link describeCaughtError} for the\n * destinations that also want to know WHAT KIND of thing failed, not only why.\n *\n * Reach for this instead of the inline `err instanceof Error ? \\`${err.name}: ${err.message}\\`\n * : String(err)` wherever the kind is load-bearing rather than decorative:\n *\n * - a **failure DIGEST / dedup key** — collapsing every distinct fault into one bucket\n * is worse than an unreadable message, because the bucket is then wrong for every\n * subsequent decision keyed off it;\n * - a **persisted terminal diagnostic** an operator reads without the log beside it;\n * - a **classifier** that branches on the fault's identity.\n *\n * A {@link WildoError_Backend} has no `name`: its kind is the pair\n * `type` + `customMessageReference`, which is what this renders. Everything else falls\n * through to the native `name`, so the output shape is unchanged for a real `Error`.\n */\nexport function describeCaughtErrorWithKind(error: unknown): string {\n if (isWildoBackendError(error)) {\n return `${error.type}/${error.customMessageReference}: ${describeCaughtError(error)}`;\n }\n return error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n}\n\n/**\n * Classify a backend error and emit exactly one structured log line at the\n * appropriate operational severity.\n *\n * Use this at every backend error-logging boundary instead of hardcoding\n * `logger.error(...)`. It guarantees a single, consistent treatment: expected\n * client conditions stay at `debug`, server faults stay at `error` (with\n * stack), and everything in between is graded by declared severity.\n *\n * @returns the level the line was emitted at (useful for tests / metrics hooks).\n */\nexport function logWildoBackendErrorAtClassifiedSeverity(\n logger: LevelledLogger,\n message: string,\n error: WildoError_Backend,\n context: Record<string, unknown> = {},\n): BackendErrorLogSeverity {\n const level = classifyBackendErrorLogSeverity(error);\n\n // Standard error fields come from the canonical projection; the caller's\n // `context` carries only boundary-specific extras (method/path, socketId,\n // jobId, …) and wins on any key overlap.\n const mergedContext: Record<string, unknown> = {\n ...projectWildoBackendErrorLogFields(error),\n ...context,\n };\n\n const finalContext: Record<string, unknown> =\n backendErrorLogSeverityIncludesStack(level) && typeof error.stack === 'string'\n ? { ...mergedContext, stack: error.stack }\n : mergedContext;\n\n // Extension point: this is the natural site to increment an\n // `auth_token_verification_total{result=\"expired\"}`-style counter (the\n // RECORD_METRICS backend action) so alerting keys off aggregate rate rather\n // than individual log lines. Wire a metrics sink here when one is available.\n\n switch (level) {\n case BackendErrorLogSeverity.DEBUG:\n logger.debug(message, finalContext);\n break;\n case BackendErrorLogSeverity.INFO:\n logger.info(message, finalContext);\n break;\n case BackendErrorLogSeverity.WARN:\n logger.warn(message, finalContext);\n break;\n case BackendErrorLogSeverity.ERROR:\n logger.error(message, finalContext);\n break;\n }\n\n return level;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"error-log-level-classification.backend.utils.js","sourceRoot":"","sources":["../../../../../src/errors/utils/error-log-level-classification.backend.utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { ErrorSeverity, isWildoBackendError, type WildoError_Backend } from '@wildo-ai/saas-models';\nimport { isExpiredJwtVerificationFailure } from '~wildo-backend-lib/security/jwt/utils/jwt-verification-error-classification.backend.utils';\nimport {\n normalizeLogContext,\n normalizeLogValue,\n} from '~wildo-backend-lib/monitoring/logger/utils/log-value-normalization.backend.utils';\nimport { LOG_SEVERITY_FLOOR_FIELD } from '~wildo-backend-lib/monitoring/logger/utils/log-severity-floor.backend.utils';\n\n/**\n * Backend log severity for an error at a logging boundary.\n *\n * Deliberately NOT the same axis as {@link ErrorSeverity} (the business/impact\n * severity carried on the error). This is the *operational* severity: \"does a\n * human operator need to look at this line?\" — the only question a log level\n * should answer.\n *\n * Values match {@link LevelledLogger} method names so dispatch is a direct\n * lookup, not a translation table.\n */\nexport enum BackendErrorLogSeverity {\n DEBUG = 'debug',\n INFO = 'info',\n WARN = 'warn',\n ERROR = 'error',\n}\n\n/**\n * Minimal structural logger contract the dispatch helper needs.\n *\n * Kept structural (not a dependency on the concrete `LoggerService`) so the\n * classification/dispatch layer stays free of DI wiring and is trivially\n * unit-testable with a stub. `LoggerService` satisfies this shape.\n */\nexport interface LevelledLogger {\n debug(message: string, context?: Record<string, unknown>): void;\n info(message: string, context?: Record<string, unknown>): void;\n warn(message: string, context?: Record<string, unknown>): void;\n error(message: string, errorOrContext?: unknown, context?: Record<string, unknown>): void;\n}\n\n/**\n * Expected, self-correcting client conditions that must never be logged as\n * faults.\n *\n * The canonical case: an **expired access token**. This is not an error — it is\n * a normal step in the token lifecycle. The frontend receives the 401, silently\n * calls `/refresh`, and retries. Logging it at `error` (with a stack trace, per\n * request, per expired session) is a category mistake that floods production\n * logs with non-actionable noise and inflates log-ingestion cost.\n *\n * This is the extension point for other genuinely self-healing conditions.\n * Add them here so every logging boundary agrees on what counts as \"expected\" —\n * do NOT special-case them at individual call sites.\n *\n * **Admission rule — both must hold before folding a condition in:**\n * 1. The client recovers with **zero human involvement** (transparent, no\n * banner, no user decision).\n * 2. The **retried request succeeds unchanged** — same payload, no lost work.\n *\n * Expired token is the textbook case (silent `/refresh` → identical retry\n * works). Deliberately EXCLUDED, with reasons, so nobody re-litigates them:\n * - **Malformed / bad-signature token** — a potential security signal; a spike\n * is credential-stuffing. Stays at `warn`.\n * - **`VERSION_CONFLICT`** (optimistic concurrency) — fails BOTH tests: it\n * surfaces a user-facing conflict banner (a human must reconcile) and a blind\n * retry would clobber the divergent remote state. It is a real concurrent-\n * edit event and a useful hot-row-contention signal. Stays at `warn`.\n * Only a future *transparent auto-merge* retry (no user involvement) would\n * qualify — the current user-mediated flow does not.\n */\nexport function isExpectedSelfHealingClientCondition(error: WildoError_Backend): boolean {\n return isExpiredJwtVerificationFailure(error);\n}\n\n/**\n * Map a backend error to the operational log severity it deserves.\n *\n * Big-tech observability practice: **log level reflects operator action, not\n * code path.** An exception used as control flow (expired token, validation\n * rejection, not-found) is not an `ERROR` just because it unwound the stack.\n *\n * The mapping is driven by the error's own declared contract — `statusCode` and\n * business {@link ErrorSeverity} from `ERROR_DEFINITIONS` — so new error types\n * inherit correct log levels for free:\n *\n * - **Expected self-healing client conditions** → `debug` (expired token, etc.).\n * Never a fault; keep them out of the error stream entirely — track via\n * metrics/counters and alert on *rate*, not individual events.\n * - **Server faults (5xx)** → `error`. A human must look (INTERNAL, DATABASE,\n * EXTERNAL_SERVICE, CONFIGURATION, UNKNOWN, uncaught/unhandled).\n * - **4xx client errors**, by business severity:\n * - `LOW` → `debug` — routine client mistakes (VALIDATION, NOT_FOUND,\n * feature-gating). The caller sent a bad request; that is not our fault.\n * - `MEDIUM` → `warn` — worth aggregate visibility but not a fault\n * (AUTHENTICATION/AUTHORIZATION failures, CONFLICT, RATE_LIMIT,\n * BUSINESS_RULE). A *spike* is the signal (e.g. credential stuffing) — the\n * rate alert fires, not the individual line.\n * - `HIGH`+ on a 4xx is unusual → `error`, so it is surfaced rather than\n * silently swallowed.\n */\nexport function classifyBackendErrorLogSeverity(error: WildoError_Backend): BackendErrorLogSeverity {\n if (isExpectedSelfHealingClientCondition(error)) {\n return BackendErrorLogSeverity.DEBUG;\n }\n\n const statusCode = typeof error.statusCode === 'number' ? error.statusCode : 500;\n\n // Server faults always warrant an operator's attention.\n if (statusCode >= 500) {\n return BackendErrorLogSeverity.ERROR;\n }\n\n // Remaining 4xx: the client's request was wrong. Business severity decides\n // how loud we are about it.\n switch (error.severity) {\n case ErrorSeverity.LOW:\n return BackendErrorLogSeverity.DEBUG;\n case ErrorSeverity.MEDIUM:\n return BackendErrorLogSeverity.WARN;\n default:\n return BackendErrorLogSeverity.ERROR;\n }\n}\n\n/**\n * A stack trace exists to locate an *unexpected* fault. Expected control-flow\n * exceptions (expired token, validation) have no fault to locate — the stack is\n * pure noise and, at scale, real ingestion cost. Attach it only for `error`.\n */\nexport function backendErrorLogSeverityIncludesStack(level: BackendErrorLogSeverity): boolean {\n return level === BackendErrorLogSeverity.ERROR;\n}\n\n/**\n * Canonical projection of a {@link WildoError_Backend} into flat, structured\n * log fields — the single source of truth for \"what error fields belong on a\n * log line\".\n *\n * Every field becomes a top-level, individually-queryable key (never a\n * pre-rendered blob). Optional fields are omitted when absent so log records\n * stay free of null keys. The stack is deliberately NOT included here: whether\n * to attach it is a per-boundary decision driven by the emitted level (see\n * {@link backendErrorLogSeverityIncludesStack}), so each boundary layers it on\n * top of this projection when appropriate.\n *\n * Used by {@link logWildoBackendErrorAtClassifiedSeverity} (HTTP, batch,\n * websocket-auth boundaries) AND directly by boundaries that own their own\n * operational severity and must NOT adopt the request-style classification —\n * e.g. a permanently dead-lettered queue job is operationally an `error`\n * regardless of the underlying error's business severity, so it keeps its\n * explicit level and merely reuses this projection to restore the full detail.\n */\nexport function projectWildoBackendErrorLogFields(error: WildoError_Backend): Record<string, unknown> {\n return {\n errorType: error.type,\n severity: error.severity,\n statusCode: error.statusCode,\n customMessageReference: error.customMessageReference,\n ...(error.operationPathKey ? { operationPath: error.operationPathKey } : {}),\n ...(error.correlationId ? { correlationId: error.correlationId } : {}),\n ...(error.backendActions?.length ? { backendActions: error.backendActions } : {}),\n ...(error.context ? { context: error.context } : {}),\n };\n}\n\n/**\n * Project ANY caught value into flat, structured, individually-queryable log\n * fields — the `catch (error)` counterpart to {@link projectWildoBackendErrorLogFields}.\n *\n * A `catch` binding is `unknown`, and the pervasive footgun is\n * `error instanceof Error ? error.message : JSON.stringify(error)`. A\n * {@link WildoError_Backend} is a **plain object, NOT an `Error` instance**, so\n * `instanceof Error` is `false` and every structured backend failure falls to the\n * `else` branch — silently collapsing to `String(error)` (`'[object Object]'`) or,\n * when the fallback is `JSON.stringify`, to a **doubly-escaped JSON string** crammed\n * under a single `error` key (Pino re-escapes the already-serialized blob → the fields\n * become un-greppable). This helper resolves the `WildoError_Backend | Error | unknown`\n * trichotomy once, emitting raw JSON in every case:\n *\n * - {@link WildoError_Backend} → the canonical flat projection (top-level queryable\n * keys) plus its carried `stack`. A best-effort catch swallows an *unexpected*\n * failure, so the stack (the fault locator) is always attached here — unlike the\n * classified HTTP boundary ({@link logWildoBackendErrorAtClassifiedSeverity}), which\n * gates the stack on the emitted level.\n * - native `Error` → a structured error object including non-enumerable\n * `name`/`message`/`stack`, `cause`, and extension fields such as Zod\n * `issues`.\n * - anything else → its JSON-native value under `error`; objects remain\n * objects, primitives retain their type, and cyclic references become an\n * explicit `[Circular]` marker.\n *\n * Spread it into a log context:\n * `logger.warn(msg, { ...ctx, ...projectCaughtErrorLogFields(error) })`.\n *\n * Choosing `warn` there is safe BECAUSE of the level floor this projection attaches: if the swallowed\n * value turns out to be a server fault, `LoggerService` emits the record at `error` regardless, and\n * records what the call site asked for under `promotedFromLevel`. Pick the level that describes the\n * expected case; the floor covers the unexpected one.\n *\n * For the same reason, never put a `ZodError`'s own `.message` in a log context\n * — in Zod 4 it IS a `JSON.stringify` blob, so it hits the same double-escaping.\n * Log the structured issues, and use `summarizeZodIssues` from\n * `@wildo-ai/saas-models` when a human-readable one-liner is wanted alongside.\n */\nexport function projectCaughtErrorLogFields(error: unknown): Record<string, unknown> {\n if (isWildoBackendError(error)) {\n return normalizeLogContext({\n ...projectWildoBackendErrorLogFields(error),\n ...(typeof error.stack === 'string' ? { stack: error.stack } : {}),\n /*\n * The LEVEL this record must not fall below, carried so the sink can apply it.\n *\n * This projection is the catch-path one, and a catch path chooses its level BY HAND — 213\n * emissions below `error` across 86 files, measured 2026-09-09 — which is exactly where\n * `classifyBackendErrorLogSeverity` gets bypassed. A swallowed DATABASE or INTERNAL failure was\n * emitted at `warn` while these very fields said `severity: CRITICAL`: greppable, and invisible\n * to an alert keyed on level.\n *\n * Carrying the classifier's own answer adds no new judgement — every \"stays at warn\" case it\n * documents is preserved — and `resolveEmittedLogLevel` only ever RAISES, so a call site that\n * deliberately logs louder keeps its choice.\n *\n * Deliberately NOT added to `projectWildoBackendErrorLogFields`: both of its consumers already\n * resolve the level on purpose (`logWildoBackendErrorAtClassifiedSeverity` emits AT the\n * classification; a dead-lettered job owns a louder one), so a floor there would be a field that\n * can never change an outcome.\n */\n [LOG_SEVERITY_FLOOR_FIELD]: classifyBackendErrorLogSeverity(error),\n });\n }\n return { error: normalizeLogValue(error) };\n}\n\n/**\n * One-line human-readable description of ANY caught value.\n *\n * The string counterpart to {@link projectCaughtErrorLogFields}, for the narrow\n * cases where a caught error must become a plain `string` rather than structured\n * log fields — a persisted `failureReason` column, a batch summary's `error`\n * field, a DLQ record. Prefer the structured projection for LOGGING; reach for\n * this only when the destination's contract is genuinely `string`.\n *\n * It exists because the obvious inline form,\n * `err instanceof Error ? err.message : String(err)`, is wrong for the engine's\n * own error type: a {@link WildoError_Backend} is a plain object, NOT an `Error`,\n * so it takes the `String(...)` branch and every structured failure is persisted\n * as the literal `'[object Object]'` — unreadable, and identical for every\n * distinct fault.\n *\n * Resolution order for a `WildoError_Backend`: the human `context.message` when\n * present, else the stable `customMessageReference` code.\n */\nexport function describeCaughtError(error: unknown): string {\n if (isWildoBackendError(error)) {\n const detail = error.context?.message;\n return typeof detail === 'string' && detail.length > 0\n ? detail\n : String(error.customMessageReference);\n }\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * `\"<kind>: <message>\"` for ANY caught value — {@link describeCaughtError} for the\n * destinations that also want to know WHAT KIND of thing failed, not only why.\n *\n * Reach for this instead of the inline `err instanceof Error ? \\`${err.name}: ${err.message}\\`\n * : String(err)` wherever the kind is load-bearing rather than decorative:\n *\n * - a **failure DIGEST / dedup key** — collapsing every distinct fault into one bucket\n * is worse than an unreadable message, because the bucket is then wrong for every\n * subsequent decision keyed off it;\n * - a **persisted terminal diagnostic** an operator reads without the log beside it;\n * - a **classifier** that branches on the fault's identity.\n *\n * A {@link WildoError_Backend} has no `name`: its kind is the pair\n * `type` + `customMessageReference`, which is what this renders. Everything else falls\n * through to the native `name`, so the output shape is unchanged for a real `Error`.\n */\nexport function describeCaughtErrorWithKind(error: unknown): string {\n if (isWildoBackendError(error)) {\n return `${error.type}/${error.customMessageReference}: ${describeCaughtError(error)}`;\n }\n return error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n}\n\n/**\n * Classify a backend error and emit exactly one structured log line at the\n * appropriate operational severity.\n *\n * Use this at every backend error-logging boundary instead of hardcoding\n * `logger.error(...)`. It guarantees a single, consistent treatment: expected\n * client conditions stay at `debug`, server faults stay at `error` (with\n * stack), and everything in between is graded by declared severity.\n *\n * @returns the level the line was emitted at (useful for tests / metrics hooks).\n */\nexport function logWildoBackendErrorAtClassifiedSeverity(\n logger: LevelledLogger,\n message: string,\n error: WildoError_Backend,\n context: Record<string, unknown> = {},\n): BackendErrorLogSeverity {\n const level = classifyBackendErrorLogSeverity(error);\n\n // Standard error fields come from the canonical projection; the caller's\n // `context` carries only boundary-specific extras (method/path, socketId,\n // jobId, …) and wins on any key overlap.\n const mergedContext: Record<string, unknown> = {\n ...projectWildoBackendErrorLogFields(error),\n ...context,\n };\n\n const finalContext: Record<string, unknown> =\n backendErrorLogSeverityIncludesStack(level) && typeof error.stack === 'string'\n ? { ...mergedContext, stack: error.stack }\n : mergedContext;\n\n // Extension point: this is the natural site to increment an\n // `auth_token_verification_total{result=\"expired\"}`-style counter (the\n // RECORD_METRICS backend action) so alerting keys off aggregate rate rather\n // than individual log lines. Wire a metrics sink here when one is available.\n\n switch (level) {\n case BackendErrorLogSeverity.DEBUG:\n logger.debug(message, finalContext);\n break;\n case BackendErrorLogSeverity.INFO:\n logger.info(message, finalContext);\n break;\n case BackendErrorLogSeverity.WARN:\n logger.warn(message, finalContext);\n break;\n case BackendErrorLogSeverity.ERROR:\n logger.error(message, finalContext);\n break;\n }\n\n return level;\n}\n"]}
|
|
@@ -80,4 +80,37 @@ export declare function resolveRateLimitEnvironmentMultiplier(applicationEnv: Ru
|
|
|
80
80
|
* @returns `authoredMax` in `STAGING` / `PRODUCTION`; the relaxed ceiling otherwise.
|
|
81
81
|
*/
|
|
82
82
|
export declare function relaxAbuseThrottleMaxForEnvironment(authoredMax: number, applicationEnv: RuntimeEnvironment): number;
|
|
83
|
+
/**
|
|
84
|
+
* Every abuse throttle this relaxation reaches, named so the boot announcement can list them (#499).
|
|
85
|
+
*
|
|
86
|
+
* A line saying "abuse limits relaxed" would be accurate and still misleading: an operator would
|
|
87
|
+
* reasonably read it as ALL of them, and it is not — a counter whose maximum is a product or tenant
|
|
88
|
+
* policy is deliberately untouched, as is any counter used as an audit de-duplication window (see the
|
|
89
|
+
* module header). Naming the reached set is what makes the announcement actionable rather than
|
|
90
|
+
* atmospheric.
|
|
91
|
+
*
|
|
92
|
+
* Maintained by hand against the import sites, which is a list re-stating another file's population —
|
|
93
|
+
* exactly the shape `invariant-call-site-enumeration.md` warns about. It is tolerable ONLY because it
|
|
94
|
+
* feeds a log line rather than a decision: a stale entry here misinforms an operator, it does not
|
|
95
|
+
* change a ceiling. Keep it in step when a site is added, and prefer deleting it over letting it rot.
|
|
96
|
+
*/
|
|
97
|
+
export declare const RELAXED_ABUSE_THROTTLE_SITES: readonly string[];
|
|
98
|
+
/** What a boot announcement should say, or `null` when the environment relaxes nothing. */
|
|
99
|
+
export interface AbuseThrottleRelaxationAnnouncement {
|
|
100
|
+
readonly applicationEnv: RuntimeEnvironment;
|
|
101
|
+
readonly multiplier: number;
|
|
102
|
+
readonly relaxedSites: readonly string[];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Describe the relaxation in force, for an unmissable line at startup (#499).
|
|
106
|
+
*
|
|
107
|
+
* The relaxation is keyed on the resolved environment and nothing else — a deliberate decision, so
|
|
108
|
+
* there is one source of truth for "what kind of host is this" rather than a second flag that can
|
|
109
|
+
* disagree with it. The residual risk is that a host which merely REPORTS development (a demonstration
|
|
110
|
+
* box, a staging-like environment mis-declared) runs with maxima multiplied by a thousand. That risk is
|
|
111
|
+
* accepted, and this function is the whole of what makes it visible instead of silent.
|
|
112
|
+
*
|
|
113
|
+
* Returns `null` in `STAGING` / `PRODUCTION`, so a caller logs nothing where nothing is relaxed.
|
|
114
|
+
*/
|
|
115
|
+
export declare function describeAbuseThrottleRelaxation(applicationEnv: RuntimeEnvironment): AbuseThrottleRelaxationAnnouncement | null;
|
|
83
116
|
//# sourceMappingURL=rate-limit-environment-relaxation.backend.utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit-environment-relaxation.backend.utils.d.ts","sourceRoot":"","sources":["../../../../../src/errors/utils/rate-limit-environment-relaxation.backend.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;;;;GAOG;AACH,eAAO,MAAM,oCAAoC,OAAO,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAgB,qCAAqC,CAAC,cAAc,EAAE,kBAAkB,GAAG,MAAM,CAIhG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mCAAmC,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,kBAAkB,GAAG,MAAM,CAEnH"}
|
|
1
|
+
{"version":3,"file":"rate-limit-environment-relaxation.backend.utils.d.ts","sourceRoot":"","sources":["../../../../../src/errors/utils/rate-limit-environment-relaxation.backend.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;;;;GAOG;AACH,eAAO,MAAM,oCAAoC,OAAO,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAgB,qCAAqC,CAAC,cAAc,EAAE,kBAAkB,GAAG,MAAM,CAIhG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mCAAmC,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,kBAAkB,GAAG,MAAM,CAEnH;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,4BAA4B,EAAE,SAAS,MAAM,EAQzD,CAAC;AAEF,2FAA2F;AAC3F,MAAM,WAAW,mCAAmC;IAClD,QAAQ,CAAC,cAAc,EAAE,kBAAkB,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,+BAA+B,CAC7C,cAAc,EAAE,kBAAkB,GACjC,mCAAmC,GAAG,IAAI,CAK5C"}
|
|
@@ -86,4 +86,44 @@ export function resolveRateLimitEnvironmentMultiplier(applicationEnv) {
|
|
|
86
86
|
export function relaxAbuseThrottleMaxForEnvironment(authoredMax, applicationEnv) {
|
|
87
87
|
return authoredMax * resolveRateLimitEnvironmentMultiplier(applicationEnv);
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Every abuse throttle this relaxation reaches, named so the boot announcement can list them (#499).
|
|
91
|
+
*
|
|
92
|
+
* A line saying "abuse limits relaxed" would be accurate and still misleading: an operator would
|
|
93
|
+
* reasonably read it as ALL of them, and it is not — a counter whose maximum is a product or tenant
|
|
94
|
+
* policy is deliberately untouched, as is any counter used as an audit de-duplication window (see the
|
|
95
|
+
* module header). Naming the reached set is what makes the announcement actionable rather than
|
|
96
|
+
* atmospheric.
|
|
97
|
+
*
|
|
98
|
+
* Maintained by hand against the import sites, which is a list re-stating another file's population —
|
|
99
|
+
* exactly the shape `invariant-call-site-enumeration.md` warns about. It is tolerable ONLY because it
|
|
100
|
+
* feeds a log line rather than a decision: a stale entry here misinforms an operator, it does not
|
|
101
|
+
* change a ceiling. Keep it in step when a site is added, and prefer deleting it over letting it rot.
|
|
102
|
+
*/
|
|
103
|
+
export const RELAXED_ABUSE_THROTTLE_SITES = [
|
|
104
|
+
'HTTP perimeter limiter',
|
|
105
|
+
'WebSocket per-event limiter',
|
|
106
|
+
'machine-credential failure guard',
|
|
107
|
+
'external-turn throttle (A2A / MCP)',
|
|
108
|
+
'authorization-denial audit sampler',
|
|
109
|
+
'webhook endpoint-test cap',
|
|
110
|
+
'rate-limit policy service',
|
|
111
|
+
];
|
|
112
|
+
/**
|
|
113
|
+
* Describe the relaxation in force, for an unmissable line at startup (#499).
|
|
114
|
+
*
|
|
115
|
+
* The relaxation is keyed on the resolved environment and nothing else — a deliberate decision, so
|
|
116
|
+
* there is one source of truth for "what kind of host is this" rather than a second flag that can
|
|
117
|
+
* disagree with it. The residual risk is that a host which merely REPORTS development (a demonstration
|
|
118
|
+
* box, a staging-like environment mis-declared) runs with maxima multiplied by a thousand. That risk is
|
|
119
|
+
* accepted, and this function is the whole of what makes it visible instead of silent.
|
|
120
|
+
*
|
|
121
|
+
* Returns `null` in `STAGING` / `PRODUCTION`, so a caller logs nothing where nothing is relaxed.
|
|
122
|
+
*/
|
|
123
|
+
export function describeAbuseThrottleRelaxation(applicationEnv) {
|
|
124
|
+
const multiplier = resolveRateLimitEnvironmentMultiplier(applicationEnv);
|
|
125
|
+
return multiplier === 1
|
|
126
|
+
? null
|
|
127
|
+
: { applicationEnv, multiplier, relaxedSites: RELAXED_ABUSE_THROTTLE_SITES };
|
|
128
|
+
}
|
|
89
129
|
//# sourceMappingURL=rate-limit-environment-relaxation.backend.utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit-environment-relaxation.backend.utils.js","sourceRoot":"","sources":["../../../../../src/errors/utils/rate-limit-environment-relaxation.backend.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,IAAI,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,UAAU,qCAAqC,CAAC,cAAkC;IACtF,OAAO,cAAc,KAAK,kBAAkB,CAAC,WAAW,IAAI,cAAc,KAAK,kBAAkB,CAAC,IAAI;QACpG,CAAC,CAAC,oCAAoC;QACtC,CAAC,CAAC,CAAC,CAAC;AACR,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,mCAAmC,CAAC,WAAmB,EAAE,cAAkC;IACzG,OAAO,WAAW,GAAG,qCAAqC,CAAC,cAAc,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["/**\n * Non-production relaxation of ABUSE-THROTTLE maxima — the single seam.\n *\n * ## Why this module exists\n *\n * Every rate-limit maximum in the engine is authored for a PRODUCTION threat model\n * (credential stuffing, registration spam, enumeration, LLM-spend abuse, unmetered\n * egress). Applied unchanged, those same numbers turn ordinary local development and\n * automated e2e/integration runs — which legitimately fire the same endpoint from the\n * same IP, the same email and the same principal dozens of times in seconds — into a\n * 429 flood.\n *\n * The relaxation used to live as a private constant inside\n * `RateLimitBackendService`, so it reached only that service's three surfaces\n * (`checkRateLimit`, `checkPolicy`, `checkPolicyForVariant`). Five other enforcement\n * sites carry their own hard-coded maxima and never saw it. The one that hurt most in\n * practice was the machine-credential failure guard\n * (`assertMachineAuthAttemptWithinRate`, 50 failures / 600 s / source IP): on a dev\n * machine every process shares `127.0.0.1`, so fifty failed `sk_*` / `oc_*`\n * presentations from ANY source lock out every machine-credential path for ten\n * minutes — including the ones a developer is actively debugging.\n *\n * This module is that single seam. Import it at every abuse-throttle site rather than\n * re-deriving an environment branch locally; a second copy of the branch is how the\n * first one drifted (see `.claude/rules/invariant-call-site-enumeration.md`).\n *\n * ## What it deliberately does NOT do\n *\n * - **It does not bypass enforcement.** The counters still increment through the real\n * Redis `INCR` + `EXPIRE` path, so a genuine regression (windows not incrementing,\n * keys colliding, TTL never set) still reproduces locally. Only the ceiling moves.\n * - **It does not touch `STAGING` / `PRODUCTION`.** {@link resolveRateLimitEnvironmentMultiplier}\n * returns `1` for every environment other than `DEVELOPMENT` and `TEST`, so the\n * authored number IS the enforced number wherever the threat model is real.\n * - **It must not be applied to business-semantic counters.** A counter whose maximum\n * is a product or tenant policy — SSO grace logins (`enforcement.graceLoginAttempts`),\n * trial quotas, plan entitlements — is not an abuse throttle. Multiplying it would\n * change observable product behavior in dev/test and make local runs disagree with\n * production semantics, which is the opposite of what this exists for. The same goes\n * for counters used as audit/log DE-DUPLICATION windows (the authorization-denial\n * audit sampler, the SAML assertion warning de-dup): relaxing those produces an\n * audit/log flood, not headroom.\n *\n * @see `.claude/rules/invariant-call-site-enumeration.md` — the per-site enumeration\n * discipline that produced this module.\n */\n\nimport { RuntimeEnvironment } from '@wildo-ai/saas-models';\n\n/**\n * Factor applied to an abuse-throttle maximum in `DEVELOPMENT` / `TEST`.\n *\n * Large on purpose. The goal is that no honest local or automated run can reach a\n * ceiling, while the counter itself still exercises the real enforcement path. A\n * smaller factor (10×, 100×) merely moves the flood later into a long e2e suite,\n * which is the worst of both worlds: still flaky, still hard to attribute.\n */\nexport const NON_PRODUCTION_RATE_LIMIT_MULTIPLIER = 1000;\n\n/**\n * `NON_PRODUCTION_RATE_LIMIT_MULTIPLIER` in `DEVELOPMENT` / `TEST`, `1` everywhere\n * else. The single branch point for the relaxation.\n *\n * @param applicationEnv - the resolved runtime environment, normally\n * `AppConfigurationService.applicationEnv`.\n */\nexport function resolveRateLimitEnvironmentMultiplier(applicationEnv: RuntimeEnvironment): number {\n return applicationEnv === RuntimeEnvironment.DEVELOPMENT || applicationEnv === RuntimeEnvironment.TEST\n ? NON_PRODUCTION_RATE_LIMIT_MULTIPLIER\n : 1;\n}\n\n/**\n * Scale one abuse-throttle maximum for the current environment. The canonical call\n * shape at an enforcement site:\n *\n * ```ts\n * const effectiveMax = relaxAbuseThrottleMaxForEnvironment(MACHINE_AUTH_FAILURE_MAX, applicationEnv);\n * if (failureCount >= effectiveMax) { … }\n * ```\n *\n * Compare the LIVE count against the returned value — never scale the count itself,\n * and never scale the window length. Shortening the window in dev would make a local\n * run stop reproducing the production timing behavior; raising the ceiling does not.\n *\n * @param authoredMax - the production-authored maximum for the window.\n * @param applicationEnv - the resolved runtime environment.\n * @returns `authoredMax` in `STAGING` / `PRODUCTION`; the relaxed ceiling otherwise.\n */\nexport function relaxAbuseThrottleMaxForEnvironment(authoredMax: number, applicationEnv: RuntimeEnvironment): number {\n return authoredMax * resolveRateLimitEnvironmentMultiplier(applicationEnv);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"rate-limit-environment-relaxation.backend.utils.js","sourceRoot":"","sources":["../../../../../src/errors/utils/rate-limit-environment-relaxation.backend.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,IAAI,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,UAAU,qCAAqC,CAAC,cAAkC;IACtF,OAAO,cAAc,KAAK,kBAAkB,CAAC,WAAW,IAAI,cAAc,KAAK,kBAAkB,CAAC,IAAI;QACpG,CAAC,CAAC,oCAAoC;QACtC,CAAC,CAAC,CAAC,CAAC;AACR,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,mCAAmC,CAAC,WAAmB,EAAE,cAAkC;IACzG,OAAO,WAAW,GAAG,qCAAqC,CAAC,cAAc,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAsB;IAC7D,wBAAwB;IACxB,6BAA6B;IAC7B,kCAAkC;IAClC,oCAAoC;IACpC,oCAAoC;IACpC,2BAA2B;IAC3B,2BAA2B;CAC5B,CAAC;AASF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,+BAA+B,CAC7C,cAAkC;IAElC,MAAM,UAAU,GAAG,qCAAqC,CAAC,cAAc,CAAC,CAAC;IACzE,OAAO,UAAU,KAAK,CAAC;QACrB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,4BAA4B,EAAE,CAAC;AACjF,CAAC","sourcesContent":["/**\n * Non-production relaxation of ABUSE-THROTTLE maxima — the single seam.\n *\n * ## Why this module exists\n *\n * Every rate-limit maximum in the engine is authored for a PRODUCTION threat model\n * (credential stuffing, registration spam, enumeration, LLM-spend abuse, unmetered\n * egress). Applied unchanged, those same numbers turn ordinary local development and\n * automated e2e/integration runs — which legitimately fire the same endpoint from the\n * same IP, the same email and the same principal dozens of times in seconds — into a\n * 429 flood.\n *\n * The relaxation used to live as a private constant inside\n * `RateLimitBackendService`, so it reached only that service's three surfaces\n * (`checkRateLimit`, `checkPolicy`, `checkPolicyForVariant`). Five other enforcement\n * sites carry their own hard-coded maxima and never saw it. The one that hurt most in\n * practice was the machine-credential failure guard\n * (`assertMachineAuthAttemptWithinRate`, 50 failures / 600 s / source IP): on a dev\n * machine every process shares `127.0.0.1`, so fifty failed `sk_*` / `oc_*`\n * presentations from ANY source lock out every machine-credential path for ten\n * minutes — including the ones a developer is actively debugging.\n *\n * This module is that single seam. Import it at every abuse-throttle site rather than\n * re-deriving an environment branch locally; a second copy of the branch is how the\n * first one drifted (see `.claude/rules/invariant-call-site-enumeration.md`).\n *\n * ## What it deliberately does NOT do\n *\n * - **It does not bypass enforcement.** The counters still increment through the real\n * Redis `INCR` + `EXPIRE` path, so a genuine regression (windows not incrementing,\n * keys colliding, TTL never set) still reproduces locally. Only the ceiling moves.\n * - **It does not touch `STAGING` / `PRODUCTION`.** {@link resolveRateLimitEnvironmentMultiplier}\n * returns `1` for every environment other than `DEVELOPMENT` and `TEST`, so the\n * authored number IS the enforced number wherever the threat model is real.\n * - **It must not be applied to business-semantic counters.** A counter whose maximum\n * is a product or tenant policy — SSO grace logins (`enforcement.graceLoginAttempts`),\n * trial quotas, plan entitlements — is not an abuse throttle. Multiplying it would\n * change observable product behavior in dev/test and make local runs disagree with\n * production semantics, which is the opposite of what this exists for. The same goes\n * for counters used as audit/log DE-DUPLICATION windows (the authorization-denial\n * audit sampler, the SAML assertion warning de-dup): relaxing those produces an\n * audit/log flood, not headroom.\n *\n * @see `.claude/rules/invariant-call-site-enumeration.md` — the per-site enumeration\n * discipline that produced this module.\n */\n\nimport { RuntimeEnvironment } from '@wildo-ai/saas-models';\n\n/**\n * Factor applied to an abuse-throttle maximum in `DEVELOPMENT` / `TEST`.\n *\n * Large on purpose. The goal is that no honest local or automated run can reach a\n * ceiling, while the counter itself still exercises the real enforcement path. A\n * smaller factor (10×, 100×) merely moves the flood later into a long e2e suite,\n * which is the worst of both worlds: still flaky, still hard to attribute.\n */\nexport const NON_PRODUCTION_RATE_LIMIT_MULTIPLIER = 1000;\n\n/**\n * `NON_PRODUCTION_RATE_LIMIT_MULTIPLIER` in `DEVELOPMENT` / `TEST`, `1` everywhere\n * else. The single branch point for the relaxation.\n *\n * @param applicationEnv - the resolved runtime environment, normally\n * `AppConfigurationService.applicationEnv`.\n */\nexport function resolveRateLimitEnvironmentMultiplier(applicationEnv: RuntimeEnvironment): number {\n return applicationEnv === RuntimeEnvironment.DEVELOPMENT || applicationEnv === RuntimeEnvironment.TEST\n ? NON_PRODUCTION_RATE_LIMIT_MULTIPLIER\n : 1;\n}\n\n/**\n * Scale one abuse-throttle maximum for the current environment. The canonical call\n * shape at an enforcement site:\n *\n * ```ts\n * const effectiveMax = relaxAbuseThrottleMaxForEnvironment(MACHINE_AUTH_FAILURE_MAX, applicationEnv);\n * if (failureCount >= effectiveMax) { … }\n * ```\n *\n * Compare the LIVE count against the returned value — never scale the count itself,\n * and never scale the window length. Shortening the window in dev would make a local\n * run stop reproducing the production timing behavior; raising the ceiling does not.\n *\n * @param authoredMax - the production-authored maximum for the window.\n * @param applicationEnv - the resolved runtime environment.\n * @returns `authoredMax` in `STAGING` / `PRODUCTION`; the relaxed ceiling otherwise.\n */\nexport function relaxAbuseThrottleMaxForEnvironment(authoredMax: number, applicationEnv: RuntimeEnvironment): number {\n return authoredMax * resolveRateLimitEnvironmentMultiplier(applicationEnv);\n}\n\n/**\n * Every abuse throttle this relaxation reaches, named so the boot announcement can list them (#499).\n *\n * A line saying \"abuse limits relaxed\" would be accurate and still misleading: an operator would\n * reasonably read it as ALL of them, and it is not — a counter whose maximum is a product or tenant\n * policy is deliberately untouched, as is any counter used as an audit de-duplication window (see the\n * module header). Naming the reached set is what makes the announcement actionable rather than\n * atmospheric.\n *\n * Maintained by hand against the import sites, which is a list re-stating another file's population —\n * exactly the shape `invariant-call-site-enumeration.md` warns about. It is tolerable ONLY because it\n * feeds a log line rather than a decision: a stale entry here misinforms an operator, it does not\n * change a ceiling. Keep it in step when a site is added, and prefer deleting it over letting it rot.\n */\nexport const RELAXED_ABUSE_THROTTLE_SITES: readonly string[] = [\n 'HTTP perimeter limiter',\n 'WebSocket per-event limiter',\n 'machine-credential failure guard',\n 'external-turn throttle (A2A / MCP)',\n 'authorization-denial audit sampler',\n 'webhook endpoint-test cap',\n 'rate-limit policy service',\n];\n\n/** What a boot announcement should say, or `null` when the environment relaxes nothing. */\nexport interface AbuseThrottleRelaxationAnnouncement {\n readonly applicationEnv: RuntimeEnvironment;\n readonly multiplier: number;\n readonly relaxedSites: readonly string[];\n}\n\n/**\n * Describe the relaxation in force, for an unmissable line at startup (#499).\n *\n * The relaxation is keyed on the resolved environment and nothing else — a deliberate decision, so\n * there is one source of truth for \"what kind of host is this\" rather than a second flag that can\n * disagree with it. The residual risk is that a host which merely REPORTS development (a demonstration\n * box, a staging-like environment mis-declared) runs with maxima multiplied by a thousand. That risk is\n * accepted, and this function is the whole of what makes it visible instead of silent.\n *\n * Returns `null` in `STAGING` / `PRODUCTION`, so a caller logs nothing where nothing is relaxed.\n */\nexport function describeAbuseThrottleRelaxation(\n applicationEnv: RuntimeEnvironment,\n): AbuseThrottleRelaxationAnnouncement | null {\n const multiplier = resolveRateLimitEnvironmentMultiplier(applicationEnv);\n return multiplier === 1\n ? null\n : { applicationEnv, multiplier, relaxedSites: RELAXED_ABUSE_THROTTLE_SITES };\n}\n"]}
|
|
@@ -55,6 +55,7 @@ import type { ResourcesRegistryBackendService } from '../resources/services/reso
|
|
|
55
55
|
import type { ErrorBuilderBackendService } from '../errors/services/error-builder.backend.service';
|
|
56
56
|
import type { LoggerService } from '../monitoring/logger/services/logger.service';
|
|
57
57
|
import type { HttpApiAuditLogsResolver } from '../base-classes/services/repositories/http-api/http-api-resource-repository.backend.service';
|
|
58
|
+
import { type AuditObservationLossMetricsRecorder } from '../monitoring/observability/audit-observation-emission.backend';
|
|
58
59
|
import { type ExternalDataExtractionSource } from './external-data-extraction-source.backend';
|
|
59
60
|
export interface ExternalDataPipelineRunInput {
|
|
60
61
|
/** The DESTINATION resource type declaring the `externalDataPipeline`. */
|
|
@@ -109,6 +110,30 @@ export declare class ExternalDataPipelineRunBackendService {
|
|
|
109
110
|
private readonly auditLogsResolver?;
|
|
110
111
|
/** Test seam — production leaves it unset and gets the HTTP source over the shared client. */
|
|
111
112
|
private readonly extractionSourceFactory?;
|
|
113
|
+
/**
|
|
114
|
+
* The PRODUCTION door to the read-through audit sink — and it had to be added, because the
|
|
115
|
+
* `@unmanaged()` thunk above cannot be one.
|
|
116
|
+
*
|
|
117
|
+
* `@unmanaged()` tells Inversify not to resolve a parameter, and this class is bound with
|
|
118
|
+
* `.to(...)`, so the container constructs it and passes `undefined` there. That made the seam a
|
|
119
|
+
* TEST-ONLY door: every scheduled ETL run in production reached `recordRunReadThroughAccess`,
|
|
120
|
+
* found no resolver, and emitted nothing. The sink itself exists
|
|
121
|
+
* (`AuditLogsBackendService.logHttpApiReadThroughAccess`), so nothing was refusing — the row was
|
|
122
|
+
* simply never written, silently, which is exactly the shape the loss counter now makes visible.
|
|
123
|
+
*
|
|
124
|
+
* Two suppliers, and they cannot collide: `@unmanaged()` is structurally unfillable by the
|
|
125
|
+
* container, so the thunk is only ever set by a test constructing this class with `new`, and it
|
|
126
|
+
* takes precedence there so a suite can substitute a double. `@optional()` here for the usual
|
|
127
|
+
* reason — a minimal container binds no audit service and an ETL run must still run.
|
|
128
|
+
*
|
|
129
|
+
* assurance-control: WILDO.AUDIT.ATTRIBUTION — an ETL run's external read is recorded.
|
|
130
|
+
*/
|
|
131
|
+
private readonly auditLogsService?;
|
|
132
|
+
/**
|
|
133
|
+
* The loss counter behind that emission. Appended LAST and `@optional()`, so a container with no
|
|
134
|
+
* metrics binding degrades a dropped attribution row to the log channel rather than to nothing.
|
|
135
|
+
*/
|
|
136
|
+
private readonly metricsService?;
|
|
112
137
|
private readonly inFlight;
|
|
113
138
|
private readonly logDebug;
|
|
114
139
|
constructor(logger: LoggerService, errorBuilder: ErrorBuilderBackendService, repositoriesRegistry: RepositoriesRegistryHandlerBackendService, resourcesRegistry: ResourcesRegistryBackendService, syncEngine: SyncSeedEngineBackendService, upgradeEngine: UpgradeSeedEngineBackendService, executionContextCreator: ExecutionContextCreatorBackendService,
|
|
@@ -125,7 +150,31 @@ export declare class ExternalDataPipelineRunBackendService {
|
|
|
125
150
|
*/
|
|
126
151
|
auditLogsResolver?: HttpApiAuditLogsResolver,
|
|
127
152
|
/** Test seam — production leaves it unset and gets the HTTP source over the shared client. */
|
|
128
|
-
extractionSourceFactory?: ExternalDataExtractionSourceFactory
|
|
153
|
+
extractionSourceFactory?: ExternalDataExtractionSourceFactory,
|
|
154
|
+
/**
|
|
155
|
+
* The PRODUCTION door to the read-through audit sink — and it had to be added, because the
|
|
156
|
+
* `@unmanaged()` thunk above cannot be one.
|
|
157
|
+
*
|
|
158
|
+
* `@unmanaged()` tells Inversify not to resolve a parameter, and this class is bound with
|
|
159
|
+
* `.to(...)`, so the container constructs it and passes `undefined` there. That made the seam a
|
|
160
|
+
* TEST-ONLY door: every scheduled ETL run in production reached `recordRunReadThroughAccess`,
|
|
161
|
+
* found no resolver, and emitted nothing. The sink itself exists
|
|
162
|
+
* (`AuditLogsBackendService.logHttpApiReadThroughAccess`), so nothing was refusing — the row was
|
|
163
|
+
* simply never written, silently, which is exactly the shape the loss counter now makes visible.
|
|
164
|
+
*
|
|
165
|
+
* Two suppliers, and they cannot collide: `@unmanaged()` is structurally unfillable by the
|
|
166
|
+
* container, so the thunk is only ever set by a test constructing this class with `new`, and it
|
|
167
|
+
* takes precedence there so a suite can substitute a double. `@optional()` here for the usual
|
|
168
|
+
* reason — a minimal container binds no audit service and an ETL run must still run.
|
|
169
|
+
*
|
|
170
|
+
* assurance-control: WILDO.AUDIT.ATTRIBUTION — an ETL run's external read is recorded.
|
|
171
|
+
*/
|
|
172
|
+
auditLogsService?: NonNullable<ReturnType<HttpApiAuditLogsResolver>>,
|
|
173
|
+
/**
|
|
174
|
+
* The loss counter behind that emission. Appended LAST and `@optional()`, so a container with no
|
|
175
|
+
* metrics binding degrades a dropped attribution row to the log channel rather than to nothing.
|
|
176
|
+
*/
|
|
177
|
+
metricsService?: AuditObservationLossMetricsRecorder);
|
|
129
178
|
/** The on-demand door (PR-12). The scheduled batch calls this per due pipeline. */
|
|
130
179
|
runPipeline(input: ExternalDataPipelineRunInput): Promise<ExternalDataPipelineRunReport>;
|
|
131
180
|
/** Every registered resource that declares an `externalDataPipeline` — the scheduled batch's population. */
|
|
@@ -156,7 +205,15 @@ export declare class ExternalDataPipelineRunBackendService {
|
|
|
156
205
|
private buildHttpExtractionSource;
|
|
157
206
|
private resolveApplicationScopeAnchor;
|
|
158
207
|
private logRejections;
|
|
159
|
-
/**
|
|
208
|
+
/**
|
|
209
|
+
* PR-10 — one audit row per run, fire-and-forget through the shared seam.
|
|
210
|
+
*
|
|
211
|
+
* The emission goes through {@link emitAuditObservation}, so a run whose attribution row never
|
|
212
|
+
* reached the pipeline lands on `audit_observation_dropped_total` instead of nowhere. The feature
|
|
213
|
+
* detection decides an ARGUMENT rather than an early return: handing the seam `undefined` is how
|
|
214
|
+
* this site reports `SERVICE_UNAVAILABLE`, and returning early would restore the silence that let
|
|
215
|
+
* this seam sit unwired in production without anything saying so.
|
|
216
|
+
*/
|
|
160
217
|
private recordRunReadThroughAccess;
|
|
161
218
|
}
|
|
162
219
|
//# sourceMappingURL=external-data-pipeline-run.backend.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-data-pipeline-run.backend.service.d.ts","sourceRoot":"","sources":["../../../../src/external-data/external-data-pipeline-run.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AASH,OAAO,EAGL,KAAK,+BAA+B,EACrC,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAML,qBAAqB,EAGtB,MAAM,iEAAiE,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qEAAqE,CAAC;AAExG,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mFAAmF,CAAC;AACtI,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,sFAAsF,CAAC;AAC5I,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qEAAqE,CAAC;AAC5G,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,+EAA+E,CAAC;AAC3I,OAAO,KAAK,EAAE,yCAAyC,EAAE,MAAM,qGAAqG,CAAC;AACrK,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,0EAA0E,CAAC;AAChI,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kEAAkE,CAAC;AACnH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAC;AAMlG,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6GAA6G,CAAC;AAC5J,OAAO,EAAuC,KAAK,4BAA4B,EAAE,MAAM,2CAA2C,CAAC;AAanI,MAAM,WAAW,4BAA4B;IAC3C,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,aAAa,EAAE,qBAAqB,CAAC,YAAY,GAAG,qBAAqB,CAAC,eAAe,CAAC;IAC1F,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,gBAAgB,GAAG,cAAc,GAAG,iBAAiB,CAAC;IAC/D,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACrC,4FAA4F;IAC5F,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,wEAAwE;IACxE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,gGAAgG;AAChG,MAAM,MAAM,mCAAmC,GAAG,CAChD,WAAW,EAAE,+BAA+B,EAC5C,eAAe,EAAE,gBAAgB,CAAC,GAAG,CAAC,KACnC,4BAA4B,CAAC;AAElC,qBACa,qCAAqC;IAKX,OAAO,CAAC,QAAQ,CAAC,MAAM;IACV,OAAO,CAAC,QAAQ,CAAC,YAAY;IACd,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IAChD,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IACV,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IAC1G;;;;OAIG;IACsE,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IACpH;;;;OAIG;IASU,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IAChD,8FAA8F;IACjF,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"external-data-pipeline-run.backend.service.d.ts","sourceRoot":"","sources":["../../../../src/external-data/external-data-pipeline-run.backend.service.ts"],"names":[],"mappings":"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"}
|