@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
|
@@ -24,6 +24,13 @@
|
|
|
24
24
|
* While a pod owns a turn it refreshes a TTL'd lease key. That is what lets
|
|
25
25
|
* `tasks/get` report an abandoned task honestly instead of leaving it `working`
|
|
26
26
|
* forever after a pod dies — see the lease helpers below.
|
|
27
|
+
*
|
|
28
|
+
* An absent lease is NOT self-explanatory, though, and reading it as death is an inversion that
|
|
29
|
+
* costs real work: a pod that could not write the lease looks exactly like a pod that died. So
|
|
30
|
+
* every successful lease write also leaves a long-lived ESTABLISHMENT marker, and
|
|
31
|
+
* `corroborateAbandonment` is what turns "no lease" into either a verdict or an admission that
|
|
32
|
+
* nothing was learned. Only the sweep — the one consumer that makes a liveness answer DURABLE —
|
|
33
|
+
* asks that question.
|
|
27
34
|
*/
|
|
28
35
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
29
36
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -40,10 +47,26 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
40
47
|
import { inject, injectable } from 'inversify';
|
|
41
48
|
import { SAAS_SERVICE_TYPES } from '../../../inject/models/service-types.js';
|
|
42
49
|
import { projectCaughtErrorLogFields } from '../../../errors/utils/error-log-level-classification.backend.utils.js';
|
|
50
|
+
import { A2A_AbandonmentEvidence } from '../../../flows-actors/a2a/models/a2a.backend.schemas.js';
|
|
43
51
|
/** Channel every replica subscribes to. App-prefixed so tenants of one Redis never cross. */
|
|
44
52
|
const CANCEL_CHANNEL_SUFFIX = 'a2a:task:cancel';
|
|
45
53
|
/** Lease key prefix — presence means "a live pod is working this task right now". */
|
|
46
54
|
const LEASE_KEY_PREFIX = 'a2a:task:lease:';
|
|
55
|
+
/**
|
|
56
|
+
* ESTABLISHMENT marker prefix — presence means "this task's liveness WAS observable at some point
|
|
57
|
+
* recently", which is a different fact from "it is alive now" and has a different lifetime.
|
|
58
|
+
*
|
|
59
|
+
* It is what makes an absent lease MEAN something (see {@link A2A_AbandonmentEvidence}). Written
|
|
60
|
+
* by the same code path and in the same failure domain as the lease itself, so it can only exist
|
|
61
|
+
* if a write actually succeeded — which is exactly the property being recorded.
|
|
62
|
+
*/
|
|
63
|
+
const LEASE_ESTABLISHED_KEY_PREFIX = 'a2a:task:leased-once:';
|
|
64
|
+
/**
|
|
65
|
+
* The sweep's own note that it has already seen one unexplained absence for a task. Written by the
|
|
66
|
+
* SWEEP's pod, whose write capability `isLeaseMechanismWritable` proved moments earlier — so the
|
|
67
|
+
* medium is known-good at the point of use, unlike the lease itself.
|
|
68
|
+
*/
|
|
69
|
+
const ABANDONMENT_OBSERVATION_KEY_PREFIX = 'a2a:task:absence-seen:';
|
|
47
70
|
/**
|
|
48
71
|
* Lease TTL and refresh cadence. The refresh interval is deliberately well under the
|
|
49
72
|
* TTL: a single missed refresh (GC pause, a slow Redis round-trip) must not make a
|
|
@@ -51,6 +74,26 @@ const LEASE_KEY_PREFIX = 'a2a:task:lease:';
|
|
|
51
74
|
*/
|
|
52
75
|
export const A2A_TASK_LEASE_TTL_SECONDS = 30;
|
|
53
76
|
export const A2A_TASK_LEASE_REFRESH_MS = 10_000;
|
|
77
|
+
/**
|
|
78
|
+
* How long the establishment marker outlives its last refresh.
|
|
79
|
+
*
|
|
80
|
+
* Sized to comfortably span the sweep's grace window plus its hourly period, so a pod that dies
|
|
81
|
+
* mid-turn is still recognisable as HAVING held the task when the next sweep looks. It is a
|
|
82
|
+
* timing optimisation, never a correctness requirement: if it lapses, the reading degrades to
|
|
83
|
+
* {@link A2A_AbandonmentEvidence.FIRST_ABSENCE} and the row is repaired one run later instead of
|
|
84
|
+
* on the first — which is the direction this whole mechanism errs in anyway.
|
|
85
|
+
*/
|
|
86
|
+
export const A2A_TASK_LEASE_ESTABLISHED_TTL_SECONDS = 6 * 60 * 60;
|
|
87
|
+
/**
|
|
88
|
+
* How long one unexplained absence stands as corroboration for the next run.
|
|
89
|
+
*
|
|
90
|
+
* MUST exceed the sweep's period or no observation ever survives to be corroborated and nothing
|
|
91
|
+
* is ever repaired through that path; generous beyond it so a skipped run (the fleet-wide abstain)
|
|
92
|
+
* does not reset the count. Nothing clears it on recovery, and it does not need clearing: a task
|
|
93
|
+
* whose pod recovered answers ALIVE on the lease long before this is consulted, and once its lease
|
|
94
|
+
* lapses for real the establishment marker gives the verdict directly.
|
|
95
|
+
*/
|
|
96
|
+
export const A2A_TASK_ABSENCE_OBSERVATION_TTL_SECONDS = 3 * 60 * 60;
|
|
54
97
|
let A2ATaskCancellationBackendService = class A2ATaskCancellationBackendService {
|
|
55
98
|
logger;
|
|
56
99
|
redisService;
|
|
@@ -70,6 +113,12 @@ let A2ATaskCancellationBackendService = class A2ATaskCancellationBackendService
|
|
|
70
113
|
leaseKey(taskId) {
|
|
71
114
|
return `${LEASE_KEY_PREFIX}${taskId}`;
|
|
72
115
|
}
|
|
116
|
+
leaseEstablishedKey(taskId) {
|
|
117
|
+
return `${LEASE_ESTABLISHED_KEY_PREFIX}${taskId}`;
|
|
118
|
+
}
|
|
119
|
+
absenceObservationKey(taskId) {
|
|
120
|
+
return `${ABANDONMENT_OBSERVATION_KEY_PREFIX}${taskId}`;
|
|
121
|
+
}
|
|
73
122
|
/**
|
|
74
123
|
* Start this pod's single shared subscriber. Idempotent — safe to call from every
|
|
75
124
|
* turn, so no startup ordering is required.
|
|
@@ -150,48 +199,85 @@ let A2ATaskCancellationBackendService = class A2ATaskCancellationBackendService
|
|
|
150
199
|
// a non-terminal task with no lease and is told FAILED by derive-on-read.
|
|
151
200
|
const controller = new AbortController();
|
|
152
201
|
this.localTurns.set(taskId, controller);
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
202
|
+
let leaseEverWritten = false;
|
|
203
|
+
let unwritableAlreadyReported = false;
|
|
204
|
+
const refresh = async () => {
|
|
205
|
+
try {
|
|
206
|
+
await this.redisService.set(this.leaseKey(taskId), '1', { ttl: A2A_TASK_LEASE_TTL_SECONDS });
|
|
207
|
+
// The ESTABLISHMENT marker rides the same write, in the same failure domain, and is what
|
|
208
|
+
// makes a LATER absence of the lease mean something: a reader that finds no lease but
|
|
209
|
+
// finds this knows a pod really did hold the task and stopped, rather than that this
|
|
210
|
+
// task's liveness was never observable at all. Written every refresh so a long turn keeps
|
|
211
|
+
// it alive; deliberately NOT written before the lease, so it can never claim an
|
|
212
|
+
// establishment that did not happen.
|
|
213
|
+
await this.redisService.set(this.leaseEstablishedKey(taskId), '1', { ttl: A2A_TASK_LEASE_ESTABLISHED_TTL_SECONDS });
|
|
214
|
+
leaseEverWritten = true;
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
// A missed REFRESH is survivable — the TTL is several refreshes long, so the lease
|
|
218
|
+
// written earlier still answers for this turn.
|
|
219
|
+
//
|
|
220
|
+
// A lease that was NEVER successfully written is a different thing entirely (review
|
|
221
|
+
// finding A3-4), and it used to log identically. No other pod can distinguish "the
|
|
222
|
+
// write failed" from "the pod died": `tasks/get` on any other replica reports this
|
|
223
|
+
// healthy running turn as FAILED, and the sweep then makes that answer DURABLE. This
|
|
224
|
+
// is the write-side twin of the read-side hole G2-8 closed — the JSDoc claim that
|
|
225
|
+
// "only a genuinely dead pod stops refreshing" was false in exactly this case.
|
|
226
|
+
if (leaseEverWritten) {
|
|
227
|
+
this.logger.warn('[A2ATaskCancel] Lease refresh failed', { taskId, ...projectCaughtErrorLogFields(error) });
|
|
228
|
+
return;
|
|
160
229
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
230
|
+
// ONCE per turn, not once per heartbeat. The heartbeat now runs even with no Redis at all
|
|
231
|
+
// (see below), so an unconditional log here would emit a line every 10 seconds for every
|
|
232
|
+
// concurrent turn of a Redis-less deployment — which is how a channel that carries a real
|
|
233
|
+
// signal gets tuned out.
|
|
234
|
+
if (unwritableAlreadyReported)
|
|
235
|
+
return;
|
|
236
|
+
unwritableAlreadyReported = true;
|
|
237
|
+
// The two causes are logged at DIFFERENT levels because one is a configuration and the
|
|
238
|
+
// other is a fault. No client on this pod is the supported single-replica / local-dev
|
|
239
|
+
// shape: `isTurnAlive` fails safe toward "alive" there and nothing reads liveness across
|
|
240
|
+
// pods, so it is a WARN. A client that is present and REJECTED the write is the dangerous
|
|
241
|
+
// asymmetry — this pod is partitioned from a liveness plane every other replica can still
|
|
242
|
+
// read — and it keeps the ERROR level it had.
|
|
243
|
+
if (!this.redisService.getReadyClient()) {
|
|
244
|
+
this.logger.warn('[A2ATaskCancel] No Redis on this pod; this turn has no liveness lease and cannot be cancelled from another replica', {
|
|
245
|
+
taskId,
|
|
246
|
+
consequence: 'harmless on a single replica; on a fleet, other pods cannot observe this turn until Redis returns',
|
|
247
|
+
...projectCaughtErrorLogFields(error),
|
|
248
|
+
});
|
|
249
|
+
return;
|
|
181
250
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
251
|
+
this.logger.error('[A2ATaskCancel] Task lease has NEVER been written; other pods will read this live turn as abandoned', {
|
|
252
|
+
taskId,
|
|
253
|
+
consequence: 'tasks/get on another replica reports failed until a later refresh lands; the sweep now abstains rather than recording it durably',
|
|
254
|
+
...projectCaughtErrorLogFields(error),
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
await refresh();
|
|
259
|
+
// Clear any prior heartbeat for this id before replacing it. Unreachable today
|
|
260
|
+
// (task ids are freshly minted uuids), but an overwritten `setInterval` handle is
|
|
261
|
+
// unclearable — it would refresh a lease forever and keep a dead task looking alive.
|
|
262
|
+
const existing = this.leaseTimers.get(taskId);
|
|
263
|
+
if (existing)
|
|
264
|
+
clearInterval(existing);
|
|
265
|
+
// ── The heartbeat is installed UNCONDITIONALLY, and that is a fix, not a tidy-up ──────────
|
|
266
|
+
//
|
|
267
|
+
// This whole block used to sit behind `if (this.redisService.getReadyClient())`, so a turn
|
|
268
|
+
// that began while this pod's client was not ready got NO lease and NO retry — it stayed
|
|
269
|
+
// unobservable for its entire life even after Redis came back, and nothing was logged at all,
|
|
270
|
+
// because the failing write never even ran. That is the SILENT half of the inversion the
|
|
271
|
+
// never-written branch above documents, and it is strictly worse: a failed first write
|
|
272
|
+
// self-heals on the next 10-second refresh, an absent heartbeat never does.
|
|
273
|
+
//
|
|
274
|
+
// The cost in a genuinely Redis-less deployment is one unref'd timer per in-flight turn and a
|
|
275
|
+
// caught rejection every 10 seconds; the log is emitted once (above), and `redisService.set`
|
|
276
|
+
// builds its error without logging. That is cheap enough to buy automatic recovery.
|
|
277
|
+
const timer = setInterval(() => { void refresh(); }, A2A_TASK_LEASE_REFRESH_MS);
|
|
278
|
+
// Never hold the event loop open on a heartbeat — a draining pod must still exit.
|
|
279
|
+
timer.unref?.();
|
|
280
|
+
this.leaseTimers.set(taskId, timer);
|
|
195
281
|
// Subscriber setup happens AFTER the lease exists (see the note above). Not awaited:
|
|
196
282
|
// a slow Redis handshake must not delay the turn, and a cancel arriving before the
|
|
197
283
|
// subscription is live is already handled — `requestCancel` aborts a locally-owned turn
|
|
@@ -204,6 +290,14 @@ let A2ATaskCancellationBackendService = class A2ATaskCancellationBackendService
|
|
|
204
290
|
*
|
|
205
291
|
* Dropping the lease EAGERLY matters — a terminal task with a live lease would look
|
|
206
292
|
* like it is still executing to anything reading liveness.
|
|
293
|
+
*
|
|
294
|
+
* The ESTABLISHMENT marker is deliberately NOT dropped with it. The two record different kinds
|
|
295
|
+
* of fact: the lease says "a pod is working this NOW" and stops being true the instant the turn
|
|
296
|
+
* unwinds, while the marker says "this task's liveness was observable", which stays true
|
|
297
|
+
* afterwards. Keeping it also covers the one case that would otherwise regress — a turn that
|
|
298
|
+
* finished but whose terminal write did not land — since the row is then genuinely abandoned and
|
|
299
|
+
* the sweep can say so on its first pass instead of waiting for corroboration. It expires on its
|
|
300
|
+
* own TTL, so nothing accumulates.
|
|
207
301
|
*/
|
|
208
302
|
async endTurn(taskId) {
|
|
209
303
|
const timer = this.leaseTimers.get(taskId);
|
|
@@ -274,6 +368,68 @@ let A2ATaskCancellationBackendService = class A2ATaskCancellationBackendService
|
|
|
274
368
|
return true;
|
|
275
369
|
}
|
|
276
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* WHY is this task's lease absent — and may that absence be turned into a durable verdict?
|
|
373
|
+
*
|
|
374
|
+
* Asked by the abandoned-task sweep, and only by it, AFTER {@link isTurnAlive} has already
|
|
375
|
+
* answered "no lease". `isTurnAlive` returns a boolean because every other consumer only needs
|
|
376
|
+
* to know whether to keep waiting; the sweep is the one caller that writes a TERMINAL status,
|
|
377
|
+
* so it is the one caller that must be able to tell a verdict from a failed enquiry.
|
|
378
|
+
*
|
|
379
|
+
* ## The case this closes, which no existing guard catches
|
|
380
|
+
*
|
|
381
|
+
* `isLeaseMechanismWritable` is evaluated on the SWEEP's pod. A per-pod failure — the executing
|
|
382
|
+
* pod's Redis connection is broken while the sweep's is fine — passes it, `isTurnAlive`
|
|
383
|
+
* truthfully reports no lease, and a healthy running turn is durably recorded FAILED. That
|
|
384
|
+
* inversion has no compensating pass; it is the reason this method exists.
|
|
385
|
+
*
|
|
386
|
+
* ## How the two are told apart
|
|
387
|
+
*
|
|
388
|
+
* 1. **An establishment marker** ({@link LEASE_ESTABLISHED_KEY_PREFIX}) is written beside every
|
|
389
|
+
* successful lease write and outlives it by hours. Present ⇒ a pod demonstrably held this
|
|
390
|
+
* task and stopped ⇒ `LEASE_LAPSED`, a verdict, on the very first pass. This is what keeps
|
|
391
|
+
* ordinary abandonment repaired in the same hour it happens.
|
|
392
|
+
* 2. **Otherwise the reading is indeterminate**, and the answer is TIME rather than another key:
|
|
393
|
+
* a live pod that merely failed one write rewrites its lease on the next 10-second heartbeat,
|
|
394
|
+
* so an absence that is still there a full sweep period later is not a missed write. The
|
|
395
|
+
* first pass records the observation and returns `FIRST_ABSENCE`; a later pass that still
|
|
396
|
+
* finds no lease and still finds the observation returns `CORROBORATED_ABSENCE`.
|
|
397
|
+
* 3. **If the observation can neither be read nor written, nothing was learned** —
|
|
398
|
+
* `UNDETERMINED`. It is NOT collapsed into `FIRST_ABSENCE`, because that one made progress
|
|
399
|
+
* toward a verdict and this one did not; recording it as progress would let two enquiries
|
|
400
|
+
* that both failed add up to a durable kill.
|
|
401
|
+
*
|
|
402
|
+
* Losing the medium fails toward the SAFE side in both directions: with the markers gone (a
|
|
403
|
+
* Redis restart) every absence is merely uncorroborated, so genuine abandonment is still
|
|
404
|
+
* repaired — one run later — while a healthy turn is not killed on a single reading.
|
|
405
|
+
*/
|
|
406
|
+
async corroborateAbandonment(taskId) {
|
|
407
|
+
// No client at all is the one case where this method can say nothing whatsoever. The sweep's
|
|
408
|
+
// fleet-wide abstain already refuses to run in that state, so reaching here means the client
|
|
409
|
+
// died between that probe and this row — indeterminate, by construction.
|
|
410
|
+
if (!this.redisService.getReadyClient())
|
|
411
|
+
return A2A_AbandonmentEvidence.UNDETERMINED;
|
|
412
|
+
try {
|
|
413
|
+
if (await this.redisService.exists(this.leaseEstablishedKey(taskId)))
|
|
414
|
+
return A2A_AbandonmentEvidence.LEASE_LAPSED;
|
|
415
|
+
const observationKey = this.absenceObservationKey(taskId);
|
|
416
|
+
if (await this.redisService.exists(observationKey))
|
|
417
|
+
return A2A_AbandonmentEvidence.CORROBORATED_ABSENCE;
|
|
418
|
+
// Record THIS observation so a later run can corroborate it. The write is inside the same
|
|
419
|
+
// try as the reads on purpose: an observation that was not durably recorded has not been
|
|
420
|
+
// made, and reporting `FIRST_ABSENCE` for it would let the next run corroborate against
|
|
421
|
+
// nothing.
|
|
422
|
+
await this.redisService.set(observationKey, '1', { ttl: A2A_TASK_ABSENCE_OBSERVATION_TTL_SECONDS });
|
|
423
|
+
return A2A_AbandonmentEvidence.FIRST_ABSENCE;
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
this.logger.warn('[A2ATaskCancel] Could not establish why a task lease is absent; the sweep will not act on this reading', {
|
|
427
|
+
taskId,
|
|
428
|
+
...projectCaughtErrorLogFields(error),
|
|
429
|
+
});
|
|
430
|
+
return A2A_AbandonmentEvidence.UNDETERMINED;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
277
433
|
/**
|
|
278
434
|
* Can the lease mechanism actually be WRITTEN right now?
|
|
279
435
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a2a-task-cancellation.backend.service.js","sourceRoot":"","sources":["../../../../../../src/flows-actors/a2a/services/a2a-task-cancellation.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Cross-pod A2A task cancellation.\n *\n * ## You do not need to find the executing pod\n *\n * With several backend replicas behind a load balancer, a `tasks/cancel` request\n * almost never lands on the pod that is running that task's LLM turn. The obvious\n * design — discover which pod owns it and route there — needs a pod registry, a\n * liveness view of it, and an internal call path, and it is wrong on every one of\n * those axes when a pod restarts mid-turn.\n *\n * Instead this BROADCASTS. Any pod publishes `{taskId}` to one Redis channel; every\n * pod runs a single shared subscriber; only the pod holding that `taskId` in its\n * in-process registry reacts. One connection per pod, no routing table, and a pod\n * that died simply does not answer — which is the correct behaviour, not an error to\n * handle.\n *\n * Rejected alternative: polling a Redis flag inside the token loop. That puts a GET on\n * the hottest path in the system (per N tokens, per concurrent turn) and bounds\n * cancellation latency by token cadence. Pub/sub costs nothing per token.\n *\n * ## Liveness is the same mechanism's other half\n *\n * While a pod owns a turn it refreshes a TTL'd lease key. That is what lets\n * `tasks/get` report an abandoned task honestly instead of leaving it `working`\n * forever after a pod dies — see the lease helpers below.\n */\n\nimport { inject, injectable } from 'inversify';\nimport type { RedisClientType } from 'redis';\n\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport type { RedisService } from '~wildo-backend-lib/databases/services/redis.service';\nimport { projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\n\n/** Channel every replica subscribes to. App-prefixed so tenants of one Redis never cross. */\nconst CANCEL_CHANNEL_SUFFIX = 'a2a:task:cancel';\n/** Lease key prefix — presence means \"a live pod is working this task right now\". */\nconst LEASE_KEY_PREFIX = 'a2a:task:lease:';\n\n/**\n * Lease TTL and refresh cadence. The refresh interval is deliberately well under the\n * TTL: a single missed refresh (GC pause, a slow Redis round-trip) must not make a\n * healthy turn look abandoned. Only a genuinely dead pod stops refreshing.\n */\nexport const A2A_TASK_LEASE_TTL_SECONDS = 30;\nexport const A2A_TASK_LEASE_REFRESH_MS = 10_000;\n\n@injectable()\nexport class A2ATaskCancellationBackendService {\n /** Tasks this pod is currently executing → the controller that aborts them. */\n private readonly localTurns = new Map<string, AbortController>();\n /** Lease heartbeats keyed by task id, cleared on release. */\n private readonly leaseTimers = new Map<string, NodeJS.Timeout>();\n\n private subscriber: RedisClientType | null = null;\n private subscribeStarted = false;\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.RedisService) private readonly redisService: RedisService,\n ) {}\n\n private channel(): string {\n return `${this.redisService.getAppPrefix()}${CANCEL_CHANNEL_SUFFIX}`;\n }\n\n private leaseKey(taskId: string): string {\n return `${LEASE_KEY_PREFIX}${taskId}`;\n }\n\n /**\n * Start this pod's single shared subscriber. Idempotent — safe to call from every\n * turn, so no startup ordering is required.\n *\n * `node-redis` forbids commands on a subscribed connection, so the subscriber MUST be\n * a duplicate rather than the shared client. Same pattern the WebSocket adapter uses.\n *\n * Fails OPEN by design: if Redis is unreachable the turn still runs — losing the\n * ability to cancel is strictly better than refusing to answer at all. The failure is\n * logged at ERROR because a persistent one silently disables cancellation fleet-wide.\n */\n private async ensureSubscriber(): Promise<void> {\n if (this.subscribeStarted) return;\n this.subscribeStarted = true;\n\n const client = this.redisService.getReadyClient();\n if (!client) {\n this.logger.error('[A2ATaskCancel] Redis unavailable — cross-pod cancellation is DISABLED for this pod');\n return;\n }\n\n let subscriber: RedisClientType | undefined;\n try {\n subscriber = client.duplicate() as RedisClientType;\n subscriber.on('error', (error: unknown) => {\n this.logger.error('[A2ATaskCancel] Cancel-channel subscriber error', { ...projectCaughtErrorLogFields(error) });\n });\n // REARM on a later death (review finding L-2). `subscribeStarted` was reset only inside the\n // SETUP catch, so a subscriber that connected and then dropped — a Redis restart, a failover,\n // an idle-timeout reap — logged from the handler above and was never rebuilt for the rest of\n // the pod's lifetime. Cross-pod cancellation then silently stopped working on that pod while\n // every other signal still looked healthy: the turns run, the leases refresh, and only the\n // broadcast never arrives. Clearing the latch lets the next turn rebuild it.\n subscriber.on('end', () => {\n this.logger.warn('[A2ATaskCancel] Cancel-channel subscriber closed; re-arming so the next turn rebuilds it');\n this.subscriber = undefined;\n this.subscribeStarted = false;\n });\n await subscriber.connect();\n await subscriber.subscribe(this.channel(), (message: string) => this.onCancelBroadcast(message));\n this.subscriber = subscriber;\n } catch (error) {\n // DESTROY the half-built connection before retrying. `connect()` can succeed and\n // `subscribe()` still throw, which leaves a live, unusable socket; since\n // `subscribeStarted` resets to allow a retry, every later turn would open another one\n // and leak a Redis connection per turn until the pod hit its file-descriptor limit.\n if (subscriber) {\n try { await subscriber.destroy(); } catch { /* already dead — nothing to reclaim */ }\n }\n this.subscribeStarted = false; // allow a later turn to retry\n this.logger.error('[A2ATaskCancel] Failed to subscribe to the cancel channel', { ...projectCaughtErrorLogFields(error) });\n }\n }\n\n /**\n * Handle a broadcast. Every pod receives every cancel; only the owner acts, and a pod\n * that does not own the task does nothing at all — that silence is the design, not a\n * missed message.\n */\n private onCancelBroadcast(taskId: string): void {\n const controller = this.localTurns.get(taskId);\n if (!controller) return;\n this.logger.info('[A2ATaskCancel] Aborting a locally-executing turn on broadcast', { taskId });\n controller.abort();\n }\n\n /**\n * Register a turn as executing on this pod: returns the signal to hand to the model\n * call, and starts the liveness lease.\n */\n public async beginTurn(taskId: string): Promise<AbortSignal> {\n // ORDER IS LOAD-BEARING. Register locally and write the lease BEFORE the subscriber\n // setup, which on the first turn performs a full Redis duplicate + connect + subscribe.\n // Awaiting that first would leave a window in which the task is materialised and the\n // client — which asked for a non-blocking turn precisely so it could poll at once — sees\n // a non-terminal task with no lease and is told FAILED by derive-on-read.\n const controller = new AbortController();\n this.localTurns.set(taskId, controller);\n\n const client = this.redisService.getReadyClient();\n if (client) {\n let leaseEverWritten = false;\n const refresh = async (): Promise<void> => {\n try {\n await this.redisService.set(this.leaseKey(taskId), '1', { ttl: A2A_TASK_LEASE_TTL_SECONDS });\n leaseEverWritten = true;\n } catch (error) {\n // A missed REFRESH is survivable — the TTL is several refreshes long, so the lease\n // written earlier still answers for this turn.\n //\n // A lease that was NEVER successfully written is a different thing entirely (review\n // finding A3-4), and it used to log identically. No other pod can distinguish \"the\n // write failed\" from \"the pod died\": `tasks/get` on any other replica reports this\n // healthy running turn as FAILED, and the sweep then makes that answer DURABLE. This\n // is the write-side twin of the read-side hole G2-8 closed — the JSDoc claim that\n // \"only a genuinely dead pod stops refreshing\" was false in exactly this case.\n if (leaseEverWritten) {\n this.logger.warn('[A2ATaskCancel] Lease refresh failed', { taskId, ...projectCaughtErrorLogFields(error) });\n } else {\n this.logger.error('[A2ATaskCancel] Task lease has NEVER been written; other pods will read this live turn as abandoned', {\n taskId,\n consequence: 'tasks/get on another replica reports failed, and the sweep may record it durably',\n ...projectCaughtErrorLogFields(error),\n });\n }\n }\n };\n await refresh();\n // Clear any prior heartbeat for this id before replacing it. Unreachable today\n // (task ids are freshly minted uuids), but an overwritten `setInterval` handle is\n // unclearable — it would refresh a lease forever and keep a dead task looking alive.\n const existing = this.leaseTimers.get(taskId);\n if (existing) clearInterval(existing);\n\n const timer = setInterval(() => { void refresh(); }, A2A_TASK_LEASE_REFRESH_MS);\n // Never hold the event loop open on a heartbeat — a draining pod must still exit.\n timer.unref?.();\n this.leaseTimers.set(taskId, timer);\n }\n\n // Subscriber setup happens AFTER the lease exists (see the note above). Not awaited:\n // a slow Redis handshake must not delay the turn, and a cancel arriving before the\n // subscription is live is already handled — `requestCancel` aborts a locally-owned turn\n // directly, without a round-trip.\n void this.ensureSubscriber();\n\n return controller.signal;\n }\n\n /**\n * Release a finished turn: stop the heartbeat, drop the lease, forget the controller.\n *\n * Dropping the lease EAGERLY matters — a terminal task with a live lease would look\n * like it is still executing to anything reading liveness.\n */\n public async endTurn(taskId: string): Promise<void> {\n const timer = this.leaseTimers.get(taskId);\n if (timer) {\n clearInterval(timer);\n this.leaseTimers.delete(taskId);\n }\n this.localTurns.delete(taskId);\n try {\n await this.redisService.del(this.leaseKey(taskId));\n } catch (error) {\n // The TTL reaps it anyway; this only shortens the window.\n this.logger.warn('[A2ATaskCancel] Failed to drop a task lease', { taskId, ...projectCaughtErrorLogFields(error) });\n }\n }\n\n /**\n * Ask the fleet to cancel a task.\n *\n * Returns whether the request was BROADCAST, never whether it was honoured: the owning\n * pod may be gone, or the turn may already have finished. The caller must therefore\n * treat the task record — not this return value — as the truth about cancellation,\n * which is also what the A2A spec requires (`tasks/cancel` returns the task's updated\n * state, not an acknowledgement).\n */\n public async requestCancel(taskId: string): Promise<boolean> {\n // A turn owned by THIS pod is aborted directly — no round-trip, and it still works\n // when Redis is down, which is the single-replica and local-dev case.\n const local = this.localTurns.get(taskId);\n if (local) local.abort();\n\n const client = this.redisService.getReadyClient();\n if (!client) return Boolean(local);\n\n try {\n await client.publish(this.channel(), taskId);\n return true;\n } catch (error) {\n this.logger.error('[A2ATaskCancel] Failed to broadcast a cancel', { taskId, ...projectCaughtErrorLogFields(error) });\n return Boolean(local);\n }\n }\n\n /**\n * Is some pod still working this task?\n *\n * This is the read half of the liveness design: a task whose stored status is\n * non-terminal but whose lease has expired was abandoned by a pod that died, and must\n * be reported as failed rather than left reading `working` forever.\n *\n * Fails SAFE toward \"alive\" when Redis is unreachable — reporting a healthy task as\n * abandoned because the cache blipped would be a far worse lie than a brief stale\n * `working`.\n */\n public async isTurnAlive(taskId: string): Promise<boolean> {\n if (this.localTurns.has(taskId)) return true;\n // Redis ABSENT is not evidence of death. `RedisService.exists` RETURNS FALSE when there\n // is no client rather than throwing, so the catch below never fired for that case and the\n // documented \"fails safe toward alive\" was untrue: with Redis down, every task on another\n // pod would have been reported FAILED. Check the client explicitly.\n if (!this.redisService.getReadyClient()) return true;\n try {\n return await this.redisService.exists(this.leaseKey(taskId));\n } catch {\n return true;\n }\n }\n\n /**\n * Can the lease mechanism actually be WRITTEN right now?\n *\n * Read by the abandoned-task sweep before it repairs anything, and only by it (review\n * finding A3-4). The distinction that makes this necessary: `isTurnAlive` fails safe by\n * answering \"alive\", so a degraded Redis costs a stale `working` — recoverable, and the next\n * poll corrects it. The SWEEP is the one consumer that turns a liveness answer into a\n * DURABLE terminal status, so it is the one that must refuse to act on a signal it cannot\n * trust.\n *\n * A WRITE probe specifically, not a read: the dangerous failure mode is asymmetric — writes\n * failing while reads succeed (a read-only replica, an OOM/quota condition). Under that\n * failure every live turn's lease is missing while `exists` cheerfully reports it absent, so\n * a read-based health check would pass and the sweep would fail every healthy task in the\n * fleet. Probing the exact capability whose loss causes the false reading is the only check\n * that catches it.\n */\n public async isLeaseMechanismWritable(): Promise<boolean> {\n if (!this.redisService.getReadyClient()) return false;\n const probeKey = this.leaseKey('__sweep-health-probe__');\n try {\n await this.redisService.set(probeKey, '1', { ttl: A2A_TASK_LEASE_TTL_SECONDS });\n const present = await this.redisService.exists(probeKey);\n await this.redisService.del(probeKey).catch(() => {});\n return present;\n } catch {\n return false;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"a2a-task-cancellation.backend.service.js","sourceRoot":"","sources":["../../../../../../src/flows-actors/a2a/services/a2a-task-cancellation.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Cross-pod A2A task cancellation.\n *\n * ## You do not need to find the executing pod\n *\n * With several backend replicas behind a load balancer, a `tasks/cancel` request\n * almost never lands on the pod that is running that task's LLM turn. The obvious\n * design — discover which pod owns it and route there — needs a pod registry, a\n * liveness view of it, and an internal call path, and it is wrong on every one of\n * those axes when a pod restarts mid-turn.\n *\n * Instead this BROADCASTS. Any pod publishes `{taskId}` to one Redis channel; every\n * pod runs a single shared subscriber; only the pod holding that `taskId` in its\n * in-process registry reacts. One connection per pod, no routing table, and a pod\n * that died simply does not answer — which is the correct behaviour, not an error to\n * handle.\n *\n * Rejected alternative: polling a Redis flag inside the token loop. That puts a GET on\n * the hottest path in the system (per N tokens, per concurrent turn) and bounds\n * cancellation latency by token cadence. Pub/sub costs nothing per token.\n *\n * ## Liveness is the same mechanism's other half\n *\n * While a pod owns a turn it refreshes a TTL'd lease key. That is what lets\n * `tasks/get` report an abandoned task honestly instead of leaving it `working`\n * forever after a pod dies — see the lease helpers below.\n *\n * An absent lease is NOT self-explanatory, though, and reading it as death is an inversion that\n * costs real work: a pod that could not write the lease looks exactly like a pod that died. So\n * every successful lease write also leaves a long-lived ESTABLISHMENT marker, and\n * `corroborateAbandonment` is what turns \"no lease\" into either a verdict or an admission that\n * nothing was learned. Only the sweep — the one consumer that makes a liveness answer DURABLE —\n * asks that question.\n */\n\nimport { inject, injectable } from 'inversify';\nimport type { RedisClientType } from 'redis';\n\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport type { RedisService } from '~wildo-backend-lib/databases/services/redis.service';\nimport { projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport { A2A_AbandonmentEvidence } from '~wildo-backend-lib/flows-actors/a2a/models/a2a.backend.schemas';\n\n/** Channel every replica subscribes to. App-prefixed so tenants of one Redis never cross. */\nconst CANCEL_CHANNEL_SUFFIX = 'a2a:task:cancel';\n/** Lease key prefix — presence means \"a live pod is working this task right now\". */\nconst LEASE_KEY_PREFIX = 'a2a:task:lease:';\n/**\n * ESTABLISHMENT marker prefix — presence means \"this task's liveness WAS observable at some point\n * recently\", which is a different fact from \"it is alive now\" and has a different lifetime.\n *\n * It is what makes an absent lease MEAN something (see {@link A2A_AbandonmentEvidence}). Written\n * by the same code path and in the same failure domain as the lease itself, so it can only exist\n * if a write actually succeeded — which is exactly the property being recorded.\n */\nconst LEASE_ESTABLISHED_KEY_PREFIX = 'a2a:task:leased-once:';\n/**\n * The sweep's own note that it has already seen one unexplained absence for a task. Written by the\n * SWEEP's pod, whose write capability `isLeaseMechanismWritable` proved moments earlier — so the\n * medium is known-good at the point of use, unlike the lease itself.\n */\nconst ABANDONMENT_OBSERVATION_KEY_PREFIX = 'a2a:task:absence-seen:';\n\n/**\n * Lease TTL and refresh cadence. The refresh interval is deliberately well under the\n * TTL: a single missed refresh (GC pause, a slow Redis round-trip) must not make a\n * healthy turn look abandoned. Only a genuinely dead pod stops refreshing.\n */\nexport const A2A_TASK_LEASE_TTL_SECONDS = 30;\nexport const A2A_TASK_LEASE_REFRESH_MS = 10_000;\n\n/**\n * How long the establishment marker outlives its last refresh.\n *\n * Sized to comfortably span the sweep's grace window plus its hourly period, so a pod that dies\n * mid-turn is still recognisable as HAVING held the task when the next sweep looks. It is a\n * timing optimisation, never a correctness requirement: if it lapses, the reading degrades to\n * {@link A2A_AbandonmentEvidence.FIRST_ABSENCE} and the row is repaired one run later instead of\n * on the first — which is the direction this whole mechanism errs in anyway.\n */\nexport const A2A_TASK_LEASE_ESTABLISHED_TTL_SECONDS = 6 * 60 * 60;\n\n/**\n * How long one unexplained absence stands as corroboration for the next run.\n *\n * MUST exceed the sweep's period or no observation ever survives to be corroborated and nothing\n * is ever repaired through that path; generous beyond it so a skipped run (the fleet-wide abstain)\n * does not reset the count. Nothing clears it on recovery, and it does not need clearing: a task\n * whose pod recovered answers ALIVE on the lease long before this is consulted, and once its lease\n * lapses for real the establishment marker gives the verdict directly.\n */\nexport const A2A_TASK_ABSENCE_OBSERVATION_TTL_SECONDS = 3 * 60 * 60;\n\n@injectable()\nexport class A2ATaskCancellationBackendService {\n /** Tasks this pod is currently executing → the controller that aborts them. */\n private readonly localTurns = new Map<string, AbortController>();\n /** Lease heartbeats keyed by task id, cleared on release. */\n private readonly leaseTimers = new Map<string, NodeJS.Timeout>();\n\n private subscriber: RedisClientType | null = null;\n private subscribeStarted = false;\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.RedisService) private readonly redisService: RedisService,\n ) {}\n\n private channel(): string {\n return `${this.redisService.getAppPrefix()}${CANCEL_CHANNEL_SUFFIX}`;\n }\n\n private leaseKey(taskId: string): string {\n return `${LEASE_KEY_PREFIX}${taskId}`;\n }\n\n private leaseEstablishedKey(taskId: string): string {\n return `${LEASE_ESTABLISHED_KEY_PREFIX}${taskId}`;\n }\n\n private absenceObservationKey(taskId: string): string {\n return `${ABANDONMENT_OBSERVATION_KEY_PREFIX}${taskId}`;\n }\n\n /**\n * Start this pod's single shared subscriber. Idempotent — safe to call from every\n * turn, so no startup ordering is required.\n *\n * `node-redis` forbids commands on a subscribed connection, so the subscriber MUST be\n * a duplicate rather than the shared client. Same pattern the WebSocket adapter uses.\n *\n * Fails OPEN by design: if Redis is unreachable the turn still runs — losing the\n * ability to cancel is strictly better than refusing to answer at all. The failure is\n * logged at ERROR because a persistent one silently disables cancellation fleet-wide.\n */\n private async ensureSubscriber(): Promise<void> {\n if (this.subscribeStarted) return;\n this.subscribeStarted = true;\n\n const client = this.redisService.getReadyClient();\n if (!client) {\n this.logger.error('[A2ATaskCancel] Redis unavailable — cross-pod cancellation is DISABLED for this pod');\n return;\n }\n\n let subscriber: RedisClientType | undefined;\n try {\n subscriber = client.duplicate() as RedisClientType;\n subscriber.on('error', (error: unknown) => {\n this.logger.error('[A2ATaskCancel] Cancel-channel subscriber error', { ...projectCaughtErrorLogFields(error) });\n });\n // REARM on a later death (review finding L-2). `subscribeStarted` was reset only inside the\n // SETUP catch, so a subscriber that connected and then dropped — a Redis restart, a failover,\n // an idle-timeout reap — logged from the handler above and was never rebuilt for the rest of\n // the pod's lifetime. Cross-pod cancellation then silently stopped working on that pod while\n // every other signal still looked healthy: the turns run, the leases refresh, and only the\n // broadcast never arrives. Clearing the latch lets the next turn rebuild it.\n subscriber.on('end', () => {\n this.logger.warn('[A2ATaskCancel] Cancel-channel subscriber closed; re-arming so the next turn rebuilds it');\n this.subscriber = undefined;\n this.subscribeStarted = false;\n });\n await subscriber.connect();\n await subscriber.subscribe(this.channel(), (message: string) => this.onCancelBroadcast(message));\n this.subscriber = subscriber;\n } catch (error) {\n // DESTROY the half-built connection before retrying. `connect()` can succeed and\n // `subscribe()` still throw, which leaves a live, unusable socket; since\n // `subscribeStarted` resets to allow a retry, every later turn would open another one\n // and leak a Redis connection per turn until the pod hit its file-descriptor limit.\n if (subscriber) {\n try { await subscriber.destroy(); } catch { /* already dead — nothing to reclaim */ }\n }\n this.subscribeStarted = false; // allow a later turn to retry\n this.logger.error('[A2ATaskCancel] Failed to subscribe to the cancel channel', { ...projectCaughtErrorLogFields(error) });\n }\n }\n\n /**\n * Handle a broadcast. Every pod receives every cancel; only the owner acts, and a pod\n * that does not own the task does nothing at all — that silence is the design, not a\n * missed message.\n */\n private onCancelBroadcast(taskId: string): void {\n const controller = this.localTurns.get(taskId);\n if (!controller) return;\n this.logger.info('[A2ATaskCancel] Aborting a locally-executing turn on broadcast', { taskId });\n controller.abort();\n }\n\n /**\n * Register a turn as executing on this pod: returns the signal to hand to the model\n * call, and starts the liveness lease.\n */\n public async beginTurn(taskId: string): Promise<AbortSignal> {\n // ORDER IS LOAD-BEARING. Register locally and write the lease BEFORE the subscriber\n // setup, which on the first turn performs a full Redis duplicate + connect + subscribe.\n // Awaiting that first would leave a window in which the task is materialised and the\n // client — which asked for a non-blocking turn precisely so it could poll at once — sees\n // a non-terminal task with no lease and is told FAILED by derive-on-read.\n const controller = new AbortController();\n this.localTurns.set(taskId, controller);\n\n let leaseEverWritten = false;\n let unwritableAlreadyReported = false;\n const refresh = async (): Promise<void> => {\n try {\n await this.redisService.set(this.leaseKey(taskId), '1', { ttl: A2A_TASK_LEASE_TTL_SECONDS });\n // The ESTABLISHMENT marker rides the same write, in the same failure domain, and is what\n // makes a LATER absence of the lease mean something: a reader that finds no lease but\n // finds this knows a pod really did hold the task and stopped, rather than that this\n // task's liveness was never observable at all. Written every refresh so a long turn keeps\n // it alive; deliberately NOT written before the lease, so it can never claim an\n // establishment that did not happen.\n await this.redisService.set(this.leaseEstablishedKey(taskId), '1', { ttl: A2A_TASK_LEASE_ESTABLISHED_TTL_SECONDS });\n leaseEverWritten = true;\n } catch (error) {\n // A missed REFRESH is survivable — the TTL is several refreshes long, so the lease\n // written earlier still answers for this turn.\n //\n // A lease that was NEVER successfully written is a different thing entirely (review\n // finding A3-4), and it used to log identically. No other pod can distinguish \"the\n // write failed\" from \"the pod died\": `tasks/get` on any other replica reports this\n // healthy running turn as FAILED, and the sweep then makes that answer DURABLE. This\n // is the write-side twin of the read-side hole G2-8 closed — the JSDoc claim that\n // \"only a genuinely dead pod stops refreshing\" was false in exactly this case.\n if (leaseEverWritten) {\n this.logger.warn('[A2ATaskCancel] Lease refresh failed', { taskId, ...projectCaughtErrorLogFields(error) });\n return;\n }\n // ONCE per turn, not once per heartbeat. The heartbeat now runs even with no Redis at all\n // (see below), so an unconditional log here would emit a line every 10 seconds for every\n // concurrent turn of a Redis-less deployment — which is how a channel that carries a real\n // signal gets tuned out.\n if (unwritableAlreadyReported) return;\n unwritableAlreadyReported = true;\n // The two causes are logged at DIFFERENT levels because one is a configuration and the\n // other is a fault. No client on this pod is the supported single-replica / local-dev\n // shape: `isTurnAlive` fails safe toward \"alive\" there and nothing reads liveness across\n // pods, so it is a WARN. A client that is present and REJECTED the write is the dangerous\n // asymmetry — this pod is partitioned from a liveness plane every other replica can still\n // read — and it keeps the ERROR level it had.\n if (!this.redisService.getReadyClient()) {\n this.logger.warn('[A2ATaskCancel] No Redis on this pod; this turn has no liveness lease and cannot be cancelled from another replica', {\n taskId,\n consequence: 'harmless on a single replica; on a fleet, other pods cannot observe this turn until Redis returns',\n ...projectCaughtErrorLogFields(error),\n });\n return;\n }\n this.logger.error('[A2ATaskCancel] Task lease has NEVER been written; other pods will read this live turn as abandoned', {\n taskId,\n consequence: 'tasks/get on another replica reports failed until a later refresh lands; the sweep now abstains rather than recording it durably',\n ...projectCaughtErrorLogFields(error),\n });\n }\n };\n await refresh();\n // Clear any prior heartbeat for this id before replacing it. Unreachable today\n // (task ids are freshly minted uuids), but an overwritten `setInterval` handle is\n // unclearable — it would refresh a lease forever and keep a dead task looking alive.\n const existing = this.leaseTimers.get(taskId);\n if (existing) clearInterval(existing);\n\n // ── The heartbeat is installed UNCONDITIONALLY, and that is a fix, not a tidy-up ──────────\n //\n // This whole block used to sit behind `if (this.redisService.getReadyClient())`, so a turn\n // that began while this pod's client was not ready got NO lease and NO retry — it stayed\n // unobservable for its entire life even after Redis came back, and nothing was logged at all,\n // because the failing write never even ran. That is the SILENT half of the inversion the\n // never-written branch above documents, and it is strictly worse: a failed first write\n // self-heals on the next 10-second refresh, an absent heartbeat never does.\n //\n // The cost in a genuinely Redis-less deployment is one unref'd timer per in-flight turn and a\n // caught rejection every 10 seconds; the log is emitted once (above), and `redisService.set`\n // builds its error without logging. That is cheap enough to buy automatic recovery.\n const timer = setInterval(() => { void refresh(); }, A2A_TASK_LEASE_REFRESH_MS);\n // Never hold the event loop open on a heartbeat — a draining pod must still exit.\n timer.unref?.();\n this.leaseTimers.set(taskId, timer);\n\n // Subscriber setup happens AFTER the lease exists (see the note above). Not awaited:\n // a slow Redis handshake must not delay the turn, and a cancel arriving before the\n // subscription is live is already handled — `requestCancel` aborts a locally-owned turn\n // directly, without a round-trip.\n void this.ensureSubscriber();\n\n return controller.signal;\n }\n\n /**\n * Release a finished turn: stop the heartbeat, drop the lease, forget the controller.\n *\n * Dropping the lease EAGERLY matters — a terminal task with a live lease would look\n * like it is still executing to anything reading liveness.\n *\n * The ESTABLISHMENT marker is deliberately NOT dropped with it. The two record different kinds\n * of fact: the lease says \"a pod is working this NOW\" and stops being true the instant the turn\n * unwinds, while the marker says \"this task's liveness was observable\", which stays true\n * afterwards. Keeping it also covers the one case that would otherwise regress — a turn that\n * finished but whose terminal write did not land — since the row is then genuinely abandoned and\n * the sweep can say so on its first pass instead of waiting for corroboration. It expires on its\n * own TTL, so nothing accumulates.\n */\n public async endTurn(taskId: string): Promise<void> {\n const timer = this.leaseTimers.get(taskId);\n if (timer) {\n clearInterval(timer);\n this.leaseTimers.delete(taskId);\n }\n this.localTurns.delete(taskId);\n try {\n await this.redisService.del(this.leaseKey(taskId));\n } catch (error) {\n // The TTL reaps it anyway; this only shortens the window.\n this.logger.warn('[A2ATaskCancel] Failed to drop a task lease', { taskId, ...projectCaughtErrorLogFields(error) });\n }\n }\n\n /**\n * Ask the fleet to cancel a task.\n *\n * Returns whether the request was BROADCAST, never whether it was honoured: the owning\n * pod may be gone, or the turn may already have finished. The caller must therefore\n * treat the task record — not this return value — as the truth about cancellation,\n * which is also what the A2A spec requires (`tasks/cancel` returns the task's updated\n * state, not an acknowledgement).\n */\n public async requestCancel(taskId: string): Promise<boolean> {\n // A turn owned by THIS pod is aborted directly — no round-trip, and it still works\n // when Redis is down, which is the single-replica and local-dev case.\n const local = this.localTurns.get(taskId);\n if (local) local.abort();\n\n const client = this.redisService.getReadyClient();\n if (!client) return Boolean(local);\n\n try {\n await client.publish(this.channel(), taskId);\n return true;\n } catch (error) {\n this.logger.error('[A2ATaskCancel] Failed to broadcast a cancel', { taskId, ...projectCaughtErrorLogFields(error) });\n return Boolean(local);\n }\n }\n\n /**\n * Is some pod still working this task?\n *\n * This is the read half of the liveness design: a task whose stored status is\n * non-terminal but whose lease has expired was abandoned by a pod that died, and must\n * be reported as failed rather than left reading `working` forever.\n *\n * Fails SAFE toward \"alive\" when Redis is unreachable — reporting a healthy task as\n * abandoned because the cache blipped would be a far worse lie than a brief stale\n * `working`.\n */\n public async isTurnAlive(taskId: string): Promise<boolean> {\n if (this.localTurns.has(taskId)) return true;\n // Redis ABSENT is not evidence of death. `RedisService.exists` RETURNS FALSE when there\n // is no client rather than throwing, so the catch below never fired for that case and the\n // documented \"fails safe toward alive\" was untrue: with Redis down, every task on another\n // pod would have been reported FAILED. Check the client explicitly.\n if (!this.redisService.getReadyClient()) return true;\n try {\n return await this.redisService.exists(this.leaseKey(taskId));\n } catch {\n return true;\n }\n }\n\n /**\n * WHY is this task's lease absent — and may that absence be turned into a durable verdict?\n *\n * Asked by the abandoned-task sweep, and only by it, AFTER {@link isTurnAlive} has already\n * answered \"no lease\". `isTurnAlive` returns a boolean because every other consumer only needs\n * to know whether to keep waiting; the sweep is the one caller that writes a TERMINAL status,\n * so it is the one caller that must be able to tell a verdict from a failed enquiry.\n *\n * ## The case this closes, which no existing guard catches\n *\n * `isLeaseMechanismWritable` is evaluated on the SWEEP's pod. A per-pod failure — the executing\n * pod's Redis connection is broken while the sweep's is fine — passes it, `isTurnAlive`\n * truthfully reports no lease, and a healthy running turn is durably recorded FAILED. That\n * inversion has no compensating pass; it is the reason this method exists.\n *\n * ## How the two are told apart\n *\n * 1. **An establishment marker** ({@link LEASE_ESTABLISHED_KEY_PREFIX}) is written beside every\n * successful lease write and outlives it by hours. Present ⇒ a pod demonstrably held this\n * task and stopped ⇒ `LEASE_LAPSED`, a verdict, on the very first pass. This is what keeps\n * ordinary abandonment repaired in the same hour it happens.\n * 2. **Otherwise the reading is indeterminate**, and the answer is TIME rather than another key:\n * a live pod that merely failed one write rewrites its lease on the next 10-second heartbeat,\n * so an absence that is still there a full sweep period later is not a missed write. The\n * first pass records the observation and returns `FIRST_ABSENCE`; a later pass that still\n * finds no lease and still finds the observation returns `CORROBORATED_ABSENCE`.\n * 3. **If the observation can neither be read nor written, nothing was learned** —\n * `UNDETERMINED`. It is NOT collapsed into `FIRST_ABSENCE`, because that one made progress\n * toward a verdict and this one did not; recording it as progress would let two enquiries\n * that both failed add up to a durable kill.\n *\n * Losing the medium fails toward the SAFE side in both directions: with the markers gone (a\n * Redis restart) every absence is merely uncorroborated, so genuine abandonment is still\n * repaired — one run later — while a healthy turn is not killed on a single reading.\n */\n public async corroborateAbandonment(taskId: string): Promise<A2A_AbandonmentEvidence> {\n // No client at all is the one case where this method can say nothing whatsoever. The sweep's\n // fleet-wide abstain already refuses to run in that state, so reaching here means the client\n // died between that probe and this row — indeterminate, by construction.\n if (!this.redisService.getReadyClient()) return A2A_AbandonmentEvidence.UNDETERMINED;\n\n try {\n if (await this.redisService.exists(this.leaseEstablishedKey(taskId))) return A2A_AbandonmentEvidence.LEASE_LAPSED;\n\n const observationKey = this.absenceObservationKey(taskId);\n if (await this.redisService.exists(observationKey)) return A2A_AbandonmentEvidence.CORROBORATED_ABSENCE;\n\n // Record THIS observation so a later run can corroborate it. The write is inside the same\n // try as the reads on purpose: an observation that was not durably recorded has not been\n // made, and reporting `FIRST_ABSENCE` for it would let the next run corroborate against\n // nothing.\n await this.redisService.set(observationKey, '1', { ttl: A2A_TASK_ABSENCE_OBSERVATION_TTL_SECONDS });\n return A2A_AbandonmentEvidence.FIRST_ABSENCE;\n } catch (error) {\n this.logger.warn('[A2ATaskCancel] Could not establish why a task lease is absent; the sweep will not act on this reading', {\n taskId,\n ...projectCaughtErrorLogFields(error),\n });\n return A2A_AbandonmentEvidence.UNDETERMINED;\n }\n }\n\n /**\n * Can the lease mechanism actually be WRITTEN right now?\n *\n * Read by the abandoned-task sweep before it repairs anything, and only by it (review\n * finding A3-4). The distinction that makes this necessary: `isTurnAlive` fails safe by\n * answering \"alive\", so a degraded Redis costs a stale `working` — recoverable, and the next\n * poll corrects it. The SWEEP is the one consumer that turns a liveness answer into a\n * DURABLE terminal status, so it is the one that must refuse to act on a signal it cannot\n * trust.\n *\n * A WRITE probe specifically, not a read: the dangerous failure mode is asymmetric — writes\n * failing while reads succeed (a read-only replica, an OOM/quota condition). Under that\n * failure every live turn's lease is missing while `exists` cheerfully reports it absent, so\n * a read-based health check would pass and the sweep would fail every healthy task in the\n * fleet. Probing the exact capability whose loss causes the false reading is the only check\n * that catches it.\n */\n public async isLeaseMechanismWritable(): Promise<boolean> {\n if (!this.redisService.getReadyClient()) return false;\n const probeKey = this.leaseKey('__sweep-health-probe__');\n try {\n await this.redisService.set(probeKey, '1', { ttl: A2A_TASK_LEASE_TTL_SECONDS });\n const present = await this.redisService.exists(probeKey);\n await this.redisService.del(probeKey).catch(() => {});\n return present;\n } catch {\n return false;\n }\n }\n}\n"]}
|
|
@@ -234,8 +234,14 @@ export declare class A2ATaskBackendService {
|
|
|
234
234
|
* Best-effort by the same reasoning as {@link materialiseTask}: the work itself has
|
|
235
235
|
* already happened, so failing to record its outcome must not convert a successful
|
|
236
236
|
* turn into an error the client sees.
|
|
237
|
+
*
|
|
238
|
+
* `reclaimAbandonedVerdict` is the ONE case in which a terminal status may be moved — see the
|
|
239
|
+
* block that uses it. It is opt-in per call site rather than a widened compare-and-swap set
|
|
240
|
+
* precisely so `tasks/cancel` can never reach it.
|
|
237
241
|
*/
|
|
238
|
-
advanceTask(owner: ConversationalOwnerScope, taskId: string, status: FlowsActors_Status
|
|
242
|
+
advanceTask(owner: ConversationalOwnerScope, taskId: string, status: FlowsActors_Status, options?: {
|
|
243
|
+
reclaimAbandonedVerdict?: boolean;
|
|
244
|
+
}): Promise<A2A_TaskTransitionOutcome>;
|
|
239
245
|
/**
|
|
240
246
|
* Read one task as the protocol object — backs `tasks/get`.
|
|
241
247
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a2a-task.backend.service.d.ts","sourceRoot":"","sources":["../../../../../../src/flows-actors/a2a/services/a2a-task.backend.service.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"a2a-task.backend.service.d.ts","sourceRoot":"","sources":["../../../../../../src/flows-actors/a2a/services/a2a-task.backend.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -349,8 +349,12 @@ let A2ATaskBackendService = class A2ATaskBackendService {
|
|
|
349
349
|
* Best-effort by the same reasoning as {@link materialiseTask}: the work itself has
|
|
350
350
|
* already happened, so failing to record its outcome must not convert a successful
|
|
351
351
|
* turn into an error the client sees.
|
|
352
|
+
*
|
|
353
|
+
* `reclaimAbandonedVerdict` is the ONE case in which a terminal status may be moved — see the
|
|
354
|
+
* block that uses it. It is opt-in per call site rather than a widened compare-and-swap set
|
|
355
|
+
* precisely so `tasks/cancel` can never reach it.
|
|
352
356
|
*/
|
|
353
|
-
async advanceTask(owner, taskId, status) {
|
|
357
|
+
async advanceTask(owner, taskId, status, options) {
|
|
354
358
|
// Returns whether the transition ACTUALLY happened (review finding G5-4). It used to return
|
|
355
359
|
// `void`, which discarded the compare-and-swap's answer — so `tasks/cancel` could have its
|
|
356
360
|
// write correctly refused by the CAS and still reply HTTP 200 with a `completed` task. That is
|
|
@@ -428,6 +432,54 @@ let A2ATaskBackendService = class A2ATaskBackendService {
|
|
|
428
432
|
if (!updated) {
|
|
429
433
|
const current = await this.systemAccess.readAsSystem(resolved.resourceType, { ...resolved.ownerFields, taskId }, { scopeContext: resolved.scopeContext });
|
|
430
434
|
if (current) {
|
|
435
|
+
// ── RECLAIMING a task the abandoned-task sweep killed underneath a live turn ─────────
|
|
436
|
+
//
|
|
437
|
+
// Until this existed there was NO way back from a wrong sweep verdict. The sweep can
|
|
438
|
+
// only ever conclude "abandoned" from the ABSENCE of a liveness lease, and a pod whose
|
|
439
|
+
// Redis writes are failing produces exactly that absence while running the turn
|
|
440
|
+
// perfectly — so the sweep records FAILED, the client is told FAILED, and when the turn
|
|
441
|
+
// then finishes for real its own outcome write is refused by the compare-and-swap and
|
|
442
|
+
// the answer is discarded. A derived verdict outranking an observed fact is backwards.
|
|
443
|
+
//
|
|
444
|
+
// The turn is the AUTHORITATIVE party here: it ran the work. So its own outcome write —
|
|
445
|
+
// and only that one — may move the task off a FAILED it did not write.
|
|
446
|
+
//
|
|
447
|
+
// Why that is safe, enumerated rather than assumed. Exactly THREE sites write FAILED to
|
|
448
|
+
// a task row: this service's two callers in `runTurnAndAdvanceTask` (the `turn.kind ===
|
|
449
|
+
// 'error'` arm and its `catch`, which are mutually exclusive and run at most once per
|
|
450
|
+
// turn) and the sweep's `updateAsSystem`. So a turn whose own outcome write finds FAILED
|
|
451
|
+
// stored did not put it there — the sweep did. Everything else is untouched:
|
|
452
|
+
// • CANCELLED is NOT in the reclaim filter, so a human's stop can never be overwritten
|
|
453
|
+
// — that is the one terminal state whose whole point is that it is a decision.
|
|
454
|
+
// • COMPLETED is not either, so a finished result stays final.
|
|
455
|
+
// • `tasks/cancel` never passes the flag, so no client-facing verb can reach this.
|
|
456
|
+
// If a fourth writer of FAILED ever appears, it belongs in this list or the reasoning
|
|
457
|
+
// above stops holding.
|
|
458
|
+
if (options?.reclaimAbandonedVerdict && current.status === FlowsActors_Status.FAILED && status !== FlowsActors_Status.FAILED) {
|
|
459
|
+
const reclaimed = await this.systemAccess.updateAsSystem(resolved.resourceType,
|
|
460
|
+
// Filtered on FAILED, not merely attempted: that is what makes the log below a
|
|
461
|
+
// statement of fact rather than an inference, and it keeps this a compare-and-swap
|
|
462
|
+
// so a genuine CANCELLED landing in between still wins.
|
|
463
|
+
{ ...resolved.ownerFields, taskId, status: FlowsActors_Status.FAILED }, { status, ...(isTerminalA2ATaskStatus(status) ? { finishedAt: new Date() } : {}) }, { scopeContext: resolved.scopeContext });
|
|
464
|
+
if (reclaimed) {
|
|
465
|
+
// WARN, and loudly: a reclaim means the sweep declared a LIVE turn dead. The row is
|
|
466
|
+
// now right, but the fleet has a pod that cannot write its liveness leases, and this
|
|
467
|
+
// is the only place that fact surfaces where an operator will see it — the owning
|
|
468
|
+
// pod's own error lands on the pod nobody is watching.
|
|
469
|
+
this.logger.warn('[A2ATask] Reclaimed a task the abandoned-task sweep had failed; the turn was alive after all', {
|
|
470
|
+
taskId, reclaimedTo: status,
|
|
471
|
+
consequence: 'the sweep acted on a missing liveness lease for a running turn — check that every pod can write Redis',
|
|
472
|
+
});
|
|
473
|
+
void this.pushDispatcher
|
|
474
|
+
.dispatchTaskUpdate(owner, this.toOutboundTask({ ...reclaimed, status }), reclaimed.pushNotificationConfigs, reclaimed.resourceServerInstanceRef, reclaimed.machineCredentialId)
|
|
475
|
+
.catch((error) => {
|
|
476
|
+
this.logger.warn('[A2ATask] Push dispatch rejected despite its no-throw contract', {
|
|
477
|
+
taskId, ...projectCaughtErrorLogFields(error),
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
return A2A_TaskTransitionOutcome.ADVANCED;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
431
483
|
this.logger.info('[A2ATask] Task already reached a terminal state; the later transition was refused', {
|
|
432
484
|
taskId, attemptedStatus: status, storedStatus: current.status,
|
|
433
485
|
});
|