@wildo-ai/saas-backend-lib 1.1.3 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/__tests__/fixture-deep-partial.d.ts.map +1 -1
- package/dist/esm/__tests__/integration/redis-integration-gate.d.ts.map +1 -1
- package/dist/esm/__tests__/setup.d.ts.map +1 -1
- package/dist/esm/__tests__/test-container.d.ts.map +1 -1
- package/dist/esm/applications/models/applications.backend.schemas.d.ts.map +1 -1
- package/dist/esm/applications/seeds/application-metadata-defaults.seeds.d.ts.map +1 -1
- 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.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.map +1 -1
- package/dist/esm/base-classes/models/repositories.backend.schemas.d.ts.map +1 -1
- package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.d.ts +1 -1
- package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/batches/batches-cronjobs-custom-execution.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/batches/batches-cronjobs-executor.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/batches/batches-cronjobs-resource-execution.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/batches/child-lifecycle-teardown.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/batches/child-lifecycle-teardown.batch.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.js +12 -1
- package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.js.map +1 -1
- 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.map +1 -1
- package/dist/esm/base-classes/services/batches/resource-retention-sweep.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/batches/suspension-reactivation-sweep.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/controllers/abstract-controller.backend.service.d.ts.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.map +1 -1
- package/dist/esm/base-classes/services/controllers/controllers-registry-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/controllers/controllers-registry-handler.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/controllers/utils/audit-access-fields.backend.utils.d.ts.map +1 -1
- package/dist/esm/base-classes/services/controllers/utils/operation-response-serializer.backend.utils.d.ts.map +1 -1
- package/dist/esm/base-classes/services/controllers/validate-field-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/__tests__/method-span-scan.guard-helpers.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/__tests__/mock-repositories-registry-handler.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/field-clearing-partition.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-filter-translation.backend.d.ts.map +1 -1
- 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 +13 -4
- 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-query.backend.d.ts.map +1 -1
- 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 +17 -0
- 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.map +1 -1
- 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.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-row-projection.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/http-api-subject-erasure-effect.backend.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/odata-query-compiler.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/odoo-jsonrpc-compiler.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/http-api/rest-json-query-compiler.backend.d.ts.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.map +1 -1
- package/dist/esm/base-classes/services/repositories/introspection/introspection-resource-repository.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/introspection/introspection-resource-source.backend.port.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.d.ts +57 -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 +95 -2
- 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.map +1 -1
- package/dist/esm/base-classes/services/repositories/repository-guarded-mutation.backend.types.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.d.ts +5 -2
- 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 +14 -3
- package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/repository-version-metadata.backend.utils.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/resource-write-integrity.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/seed-row-default-materialization.backend.d.ts +72 -0
- package/dist/esm/base-classes/services/repositories/seed-row-default-materialization.backend.d.ts.map +1 -0
- package/dist/esm/base-classes/services/repositories/seed-row-default-materialization.backend.js +88 -0
- package/dist/esm/base-classes/services/repositories/seed-row-default-materialization.backend.js.map +1 -0
- package/dist/esm/base-classes/services/repositories/unique-constraint-conflict-reference.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/resource-operations-helper.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/__tests__/mock-services-registry-handler.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/__tests__/mock-system-access.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/read-only-field-change.backend.utils.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-audit-emission.backend.utils.d.ts.map +1 -1
- 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-operation-custom-implementation-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-implementation-coverage.backend.utils.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-server-injected-fields.backend.utils.d.ts.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts.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.map +1 -1
- 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.map +1 -1
- 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 +44 -6
- 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.map +1 -1
- package/dist/esm/base-classes/services/services/system-access.backend.service.js.map +1 -1
- package/dist/esm/base-classes/utils/backend-type-utils.d.ts.map +1 -1
- package/dist/esm/base-classes/utils/single-subject-addressing.backend.utils.d.ts.map +1 -1
- package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.js.map +1 -1
- package/dist/esm/billing/batches/usage-flush.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/batches/usage-flush.batch.backend.service.js.map +1 -1
- package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.d.ts.map +1 -1
- package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.js.map +1 -1
- package/dist/esm/billing/services/back-office/abstract-billing.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/back-office/billing-feature-sync.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.d.ts +1 -1
- package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.js +5 -4
- package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.js.map +1 -1
- package/dist/esm/billing/services/back-office/billing-state.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/back-office/billing-state.backend.service.js +11 -1
- package/dist/esm/billing/services/back-office/billing-state.backend.service.js.map +1 -1
- package/dist/esm/billing/services/back-office/billing-subject-erasure-effect.backend.d.ts.map +1 -1
- 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.map +1 -1
- 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.map +1 -1
- package/dist/esm/billing/services/billing-adapter-registry.backend.d.ts.map +1 -1
- package/dist/esm/billing/services/billing-adapter-registry.backend.js.map +1 -1
- 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.map +1 -1
- package/dist/esm/billing/services/billing.utils.d.ts.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.map +1 -1
- package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.d.ts +32 -0
- 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 +32 -1
- 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.map +1 -1
- package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.js.map +1 -1
- package/dist/esm/billing/services/custom-impl/credit-pool.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.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.d.ts +9 -6
- 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 +9 -6
- 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.map +1 -1
- package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js.map +1 -1
- package/dist/esm/billing/services/webhooks/billing-webhook-adapter.backend.service.d.ts.map +1 -1
- package/dist/esm/billing/services/webhooks/billing-webhook-capability-handler.backend.service.d.ts.map +1 -1
- 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 +50 -3
- package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.js.map +1 -1
- package/dist/esm/billing/testing/billing-test-fixtures.d.ts.map +1 -1
- package/dist/esm/billing/testing/mock-billing-provider.d.ts.map +1 -1
- package/dist/esm/billing/testing/mock-billing-provider.js.map +1 -1
- package/dist/esm/charts/controllers/chart.backend.controller.d.ts.map +1 -1
- package/dist/esm/charts/services/chart-registry.backend.service.d.ts +80 -7
- package/dist/esm/charts/services/chart-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/charts/services/chart-registry.backend.service.js +115 -8
- package/dist/esm/charts/services/chart-registry.backend.service.js.map +1 -1
- package/dist/esm/companion-exports.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/audit-logs.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/batches/audit-logs-archive.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/batches/audit-logs-archive.batch.backend.service.js.map +1 -1
- package/dist/esm/compliance/audit-trails/batches/immudb-audit-reconcile.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/batches/siem-webhook-delivery.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/__tests__/mock-audit-logs.service.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.d.ts +107 -4
- 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 +176 -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.map +1 -1
- 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.map +1 -1
- 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.map +1 -1
- package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.js.map +1 -1
- 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 +21 -0
- package/dist/esm/compliance/audit-trails/services/utils/ocsf-activity-mapping.backend.utils.js.map +1 -1
- package/dist/esm/compliance/audit-trails/services/utils/ocsf-class-mapping.backend.utils.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/utils/siem-dictionary.backend.utils.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/utils/siem-ocsf-projection.backend.utils.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/services/utils/siem-projection-contract.backend.utils.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/utils/audit-actor.backend.utils.d.ts.map +1 -1
- package/dist/esm/compliance/audit-trails/utils/layer2-audit-provider-boot-diagnostic.backend.utils.d.ts.map +1 -1
- package/dist/esm/compliance/index.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/retention-hide-predicate.backend.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/services/subject-erasure-external-effects.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/privacy/services/subject-session-revocation.backend.service.d.ts.map +1 -1
- package/dist/esm/config/bootstrap/application-runtime-profile.backend.d.ts.map +1 -1
- package/dist/esm/config/bootstrap/application-runtime-profile.backend.js.map +1 -1
- package/dist/esm/config/bootstrap/minion-initialization-projection.backend.d.ts.map +1 -1
- package/dist/esm/config/bootstrap/runtime-principal-attestation.backend.service.d.ts.map +1 -1
- package/dist/esm/config/bootstrap/runtime-principal-attestation.backend.service.js +3 -0
- package/dist/esm/config/bootstrap/runtime-principal-attestation.backend.service.js.map +1 -1
- package/dist/esm/config/bootstrap/runtime-principal.backend.service.d.ts.map +1 -1
- package/dist/esm/config/custom/application-config-controller.backend.service.d.ts.map +1 -1
- package/dist/esm/config/models/app-config-secrets.backend.schemas.d.ts.map +1 -1
- package/dist/esm/config/models/app-config.backend-authored.definitions.d.ts.map +1 -1
- package/dist/esm/config/models/app-config.backend.schemas.d.ts +4 -4
- package/dist/esm/config/models/app-config.backend.schemas.d.ts.map +1 -1
- package/dist/esm/config/models/app-config.backend.schemas.js.map +1 -1
- package/dist/esm/config/models/app-env-config.backend.schemas.d.ts.map +1 -1
- package/dist/esm/config/models/apps-manager-transport.backend.definitions.d.ts +36 -0
- package/dist/esm/config/models/apps-manager-transport.backend.definitions.d.ts.map +1 -0
- package/dist/esm/config/models/apps-manager-transport.backend.definitions.js +36 -0
- package/dist/esm/config/models/apps-manager-transport.backend.definitions.js.map +1 -0
- package/dist/esm/config/models/config-mutation-boundary.utils.d.ts.map +1 -1
- package/dist/esm/config/models/postgresql-env-config.backend.schemas.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/config/models/runtime-topology.backend.contracts.d.ts.map +1 -1
- package/dist/esm/config/services/__tests__/mock-app-configuration.service.d.ts.map +1 -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 +3 -0
- 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.map +1 -1
- package/dist/esm/config/services/app-configuration.backend.utils.d.ts.map +1 -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 +12 -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 +28 -0
- package/dist/esm/config/services/application-startup-config-validator.backend.service.js.map +1 -1
- package/dist/esm/data-seeding/batches/data-seeding-run-cleanup.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/data-seeding/batches/data-seeding-scheduled-rerun.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/data-seeding/controllers/data-seeding-admin.backend.contracts.d.ts.map +1 -1
- package/dist/esm/data-seeding/controllers/data-seeding-admin.backend.controller.d.ts.map +1 -1
- package/dist/esm/data-seeding/data-seeding-models.d.ts.map +1 -1
- package/dist/esm/data-seeding/models/business-key-resolver.shared.utils.d.ts.map +1 -1
- package/dist/esm/data-seeding/models/data-seed-execution-context.shared.types.d.ts.map +1 -1
- package/dist/esm/data-seeding/models/data-seed-migrator-runner.shared.utils.d.ts.map +1 -1
- package/dist/esm/data-seeding/models/data-seed-reconciler.shared.utils.d.ts.map +1 -1
- package/dist/esm/data-seeding/models/data-seed-row-metadata.shared.schemas.d.ts.map +1 -1
- package/dist/esm/data-seeding/models/data-seed-row-metadata.shared.utils.d.ts.map +1 -1
- package/dist/esm/data-seeding/models/data-seed-run.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/data-seeding/models/data-seed-run.shared.schemas.d.ts.map +1 -1
- package/dist/esm/data-seeding/models/data-seed-trigger-mode-matrix.shared.utils.d.ts.map +1 -1
- package/dist/esm/data-seeding/models/data-seed.shared.schemas.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/data-seed-application-bootstrap.backend.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/data-seed-dispatcher.backend.service.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/data-seed-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/data-seed-scope-resolver-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/engines/additive-seed-engine.backend.service.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/engines/lazy-seed-engine.backend.service.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/engines/manual-seed-engine.backend.service.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/engines/sync-seed-engine.backend.service.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/engines/upgrade-seed-engine.backend.service.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/shared/data-seed-business-key.shared.utils.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/shared/data-seed-error.shared.utils.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/shared/data-seed-run-counters.shared.types.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/shared/data-seed-run-ledger.backend.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/shared/data-seed-scope-anchor.shared.types.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/shared/data-seed-scope-iteration.shared.utils.d.ts.map +1 -1
- package/dist/esm/data-seeding/services/shared/data-seed-scope-resolution.backend.d.ts.map +1 -1
- package/dist/esm/databases/models/aggregation.backend.schemas.d.ts.map +1 -1
- package/dist/esm/databases/models/databases.backend.schemas.d.ts.map +1 -1
- package/dist/esm/databases/models/filter.backend.schemas.d.ts.map +1 -1
- package/dist/esm/databases/models/resolve-persistence-adapter.backend.utils.d.ts.map +1 -1
- package/dist/esm/databases/models/sql.backend.schemas.d.ts.map +1 -1
- package/dist/esm/databases/models/transaction.shared.schemas.d.ts.map +1 -1
- package/dist/esm/databases/services/__tests__/mock-mongo-transaction-registry.service.d.ts.map +1 -1
- package/dist/esm/databases/services/__tests__/mock-mongodb.service.d.ts.map +1 -1
- package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.d.ts.map +1 -1
- package/dist/esm/databases/services/__tests__/mock-redis.service.d.ts.map +1 -1
- package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.d.ts.map +1 -1
- package/dist/esm/databases/services/aggregation/aggregation-authorization.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/aggregation/aggregation-query.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/aggregation/computed-measure-evaluator.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/aggregation/field-access-validator.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/aggregation/time-series-densifier.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/aggregation/topn-processor.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/aggregation/window-function-processor.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/db-utils.d.ts.map +1 -1
- package/dist/esm/databases/services/mongo-aggregation.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/mongodb.service.d.ts.map +1 -1
- package/dist/esm/databases/services/postgresql-aggregation.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/postgresql-database.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/postgresql-development-provisioning.backend.d.ts.map +1 -1
- package/dist/esm/databases/services/postgresql-filter.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/postgresql-migration-runner.backend.d.ts.map +1 -1
- package/dist/esm/databases/services/postgresql-schema-ddl.backend.d.ts.map +1 -1
- package/dist/esm/databases/services/postgresql-schema-migration-sql.backend.d.ts.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.map +1 -1
- package/dist/esm/databases/services/postgresql-schema-plan-lockfile.backend.d.ts.map +1 -1
- package/dist/esm/databases/services/redis.service.d.ts.map +1 -1
- package/dist/esm/databases/services/resource-persistence-unit-of-work.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/schema-planning-standalone.backend.d.ts.map +1 -1
- package/dist/esm/databases/services/zod-to-mongoose-schema-convertor.backend.service.d.ts.map +1 -1
- package/dist/esm/databases/services/zod-to-sql-hybrid-schema.planner.d.ts.map +1 -1
- package/dist/esm/databases/utils/postgresql-identifier.backend.utils.d.ts.map +1 -1
- package/dist/esm/errors/services/__tests__/mock-error-builder.service.d.ts.map +1 -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.map +1 -1
- package/dist/esm/errors/services/error-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/errors/services/error-handler.backend.service.js.map +1 -1
- package/dist/esm/errors/services/rate-limit.backend.service.d.ts.map +1 -1
- 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.map +1 -1
- 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.map +1 -1
- package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.js.map +1 -1
- package/dist/esm/external-data/batches/external-data-pipeline-scheduled-run.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/external-data/controllers/external-data-admin.backend.contracts.d.ts.map +1 -1
- package/dist/esm/external-data/controllers/external-data-admin.backend.controller.d.ts.map +1 -1
- package/dist/esm/external-data/external-data-extraction-source.backend.d.ts.map +1 -1
- package/dist/esm/external-data/external-data-models.exports.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/external-data/external-data-transform.backend.d.ts.map +1 -1
- package/dist/esm/external-data/models/external-data-pipeline-state.backend.schemas.d.ts.map +1 -1
- package/dist/esm/external-providers/models/external-providers.backend.schemas.d.ts.map +1 -1
- 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 +102 -52
- package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.js +117 -71
- package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.js.map +1 -1
- package/dist/esm/external-providers/operations/provider-operation-request.backend.d.ts.map +1 -1
- package/dist/esm/external-providers/operations/provider-operation-request.backend.js.map +1 -1
- package/dist/esm/external-providers/operations/provider-request-signing.backend.d.ts.map +1 -1
- package/dist/esm/external-providers/operations/provider-request-signing.backend.js +26 -7
- package/dist/esm/external-providers/operations/provider-request-signing.backend.js.map +1 -1
- package/dist/esm/external-providers/operations/provider-rest-call-client.backend.d.ts.map +1 -1
- package/dist/esm/external-providers/operations/provider-rest-call-client.backend.js.map +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.map +1 -1
- package/dist/esm/external-providers/services/backend-provider-loader.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/backend-provider-loader.backend.service.js.map +1 -1
- 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.map +1 -1
- package/dist/esm/external-providers/services/document-extraction.backend.service.d.ts +81 -34
- 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 +179 -98
- 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.map +1 -1
- package/dist/esm/external-providers/services/external-api-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +121 -0
- 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 +151 -0
- 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 +15 -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 +60 -4
- package/dist/esm/external-providers/services/frontend-bootstrap.backend.service.js.map +1 -1
- package/dist/esm/features/controllers/features.backend.controller.d.ts.map +1 -1
- package/dist/esm/features/services/__tests__/mock-feature-definition-registry.service.d.ts.map +1 -1
- package/dist/esm/features/services/__tests__/mock-feature-resolution.service.d.ts.map +1 -1
- package/dist/esm/features/services/application-features-admin-write-path.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/features/services/feature-definition-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/features/services/feature-gate.backend.service.d.ts.map +1 -1
- package/dist/esm/features/services/feature-resolution.backend.service.d.ts.map +1 -1
- package/dist/esm/features/services/organization-features-admin-write-path.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/features/services/scope-feature-ledger-relationship.backend.utils.d.ts.map +1 -1
- package/dist/esm/features/services/scope-features-cache-invalidation.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/features/testing/feature-test-utils.d.ts.map +1 -1
- package/dist/esm/files/batches/files-cleanup.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/files/constraints/file-analyzers.types.d.ts.map +1 -1
- package/dist/esm/files/constraints/file-constraint-resolver-chain.backend.service.d.ts.map +1 -1
- package/dist/esm/files/constraints/file-constraint.types.d.ts.map +1 -1
- package/dist/esm/files/constraints/file-validation.backend.service.d.ts.map +1 -1
- package/dist/esm/files/constraints/resource-field-constraint-resolver.backend.service.d.ts.map +1 -1
- package/dist/esm/files/controllers/file.controller.d.ts.map +1 -1
- package/dist/esm/files/controllers/file.controller.js.map +1 -1
- package/dist/esm/files/handlers/file-upload-route-locals.backend.types.d.ts.map +1 -1
- package/dist/esm/files/handlers/file-upload-route-locals.backend.types.js.map +1 -1
- package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.d.ts +37 -0
- 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 +221 -21
- package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.js.map +1 -1
- package/dist/esm/files/scanning/clamav-scanner.backend.service.d.ts.map +1 -1
- package/dist/esm/files/scanning/file-scan.types.d.ts.map +1 -1
- package/dist/esm/files/scanning/yara-scanner.backend.service.d.ts.map +1 -1
- package/dist/esm/files/scanning/yara-scanner.backend.service.js +20 -2
- package/dist/esm/files/scanning/yara-scanner.backend.service.js.map +1 -1
- package/dist/esm/files/services/__tests__/mock-file-field-detection.service.d.ts.map +1 -1
- package/dist/esm/files/services/__tests__/mock-file-operation-handler.service.d.ts.map +1 -1
- package/dist/esm/files/services/__tests__/mock-file-repository.service.d.ts.map +1 -1
- package/dist/esm/files/services/file-field-detection.backend.service.d.ts.map +1 -1
- package/dist/esm/files/services/file-operation-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/files/services/file-operation-handler.backend.service.js.map +1 -1
- package/dist/esm/files/services/file-population.backend.service.d.ts.map +1 -1
- package/dist/esm/files/services/file-scanning.backend.service.d.ts.map +1 -1
- package/dist/esm/files/services/file-scanning.backend.service.js +5 -0
- 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.map +1 -1
- package/dist/esm/files/services/file-text-extraction.backend.service.js +8 -5
- 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.map +1 -1
- package/dist/esm/files/services/file-upload-grant.backend.service.js.map +1 -1
- package/dist/esm/files/services/files.backend.service.d.ts.map +1 -1
- package/dist/esm/files/services/files.backend.service.js +3 -1
- package/dist/esm/files/services/files.backend.service.js.map +1 -1
- package/dist/esm/files/services/rag-source-field-detection.backend.service.d.ts.map +1 -1
- package/dist/esm/files/storage/application-storage-key.backend.utils.d.ts.map +1 -1
- package/dist/esm/files/storage/application-storage-key.backend.utils.js.map +1 -1
- package/dist/esm/files/storage/file-storage-path-resolver.backend.service.d.ts.map +1 -1
- package/dist/esm/files/storage/file-storage-provider.types.d.ts +36 -1
- 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/file-storage-router.backend.service.d.ts +21 -3
- package/dist/esm/files/storage/file-storage-router.backend.service.d.ts.map +1 -1
- package/dist/esm/files/storage/file-storage-router.backend.service.js +38 -5
- package/dist/esm/files/storage/file-storage-router.backend.service.js.map +1 -1
- package/dist/esm/files/storage/google-drive-storage-provider.backend.service.d.ts +87 -0
- package/dist/esm/files/storage/google-drive-storage-provider.backend.service.d.ts.map +1 -0
- package/dist/esm/files/storage/google-drive-storage-provider.backend.service.js +340 -0
- package/dist/esm/files/storage/google-drive-storage-provider.backend.service.js.map +1 -0
- 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.map +1 -1
- package/dist/esm/files/storage/storage-credential-provider.backend.utils.d.ts.map +1 -1
- package/dist/esm/files/storage/storage-platform-sts-credential-resolver.backend.utils.d.ts.map +1 -1
- package/dist/esm/files/storage/storage-sts-credential-resolver.backend.utils.d.ts.map +1 -1
- package/dist/esm/files/storage/storage-sts-credential-resolver.backend.utils.js +10 -3
- package/dist/esm/files/storage/storage-sts-credential-resolver.backend.utils.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.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.map +1 -1
- package/dist/esm/files/utils/file-upload.utils.d.ts.map +1 -1
- package/dist/esm/files/utils/file-uploader.utils.d.ts.map +1 -1
- package/dist/esm/files/utils/file-uploader.utils.js.map +1 -1
- package/dist/esm/files/utils/file-validation.utils.d.ts.map +1 -1
- package/dist/esm/files/utils/image-derivation.backend.utils.d.ts.map +1 -1
- package/dist/esm/files/utils/image-thumbnail.backend.utils.d.ts.map +1 -1
- package/dist/esm/files/utils/office-document-text-extraction.backend.utils.d.ts.map +1 -1
- package/dist/esm/files/utils/office-document-text-extraction.backend.utils.js.map +1 -1
- package/dist/esm/files/utils/rag-source-field-schema-path.backend.utils.d.ts.map +1 -1
- package/dist/esm/files/utils/storage-application-identity.backend.utils.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/flows-actors/a2a/batches/a2a-push-delivery.batch.backend.service.d.ts.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.map +1 -1
- package/dist/esm/flows-actors/a2a/models/a2a-dialect.backend.schemas.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a/models/a2a-push-notification-delivery.backend.utils.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a/models/a2a-push-notification.backend.schemas.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/flows-actors/a2a/services/a2a-push-delivery-log.repository.d.ts.map +1 -1
- package/dist/esm/flows-actors/a2a/services/a2a-push-dispatcher.backend.service.d.ts.map +1 -1
- 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.map +1 -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.map +1 -1
- 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.map +1 -1
- 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/controllers/flows-actors.controller.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/flows-actors/models/agent-facets.backend.definitions.d.ts.map +1 -1
- package/dist/esm/flows-actors/models/agents.backend.definitions.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/flows-actors/models/flows-actors.backend.definitions.d.ts.map +1 -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 +107 -16
- 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 +118 -18
- 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.map +1 -1
- package/dist/esm/flows-actors/models/mcp-client.backend.definitions.d.ts.map +1 -1
- package/dist/esm/flows-actors/models/mcp-client.backend.definitions.js.map +1 -1
- package/dist/esm/flows-actors/services/__tests__/fixtures/meta-workflow-evaluation-treatment.test-fixture.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/flows-actors/services/agent-call-trace-sink.backend.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/agent-facets.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/agents.backend.service.d.ts +104 -5
- package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/agents.backend.service.js +263 -31
- package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/context-curation.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts +46 -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 +193 -6
- 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.map +1 -1
- 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.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.map +1 -1
- package/dist/esm/flows-actors/services/mcp-client.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/mcp-client.backend.service.js +3 -0
- package/dist/esm/flows-actors/services/mcp-client.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/mcp-credential-resolver.backend.service.d.ts +99 -0
- package/dist/esm/flows-actors/services/mcp-credential-resolver.backend.service.d.ts.map +1 -0
- package/dist/esm/flows-actors/services/mcp-credential-resolver.backend.service.js +155 -0
- package/dist/esm/flows-actors/services/mcp-credential-resolver.backend.service.js.map +1 -0
- package/dist/esm/flows-actors/services/meta-workflow-evaluation-treatment-compiler.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/meta-workflow-standard-action-contracts.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/meta-workflow-standard-evaluation-contracts.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/meta-workflow-structured-artifact-action-compiler.backend.service.d.ts.map +1 -1
- 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.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 +9 -0
- package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
- package/dist/esm/flows-actors/utils/bounded-subprocess.backend.utils.d.ts.map +1 -1
- package/dist/esm/flows-actors/utils/flows-actors-frontend-extractor.utils.d.ts.map +1 -1
- 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.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/flows-actors/utils/prompt-ir-adapters.backend.utils.d.ts.map +1 -1
- package/dist/esm/flows-actors/utils/tool-approval-modification.backend.utils.d.ts +77 -0
- package/dist/esm/flows-actors/utils/tool-approval-modification.backend.utils.d.ts.map +1 -0
- package/dist/esm/flows-actors/utils/tool-approval-modification.backend.utils.js +164 -0
- package/dist/esm/flows-actors/utils/tool-approval-modification.backend.utils.js.map +1 -0
- package/dist/esm/flows-actors/utils/tool-approval-signing.backend.utils.d.ts +48 -0
- package/dist/esm/flows-actors/utils/tool-approval-signing.backend.utils.d.ts.map +1 -0
- package/dist/esm/flows-actors/utils/tool-approval-signing.backend.utils.js +101 -0
- package/dist/esm/flows-actors/utils/tool-approval-signing.backend.utils.js.map +1 -0
- package/dist/esm/guidance/batches/dormancy-detection.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/guidance/services/guidance-trigger-evaluator.backend.service.d.ts.map +1 -1
- package/dist/esm/guidance/services/lifecycle-custom-implementations.backend.d.ts.map +1 -1
- package/dist/esm/guidance/services/lifecycle-evaluator.backend.service.d.ts.map +1 -1
- package/dist/esm/guidance/services/lifecycle-scope-id.backend.utils.d.ts.map +1 -1
- package/dist/esm/guidance/services/milestone-condition-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/guidance/services/milestone-definition-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/guidance/services/milestone-evaluator.backend.service.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/guidance/services/progression-state-store.backend.service.js.map +1 -1
- package/dist/esm/guidance/services/scoped-state-read-custom-implementations.backend.d.ts.map +1 -1
- package/dist/esm/i18n/controllers/i18n-controller.backend.service.d.ts.map +1 -1
- package/dist/esm/i18n/controllers/i18n-controller.backend.service.js.map +1 -1
- package/dist/esm/i18n/services/i18n.backend.service.d.ts.map +1 -1
- package/dist/esm/index.d.ts +0 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +0 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/inject/models/container.d.ts +10 -0
- package/dist/esm/inject/models/container.d.ts.map +1 -1
- package/dist/esm/inject/models/container.js +49 -1
- package/dist/esm/inject/models/container.js.map +1 -1
- package/dist/esm/inject/models/service-types.d.ts +3 -0
- package/dist/esm/inject/models/service-types.d.ts.map +1 -1
- package/dist/esm/inject/models/service-types.js +3 -0
- 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 +50 -3
- package/dist/esm/mcp/controllers/mcp.controller.js.map +1 -1
- package/dist/esm/mcp/models/mcp-protocol.backend.schemas.d.ts.map +1 -1
- package/dist/esm/mcp/models/mcp-tool.backend.schemas.d.ts.map +1 -1
- package/dist/esm/mcp/models/mcp-tool.backend.schemas.js.map +1 -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.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.map +1 -1
- package/dist/esm/mcp/services/resource-server-instances-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/mcp/utils/zod-to-mcp-json-schema.backend.utils.d.ts.map +1 -1
- package/dist/esm/meta-workflow-runtime.exports.d.ts.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.map +1 -1
- package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.js.map +1 -1
- 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.map +1 -1
- 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.map +1 -1
- package/dist/esm/monitoring/logger/models/logger.backend.schemas.js.map +1 -1
- package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.d.ts.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 +3 -3
- 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.map +1 -1
- package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.js.map +1 -1
- package/dist/esm/monitoring/logger/utils/log-value-normalization.backend.utils.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/audit-observation-emission.backend.d.ts +10 -6
- package/dist/esm/monitoring/observability/audit-observation-emission.backend.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/audit-observation-emission.backend.js +10 -6
- package/dist/esm/monitoring/observability/audit-observation-emission.backend.js.map +1 -1
- 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/otel-preload.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/otel-sdk-global-handle.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/services/__tests__/mock-metrics.service.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -1
- package/dist/esm/monitoring/observability/services/observability.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/email/components/email-components.d.ts.map +1 -1
- package/dist/esm/notifications/email/models/email-template-definition.d.ts.map +1 -1
- package/dist/esm/notifications/email/models/email-transport.backend.definitions.d.ts.map +1 -1
- package/dist/esm/notifications/email/services/email-batch-send.batch.backend.service.d.ts.map +1 -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.map +1 -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.map +1 -1
- package/dist/esm/notifications/email/services/email.backend.service.d.ts +47 -6
- package/dist/esm/notifications/email/services/email.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/email/services/email.backend.service.js +86 -36
- package/dist/esm/notifications/email/services/email.backend.service.js.map +1 -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/email/utils/interpolate-email-label.utils.d.ts.map +1 -1
- package/dist/esm/notifications/email/utils/zod-to-typescript.utils.d.ts.map +1 -1
- package/dist/esm/notifications/services/notification-badge.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/services/notification-badge.backend.service.js.map +1 -1
- package/dist/esm/notifications/services/notifications-dispatcher.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/services/notifications-dispatcher.backend.service.js.map +1 -1
- package/dist/esm/notifications/sms/models/sms-transport.backend.definitions.d.ts +32 -0
- package/dist/esm/notifications/sms/models/sms-transport.backend.definitions.d.ts.map +1 -0
- package/dist/esm/notifications/sms/models/sms-transport.backend.definitions.js +32 -0
- package/dist/esm/notifications/sms/models/sms-transport.backend.definitions.js.map +1 -0
- package/dist/esm/notifications/sms/services/sms.backend.service.d.ts +64 -10
- package/dist/esm/notifications/sms/services/sms.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/sms/services/sms.backend.service.js +277 -82
- 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.map +1 -1
- 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.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.js.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.utils.d.ts.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.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.repository.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-dispatcher.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/services/webhook-config-public-key.custom-impl.backend.service.d.ts.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.map +1 -1
- package/dist/esm/notifications/webhooks/outbound/services/webhook-config.backend.service.d.ts.map +1 -1
- package/dist/esm/notifications/webhooks/services/polymorphic-lookup.backend.service.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/organizations/batches/organization-member-invitation-sweep.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/organizations/batches/organization-purge.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/organizations/batches/organization-purge.batch.backend.service.js.map +1 -1
- package/dist/esm/organizations/services/authority-change-audit.backend.utils.d.ts.map +1 -1
- package/dist/esm/organizations/services/invitation-acceptance.backend.utils.d.ts.map +1 -1
- package/dist/esm/organizations/services/org-creation-on-registration.backend.utils.d.ts.map +1 -1
- package/dist/esm/organizations/services/org-member-roles-validation.backend.utils.d.ts.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.map +1 -1
- package/dist/esm/organizations/services/organization-deletion-audit.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/organizations/services/organization-member-custom-implementation.backend.service.d.ts.map +1 -1
- package/dist/esm/organizations/services/organization-onboarding-operation.backend.utils.d.ts.map +1 -1
- package/dist/esm/organizations/services/organization-unit-custom-implementation.backend.service.d.ts.map +1 -1
- package/dist/esm/organizations/services/organization-unit-member-custom-implementation.backend.service.d.ts.map +1 -1
- package/dist/esm/organizations/services/scim-provisioning-gate.backend.utils.d.ts.map +1 -1
- package/dist/esm/organizations/services/user-org-type-grant.backend.utils.d.ts.map +1 -1
- package/dist/esm/organizations/services/user-type-revocation-on-org-leave.backend.utils.d.ts.map +1 -1
- package/dist/esm/pdf-templates/__tests__/fixtures/tiny-pdf-template.fixture.d.ts.map +1 -1
- package/dist/esm/pdf-templates/models/pdf-template-binding.d.ts.map +1 -1
- package/dist/esm/pdf-templates/models/pdf-template-definition.d.ts.map +1 -1
- package/dist/esm/pdf-templates/services/pdf-generated-file-writer.backend.service.d.ts.map +1 -1
- package/dist/esm/pdf-templates/services/pdf-generation-orchestrator.backend.service.d.ts.map +1 -1
- package/dist/esm/pdf-templates/services/pdf-renderer.backend.service.d.ts.map +1 -1
- package/dist/esm/pdf-templates/services/pdf-template-binding.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.js.map +1 -1
- package/dist/esm/queue/adapters/queue-adapter.backend.binding.d.ts.map +1 -1
- package/dist/esm/queue/adapters/queue-adapter.backend.binding.js.map +1 -1
- package/dist/esm/queue/adapters/queue-adapter.backend.interface.d.ts.map +1 -1
- package/dist/esm/queue/adapters/queue-adapter.backend.interface.js.map +1 -1
- package/dist/esm/queue/adapters/queue-adapter.backend.options.d.ts.map +1 -1
- package/dist/esm/queue/adapters/queue-adapter.backend.options.js.map +1 -1
- package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.js.map +1 -1
- package/dist/esm/queue/apps-crontabs-manager.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/cron-job-sync.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/domain-queue-consumer.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/domain-queue-consumer.backend.service.js.map +1 -1
- package/dist/esm/queue/job-completion-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/job-consumer.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/job-consumer.backend.service.js.map +1 -1
- package/dist/esm/queue/job-executor.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/job-executor.backend.service.js.map +1 -1
- package/dist/esm/queue/job-payload-storage.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/job-status-tracking.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/queue-monitoring.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/queue-monitoring.backend.service.js.map +1 -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.map +1 -1
- package/dist/esm/queue/queue.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/queue.backend.service.js.map +1 -1
- package/dist/esm/queue/scheduled-message-verifier.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/worker-shutdown-manager.backend.service.d.ts.map +1 -1
- package/dist/esm/queue/worker-shutdown-manager.backend.service.js.map +1 -1
- package/dist/esm/rag/batches/rag-embedding-drain.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/rag/batches/rag-reconciliation-sweep.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/rag/models/rag-chunk-store.backend.types.d.ts.map +1 -1
- package/dist/esm/rag/models/rag-retrieval.backend.types.d.ts.map +1 -1
- package/dist/esm/rag/services/mongodb-rag-chunk-store.backend.service.d.ts.map +1 -1
- package/dist/esm/rag/services/postgresql-rag-chunk-store.backend.service.d.ts.map +1 -1
- package/dist/esm/rag/services/rag-chunk-collection.mongodb-ddl.backend.d.ts.map +1 -1
- package/dist/esm/rag/services/rag-chunk-retrieval.mongodb-query.backend.d.ts.map +1 -1
- package/dist/esm/rag/services/rag-chunk-retrieval.postgresql-query.backend.d.ts.map +1 -1
- package/dist/esm/rag/services/rag-chunk-store.backend.service.d.ts.map +1 -1
- package/dist/esm/rag/services/rag-chunk-table.postgresql-ddl.backend.d.ts.map +1 -1
- package/dist/esm/rag/services/rag-ingestion.backend.service.d.ts.map +1 -1
- package/dist/esm/rag/services/rag-retrieval.backend.service.d.ts.map +1 -1
- package/dist/esm/rag/utils/rag-chunk-fusion.backend.utils.d.ts.map +1 -1
- package/dist/esm/rag/utils/rag-chunk-removal.backend.utils.d.ts.map +1 -1
- package/dist/esm/rag/utils/rag-chunk-row-shaping.backend.utils.d.ts.map +1 -1
- package/dist/esm/rag/utils/rag-chunking.backend.utils.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/rag/utils/rag-context-assembly.backend.utils.js.map +1 -1
- package/dist/esm/rag/utils/rag-ingestion-trigger.backend.utils.d.ts.map +1 -1
- package/dist/esm/rag/utils/rag-retrieval-scope.backend.utils.d.ts.map +1 -1
- package/dist/esm/rag/utils/rag-source-field-value.backend.utils.d.ts.map +1 -1
- package/dist/esm/requests/models/api-routes.backend.defintions.d.ts.map +1 -1
- package/dist/esm/requests/models/requests.backend.schemas.d.ts.map +1 -1
- package/dist/esm/requests/service/platform-mutualized-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/requests/service/platform-requests.backend.utils.d.ts.map +1 -1
- package/dist/esm/requests/service/remote-client-base.backend.service.d.ts.map +1 -1
- package/dist/esm/requests/service/serverless-services-handler.backend.service.d.ts.map +1 -1
- package/dist/esm/requests/service/websocket.service.d.ts.map +1 -1
- package/dist/esm/requests/service/websocket.service.js +49 -1
- package/dist/esm/requests/service/websocket.service.js.map +1 -1
- package/dist/esm/resources/backend-resource-registry.exports.d.ts.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 +2 -0
- package/dist/esm/resources/models/custom-service-implementations.backend.definition.js.map +1 -1
- package/dist/esm/resources/models/index.d.ts.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.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.map +1 -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.map +1 -1
- package/dist/esm/resources/models/resources.backend.schemas.d.ts.map +1 -1
- package/dist/esm/resources/models/virtual-fields.backend.types.d.ts.map +1 -1
- package/dist/esm/resources/services/__tests__/mock-resources-registry.service.d.ts.map +1 -1
- package/dist/esm/resources/services/resource-context.backend.service.d.ts.map +1 -1
- package/dist/esm/resources/services/resource-id.backend.service.d.ts.map +1 -1
- package/dist/esm/resources/services/resource-population.backend.service.d.ts +17 -2
- package/dist/esm/resources/services/resource-population.backend.service.d.ts.map +1 -1
- package/dist/esm/resources/services/resource-population.backend.service.js +74 -18
- package/dist/esm/resources/services/resource-population.backend.service.js.map +1 -1
- package/dist/esm/resources/services/resources-registry.backend.service.d.ts +23 -0
- package/dist/esm/resources/services/resources-registry.backend.service.d.ts.map +1 -1
- package/dist/esm/resources/services/resources-registry.backend.service.js +31 -0
- package/dist/esm/resources/services/resources-registry.backend.service.js.map +1 -1
- package/dist/esm/resources/services/virtual-fields.backend.service.d.ts.map +1 -1
- package/dist/esm/resources/utils/resource-retention.backend.utils.d.ts.map +1 -1
- package/dist/esm/runtime/controllers/health-controller.backend.service.d.ts.map +1 -1
- package/dist/esm/runtime/controllers/health-controller.backend.service.js.map +1 -1
- package/dist/esm/runtime/domain-module.backend.definitions.d.ts.map +1 -1
- package/dist/esm/runtime/domain-module.backend.definitions.js.map +1 -1
- package/dist/esm/runtime/models/execution-context.backend.schemas.d.ts.map +1 -1
- package/dist/esm/runtime/models/request-context.als.backend.d.ts.map +1 -1
- package/dist/esm/runtime/models/runtime.backend.schemas.d.ts.map +1 -1
- package/dist/esm/runtime/services/execution-context-creator.backend.service.d.ts.map +1 -1
- package/dist/esm/runtime/services/execution-context-creator.backend.service.js.map +1 -1
- package/dist/esm/runtime/services/execution-context-handler.backend.service.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/runtime/services/http-server.backend.service.js +10 -0
- package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -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 +26 -12
- package/dist/esm/runtime/services/start-application.backend.service.js.map +1 -1
- package/dist/esm/runtime/services/utils/oauth-body-cap.backend.utils.d.ts.map +1 -1
- package/dist/esm/runtime/testing/execution-context-test-fixtures.d.ts.map +1 -1
- package/dist/esm/runtime/testing/mock-execution-context-creator.service.d.ts.map +1 -1
- package/dist/esm/runtime/utils/application-startup-config-access.backend.utils.d.ts.map +1 -1
- package/dist/esm/runtime/utils/feature-gated-core-resource-exclusions.backend.utils.d.ts.map +1 -1
- package/dist/esm/runtime/utils/request-client-ip.utils.d.ts.map +1 -1
- package/dist/esm/runtime/utils/scan-default-exports.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/api-keys/api-key-generation.backend.utils.d.ts.map +1 -1
- 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.map +1 -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.map +1 -1
- package/dist/esm/security/authentications/controllers/auth-method-management-controller.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.d.ts +22 -0
- 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 +84 -0
- 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.map +1 -1
- package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/models/auth-constants.backend.d.ts.map +1 -1
- package/dist/esm/security/authentications/models/authentications.backend.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/models/authorization-client.backend.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/models/cimd.backend.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/models/cimd.backend.schemas.js.map +1 -1
- package/dist/esm/security/authentications/models/federated-auth-transport.backend.definitions.d.ts +37 -0
- package/dist/esm/security/authentications/models/federated-auth-transport.backend.definitions.d.ts.map +1 -0
- package/dist/esm/security/authentications/models/federated-auth-transport.backend.definitions.js +37 -0
- package/dist/esm/security/authentications/models/federated-auth-transport.backend.definitions.js.map +1 -0
- package/dist/esm/security/authentications/models/identity-persistence-boundaries.backend.d.ts.map +1 -1
- package/dist/esm/security/authentications/models/jwt.backend.schemas.d.ts.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/models/saml-authentication.backend.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/models/sso-connection.backend.schemas.d.ts.map +1 -1
- package/dist/esm/security/authentications/models/user-authorization-version.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/seeds/enterprise-config-defaults.seeds.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/__tests__/mock-auth-execution-context-factory.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/__tests__/mock-auth-token-issuer.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/__tests__/oauth-provider-audit-spies.mock.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/__tests__/mock-domain-to-org-lookup.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/__tests__/mock-enterprise-user-provisioning.service.d.ts.map +1 -1
- 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.map +1 -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.map +1 -1
- 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.map +1 -1
- 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.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/oidc-discovery.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/admin-config/oidc-discovery.backend.service.js +2 -1
- package/dist/esm/security/authentications/services/admin-config/oidc-discovery.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/anonymous-session.backend.service.d.ts +9 -2
- 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 +9 -2
- package/dist/esm/security/authentications/services/anonymous-session.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/auth-credential-verifier.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-execution-context-factory.backend.service.d.ts.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.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-mfa.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-phone-verification.backend.service.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.d.ts +97 -0
- 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 +218 -26
- 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 +14 -0
- 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 +36 -0
- 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/saml-assertion-validator.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/saml-authentication.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/saml-metadata.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/saml-replay-guard.backend.service.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/security/authentications/services/auth-session-store.backend.service.d.ts.map +1 -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.map +1 -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.map +1 -1
- 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.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.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/scim-tokens.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js +57 -1
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js.map +1 -1
- 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.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/sso-connection.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/custom-impls/sso-connection.custom-impl.backend.service.js +11 -1
- package/dist/esm/security/authentications/services/custom-impls/sso-connection.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/security/authentications/services/email-verification-initiator.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/machine-token-issuer.backend.service.d.ts.map +1 -1
- 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.map +1 -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.map +1 -1
- package/dist/esm/security/authentications/services/oidc-user-claims.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/resolve-active-member-orgs.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/utils/__tests__/mock-auth-user-lookup.service.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/utils/auth-controller.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/utils/auth-credential-ops.backend.service.d.ts.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.map +1 -1
- package/dist/esm/security/authentications/services/utils/auth-response-helper.backend.service.d.ts.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.map +1 -1
- package/dist/esm/security/authentications/services/utils/concurrent-session-eviction.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/utils/ensure-user-profile.backend.utils.d.ts.map +1 -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.map +1 -1
- package/dist/esm/security/authentications/services/utils/machine-auth-rate-limit.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/utils/pkce.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/services/utils/saml-java-availability.d.ts.map +1 -1
- package/dist/esm/security/authentications/utils/application-auth-policy-audit.backend.utils.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/security/authentications/utils/one-off-session-lifetime.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authentications/utils/social-oauth2-purpose.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/access-grant-decision.factory.backend.d.ts +59 -0
- package/dist/esm/security/authorizations/access-grant-decision.factory.backend.d.ts.map +1 -0
- package/dist/esm/security/authorizations/access-grant-decision.factory.backend.js +111 -0
- package/dist/esm/security/authorizations/access-grant-decision.factory.backend.js.map +1 -0
- package/dist/esm/security/authorizations/access-grant-lifecycle-audit.backend.d.ts +57 -0
- package/dist/esm/security/authorizations/access-grant-lifecycle-audit.backend.d.ts.map +1 -0
- package/dist/esm/security/authorizations/access-grant-lifecycle-audit.backend.js +133 -0
- package/dist/esm/security/authorizations/access-grant-lifecycle-audit.backend.js.map +1 -0
- package/dist/esm/security/authorizations/application-access-grant-custom-implementation.backend.service.d.ts +41 -0
- package/dist/esm/security/authorizations/application-access-grant-custom-implementation.backend.service.d.ts.map +1 -0
- package/dist/esm/security/authorizations/application-access-grant-custom-implementation.backend.service.js +157 -0
- package/dist/esm/security/authorizations/application-access-grant-custom-implementation.backend.service.js.map +1 -0
- package/dist/esm/security/authorizations/application-wide-read-admission.backend.d.ts +84 -0
- package/dist/esm/security/authorizations/application-wide-read-admission.backend.d.ts.map +1 -0
- package/dist/esm/security/authorizations/application-wide-read-admission.backend.js +99 -0
- package/dist/esm/security/authorizations/application-wide-read-admission.backend.js.map +1 -0
- package/dist/esm/security/authorizations/authorization-denial-audit.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.d.ts.map +1 -1
- package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.js.map +1 -1
- package/dist/esm/security/authorizations/initiator-organization-confinement.backend.d.ts.map +1 -1
- package/dist/esm/security/authorizations/junction-scope-resolution.backend.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/security/authorizations/organization-unit-narrowing-enforcement.backend.d.ts.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 +20 -181
- package/dist/esm/security/authorizations/platform-access-grant-custom-implementation.backend.service.js.map +1 -1
- package/dist/esm/security/authorizations/privileged-access-review.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/relationship-foreign-key-filter.backend.d.ts.map +1 -1
- package/dist/esm/security/authorizations/role-ceiling.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/role-ceiling.backend.utils.js.map +1 -1
- package/dist/esm/security/authorizations/role-conferral.backend.utils.d.ts +40 -0
- package/dist/esm/security/authorizations/role-conferral.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/authorizations/role-conferral.backend.utils.js +43 -1
- package/dist/esm/security/authorizations/role-conferral.backend.utils.js.map +1 -1
- package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.d.ts +27 -17
- 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 +27 -17
- 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 +72 -0
- package/dist/esm/security/authorizations/services/authorizations.backend.service.d.ts.map +1 -1
- package/dist/esm/security/authorizations/services/authorizations.backend.service.js +153 -10
- 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.map +1 -1
- 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.map +1 -1
- package/dist/esm/security/connected-accounts/connection-target-authorization.backend.js.map +1 -1
- package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.d.ts +139 -1
- package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.js +474 -33
- package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.js.map +1 -1
- package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.d.ts +40 -0
- package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.js.map +1 -1
- package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.js.map +1 -1
- package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.d.ts +19 -0
- package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.js +38 -0
- package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.js.map +1 -1
- package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.js +17 -1
- package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.js.map +1 -1
- package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.d.ts +14 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.js +16 -0
- package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.js.map +1 -1
- package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.js +1 -1
- package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.js.map +1 -1
- package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.d.ts +19 -0
- package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.js +45 -2
- package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.js.map +1 -1
- package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.d.ts +37 -1
- package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.js.map +1 -1
- package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.js.map +1 -1
- package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.js.map +1 -1
- package/dist/esm/security/connected-accounts/utils/user-delegated-access-token-slot.backend.utils.d.ts +34 -0
- package/dist/esm/security/connected-accounts/utils/user-delegated-access-token-slot.backend.utils.d.ts.map +1 -0
- package/dist/esm/security/connected-accounts/utils/user-delegated-access-token-slot.backend.utils.js +39 -0
- package/dist/esm/security/connected-accounts/utils/user-delegated-access-token-slot.backend.utils.js.map +1 -0
- package/dist/esm/security/consumable-tokens/batches/consumable-tokens-cleanup.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/security/consumable-tokens/consumable-token-models.exports.d.ts.map +1 -1
- package/dist/esm/security/consumable-tokens/models/consumable-tokens.backend.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/security/consumable-tokens/models/consumable-tokens.shared.schemas.d.ts.map +1 -1
- package/dist/esm/security/consumable-tokens/models/index.d.ts.map +1 -1
- package/dist/esm/security/consumable-tokens/services/__tests__/mock-consumable-token.service.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/security/credential-rotation-grace.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/credential-rotation-grace.backend.utils.js.map +1 -1
- package/dist/esm/security/jwt/services/auth-jwt-guard.backend.service.d.ts.map +1 -1
- package/dist/esm/security/jwt/services/jwt.backend.service.d.ts.map +1 -1
- package/dist/esm/security/jwt/services/wildo-worker-bootstrap-client.backend.service.d.ts +13 -0
- package/dist/esm/security/jwt/services/wildo-worker-bootstrap-client.backend.service.d.ts.map +1 -1
- package/dist/esm/security/jwt/services/wildo-worker-bootstrap-client.backend.service.js +14 -0
- package/dist/esm/security/jwt/services/wildo-worker-bootstrap-client.backend.service.js.map +1 -1
- package/dist/esm/security/jwt/utils/jwt-verification-error-classification.backend.utils.d.ts.map +1 -1
- 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.map +1 -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.map +1 -1
- package/dist/esm/security/outbound/outbound-request-deadline.backend.utils.d.ts +39 -0
- package/dist/esm/security/outbound/outbound-request-deadline.backend.utils.d.ts.map +1 -0
- package/dist/esm/security/outbound/outbound-request-deadline.backend.utils.js +60 -0
- package/dist/esm/security/outbound/outbound-request-deadline.backend.utils.js.map +1 -0
- package/dist/esm/security/outbound/outbound-request-headers.backend.utils.d.ts +66 -0
- package/dist/esm/security/outbound/outbound-request-headers.backend.utils.d.ts.map +1 -0
- package/dist/esm/security/outbound/outbound-request-headers.backend.utils.js +75 -0
- package/dist/esm/security/outbound/outbound-request-headers.backend.utils.js.map +1 -0
- package/dist/esm/security/scim/controllers/scim.backend.controller.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/security/scim/models/scim-protocol.backend.schemas.js.map +1 -1
- package/dist/esm/security/scim/utils/scim-attribute-path-resolver.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/scim/utils/scim-filter-parser.d.ts.map +1 -1
- package/dist/esm/security/scim/utils/scim-response-formatter.d.ts.map +1 -1
- package/dist/esm/security/session-invalidation-fence.backend.utils.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.d.ts.map +1 -1
- package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.js.map +1 -1
- package/dist/esm/security/token-invalidation-fence.backend.utils.d.ts.map +1 -1
- package/dist/esm/testing.d.ts.map +1 -1
- package/dist/esm/users/services/inbound-contact-custom-implementation.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/user-deletion-audit.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/user-self-custom-implementations.backend.d.ts.map +1 -1
- package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/dist/esm/external-providers/services/flow-actor-design.backend.service.d.ts +0 -45
- package/dist/esm/external-providers/services/flow-actor-design.backend.service.d.ts.map +0 -1
- package/dist/esm/external-providers/services/flow-actor-design.backend.service.js +0 -22
- package/dist/esm/external-providers/services/flow-actor-design.backend.service.js.map +0 -1
- package/dist/esm/notifications/email/models/email-context-provider.interface.d.ts +0 -0
- package/dist/esm/notifications/email/models/email-context-provider.interface.d.ts.map +0 -0
- package/dist/esm/notifications/email/models/email-context-provider.interface.js +0 -0
- package/dist/esm/notifications/email/models/email-context-provider.interface.js.map +0 -0
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.d.ts +0 -0
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.d.ts.map +0 -0
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.js +0 -0
- package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.js.map +0 -0
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.d.ts +0 -0
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.d.ts.map +0 -0
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.js +0 -0
- package/dist/esm/notifications/email/services/email-template-compiler.backend.service.js.map +0 -0
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.d.ts +0 -0
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.d.ts.map +0 -0
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.js +0 -0
- package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.js.map +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organization-provider-credential-store.backend.service.js","sourceRoot":"","sources":["../../../../../../src/security/connected-accounts/services/organization-provider-credential-store.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The organization-provider-credential STORE — the port implementation the registry consults.\n *\n * ## What makes the isolation structural rather than a filter\n *\n * Three independent mechanisms have to agree before a credential is handed back, and none of them\n * is a predicate somebody has to remember to write at each call site:\n *\n * 1. **The scope FK is injected by the context machinery.** The read goes through `readAsSystem`\n * with the organization in the system scope map, so `buildContextualFilter` adds the tenant\n * clause itself. A caller cannot omit it, because the caller never writes it.\n * 2. **The filter names the organization explicitly as well.** Belt and braces, deliberately: the\n * contextual filter is injected by a mechanism that exists TWICE (a Mongo implementation and a\n * PostgreSQL one), so a regression in one adapter is a bypass in that adapter alone. The explicit\n * clause is adapter-independent and would still scope the read.\n * 3. **The envelope is BOUND to the row identity.** Even a read that returned another tenant's row\n * would fail to OPEN it — the associated data is the organization, provider and slug, so the seal\n * itself refuses. This is the one that holds when the other two are wrong, which is why it exists.\n *\n * ## The store never accepts a caller-supplied organization from a request\n *\n * `organizationId` arrives from the calling code's trusted execution scope. The port cannot verify\n * it — nothing at this tier can — so the honest statement is that the guarantee holds one level up,\n * and the envelope binding is what keeps a mistake there from becoming a cross-tenant credential\n * disclosure rather than merely a failed read.\n */\n\nimport { inject, injectable, optional } from 'inversify';\nimport {\n CoreResourceType,\n ProviderCredentialResolutionSource,\n ProviderCredentialValidationState,\n serializeProviderOAuth2Grant,\n type ProviderOAuth2Grant,\n type OrganizationProviderCredential,\n} from '@wildo-ai/saas-models';\n\nimport { ExternalProvider_Connection_DelegationMode, ExternalProvider_Connection_OwnerScope } from '@wildo-ai/external-connectors-models';\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 { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport type { SystemAccessBackendService } from '~wildo-backend-lib/base-classes/services/services/system-access.backend.service';\nimport type { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';\nimport { describeCaughtError } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\n\nimport {\n ProviderCredentialEnvelopeError,\n openProviderCredential,\n} from '../utils/provider-credential-envelope.backend.utils';\nimport { resolveStoredCredentialValue } from '../utils/stored-credential-value.backend.utils';\nimport { providerOAuth2GrantWasPermanentlyRejected } from './provider-oauth2-exchange.backend';\nimport type { ProviderOAuth2RefresherPort } from '../provider-oauth2-refresher.port';\nimport type {\n OrganizationProviderCredentialQuery,\n OrganizationProviderCredentialResolution,\n OrganizationProviderCredentialResolverPort,\n} from '../organization-provider-credential-resolver.port';\n\n@injectable()\nexport class OrganizationProviderCredentialStoreBackendService implements OrganizationProviderCredentialResolverPort {\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.AppConfigService) private readonly appConfigService: AppConfigurationService,\n @inject(SAAS_SERVICE_TYPES.SystemAccessService) private readonly systemAccess: SystemAccessBackendService,\n /**\n * OPTIONAL and lazily used, mirroring `SystemAccessBackendService`'s own treatment of it: audit\n * emission must never be the reason a provider call fails, and a minimal test container must\n * still be able to construct this service.\n */\n @inject(SAAS_SERVICE_TYPES.AuditLogsService) @optional() private readonly auditLogs?: AuditLogsBackendService,\n /**\n * Appended LAST, deliberately: a parameter inserted mid-signature silently reassigns every\n * positional argument after it, and this constructor is called positionally by several harnesses.\n *\n * OPTIONAL, and its absence is not a degradation — a store without one resolves every pasted\n * credential and every non-expiring token exactly as before. Only an EXPIRING grant needs it, and\n * that case refuses by name rather than sending a stale token.\n */\n @inject(SAAS_SERVICE_TYPES.ProviderOAuth2Refresher) @optional() private readonly refresher?: ProviderOAuth2RefresherPort,\n ) {}\n\n /**\n * The organization's own credential, opened, or `undefined` when the tenant has not set one.\n *\n * See the port's JSDoc for why \"absent\" returns and \"present but unopenable\" throws.\n */\n public async resolveOrganizationCredential(\n query: OrganizationProviderCredentialQuery,\n ): Promise<OrganizationProviderCredentialResolution | undefined> {\n const row = await this.readCredentialRow(query);\n if (!row) {\n return undefined;\n }\n\n // A disabled credential is a tenant's deliberate \"do not spend this\" and must read as ABSENT, so\n // the registry falls through to the deployment environment exactly as it would for a tenant that\n // never configured one. Throwing instead would make disabling a credential break the integration\n // rather than park it, which is the opposite of what an operator reaches for during an incident.\n if (row.enabled === false) {\n this.logger.debug?.(\n '[organization-provider-credential] credential is disabled; treating as absent',\n { organizationId: query.organizationId, providerRef: query.providerRef, secretSlug: query.secretSlug },\n );\n return undefined;\n }\n\n const plaintext = openProviderCredential(\n row.secretValue,\n this.appConfigService.secrets.security.session.encryptionKey,\n {\n ownerScope: ExternalProvider_Connection_OwnerScope.ORGANIZATION,\n ownerId: query.organizationId,\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n },\n );\n\n // What is STORED is not always what goes on the wire: an OAuth2 grant is a JSON document whose\n // access token is one field. Returning the plaintext directly would put that document on the\n // wire as a bearer token, and the vendor's 401 would name a credential problem rather than a\n // serialization one. One shared resolver, because both stores hold both shapes.\n const describeRow = `organization '${query.organizationId}', provider '${query.providerRef}', slug '${query.secretSlug}'`;\n const resolved = resolveStoredCredentialValue(plaintext, describeRow, this.refresher !== undefined);\n if (resolved.needsRefresh) {\n // The renewal round trip and the write-back, in that order. The exchange belongs to the\n // refresher (it needs the contract and the application's registration); persisting belongs\n // here (it needs the table, the envelope key and the scope map). Neither half is where the\n // other's inputs are, which is why this is two components rather than one.\n const renewed = await this.renewOrRetire(row._id, query, {\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n target: {\n ownerScope: ExternalProvider_Connection_OwnerScope.ORGANIZATION,\n ownerId: query.organizationId,\n delegation: ExternalProvider_Connection_DelegationMode.SERVICE,\n },\n grant: resolved.grant!,\n // From the ROW. The authorization record that first held these expired ten minutes after\n // the connect; a templated token URL is still templated an hour later, so without this a\n // Microsoft or regional connection renews into `needs a value for 'cloud'`.\n connectionParameters: row.connectionParameters,\n });\n await this.persistRenewedGrant(query, row._id, renewed);\n return { value: renewed.accessToken, credentialId: row._id };\n }\n\n return { value: resolved.wireValue, credentialId: row._id };\n }\n\n /**\n * The row, read through the system door.\n *\n * `readAsSystem` bypasses the CALLER's role check, not the tenant boundary — an outbound provider\n * call legitimately happens on a batch, a queue consumer or an anonymous webhook return leg, none\n * of which holds an ORG_ADMIN role, and all of which must still resolve the tenant's credential.\n * The organization travels in the system scope map, which is the channel both the contextual\n * filter and the enrichment actually consume.\n */\n private async readCredentialRow(\n query: OrganizationProviderCredentialQuery,\n ): Promise<OrganizationProviderCredential | null> {\n return this.systemAccess.readAsSystem<OrganizationProviderCredential>(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n {\n organizationId: query.organizationId,\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n },\n { scopeContext: { organizationId: query.organizationId } },\n );\n }\n\n /**\n * Record that a credential was spent, and what the provider thought of it.\n *\n * Best-effort in both halves and deliberately so: an outbound provider call has already happened\n * by the time this runs, and failing the caller because a bookkeeping write did not land would\n * turn a successful integration into an error. Every failure is logged with the row named.\n *\n * The audit event is emitted for BOTH sources, including the deployment-environment fallback,\n * because \"this tenant is silently acting as the shared principal\" is the condition worth seeing\n * and it is invisible if only the interesting case is recorded.\n */\n public async recordCredentialUse(use: {\n organizationId: string;\n providerRef: string;\n secretSlug: string;\n source: ProviderCredentialResolutionSource;\n credentialId?: string;\n /** What the provider said. Absent means the outcome is not yet known to the caller. */\n outcome?: { accepted: boolean; providerMessage?: string };\n }): Promise<void> {\n await this.emitUseAudit(use);\n\n // Only a tenant's OWN credential has a row to stamp. A deployment-environment resolution has\n // nothing to write to, and inventing a row for it would create a credential the tenant never set.\n if (use.source !== ProviderCredentialResolutionSource.ORGANIZATION_CREDENTIAL || !use.credentialId) {\n return;\n }\n\n const now = new Date();\n const patch: Record<string, unknown> = { lastUsedAt: now };\n if (use.outcome) {\n patch.validationState = use.outcome.accepted\n ? ProviderCredentialValidationState.VALID\n : ProviderCredentialValidationState.INVALID;\n patch.lastValidatedAt = now;\n // Truncated to the schema's own bound. The provider's message describes the CREDENTIAL's\n // status and must never be derived from the credential itself — a caller passing the secret\n // here would publish it to a client-readable field, which is why this is documented at the\n // one place a provider string enters the row.\n patch.validationError = use.outcome.accepted\n ? undefined\n : (use.outcome.providerMessage ?? '').slice(0, 500) || undefined;\n }\n\n try {\n await this.systemAccess.updateAsSystem(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n use.credentialId,\n patch,\n {\n scopeContext: { organizationId: use.organizationId },\n /*\n * `lastUsedAt`, `lastValidatedAt` and `validationError` are all\n * `.excludeFromCreate().excludeFromUpdate()`, so the repository's strict `requestDto.parse`\n * drops them before persistence unless they are allow-listed here.\n *\n * The automatic diff that populates this list covers fields a custom-impl PREFIX hook\n * injected — which is how `secretSetAt` reaches the row on a write. Nothing populates it\n * for a payload a caller passes directly, which is what this is, so the omission was\n * silent in the worst way: `validationState` is NOT excluded and moved correctly, so the\n * row went INVALID while the timestamp and the provider's explanation of WHY vanished.\n * A person looking at a credential marked invalid with no reason and no last-use time is\n * being told less than the code believes it recorded.\n */\n preserveServerInjectedFields: ['lastUsedAt', 'lastValidatedAt', 'validationError'],\n },\n );\n } catch (error) {\n this.logger.warn?.(\n '[organization-provider-credential] failed to record credential use',\n {\n organizationId: use.organizationId,\n providerRef: use.providerRef,\n secretSlug: use.secretSlug,\n credentialId: use.credentialId,\n error: describeCaughtError(error),\n },\n );\n }\n }\n\n private async emitUseAudit(use: {\n organizationId: string;\n providerRef: string;\n secretSlug: string;\n source: ProviderCredentialResolutionSource;\n credentialId?: string;\n }): Promise<void> {\n if (!this.auditLogs) {\n return;\n }\n try {\n await this.auditLogs.logOrganizationProviderCredentialUsed({\n organizationId: use.organizationId,\n providerRef: use.providerRef,\n secretSlug: use.secretSlug,\n resolvedFrom: use.source,\n credentialId: use.credentialId,\n });\n } catch (error) {\n this.logger.warn?.(\n '[organization-provider-credential] failed to emit credential-use audit event',\n {\n organizationId: use.organizationId,\n providerRef: use.providerRef,\n error: describeCaughtError(error),\n },\n );\n }\n }\n\n\n /**\n * Record a grant the authorization exchange just minted, replacing one already stored.\n *\n * The plaintext goes in and the resource's own WRITE DOOR seals it — the same hook that seals a\n * credential a person types, and the same reason `persistRenewedGrant` hands over plaintext:\n * `createAsSystem` / `updateAsSystem` reach the SERVICE tier, so a pre-sealed value arrives at\n * that hook and the envelope refuses to double-seal.\n *\n * ## Reconnecting REPLACES rather than adding a second row\n *\n * The business key is (organizationId, providerRef, secretSlug) and it is UNIQUE, so a second connect would\n * violate the index. Read-then-write is a race, and the honest statement is that the index is what\n * decides it: two simultaneous connects mean one of them loses, which is the correct outcome —\n * a person who authorized twice gets one connection, not two half-connections.\n *\n * @returns the credential row's id, so the caller can name it in an audit event.\n */\n public async storeGrant(\n query: OrganizationProviderCredentialQuery,\n grant: ProviderOAuth2Grant,\n connectionParameters?: Readonly<Record<string, string>>,\n ): Promise<string> {\n const existing = await this.readCredentialRow(query);\n const secretValue = serializeProviderOAuth2Grant(grant);\n const scopeContext = { organizationId: query.organizationId };\n\n if (existing) {\n // `connectionParameters` is `.excludeFromUpdate()` — it describes the ACCOUNT the grant is\n // for, and re-authorizing against a different directory is a different connection. A\n // reconnect that changed them would point the refresh somewhere the token was not issued.\n await this.systemAccess.updateAsSystem(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n existing._id,\n {\n secretValue,\n enabled: true,\n // Clearing the mark is part of reconnecting, not a separate concern. A row retired by\n // `renewOrRetire` would otherwise keep `validationState: INVALID` forever — so somebody\n // who did exactly what the screen told them to do would reconnect successfully and still\n // be shown a broken connection.\n validationState: ProviderCredentialValidationState.UNVALIDATED,\n validationError: undefined,\n },\n { scopeContext, preserveServerInjectedFields: ['validationError'] },\n );\n await this.emitConnectionGranted(query, grant, existing._id, true);\n return existing._id;\n }\n\n const created = await this.systemAccess.createAsSystem<OrganizationProviderCredential>(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n {\n organizationId: query.organizationId,\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n secretValue,\n ...(connectionParameters === undefined ? {} : { connectionParameters }),\n },\n { scopeContext },\n );\n await this.emitConnectionGranted(query, grant, created._id, false);\n return created._id;\n }\n\n /**\n * Renew the grant, and RETIRE the connection when the vendor says it is finished.\n *\n * Without this the refresh call was unguarded, and the failure was slow and silent in the worst\n * direction. A vendor that permanently rejects a refresh token — the person removed the app at the\n * vendor, an administrator revoked it, the token aged past its absolute lifetime — throws, the\n * error propagates out of the resolve, and NOTHING touches the row. `validationState` stays where\n * it was, so the connected-accounts screen goes on showing the account as connected, every call\n * fails identically forever, and the person is never told the one thing they could act on.\n *\n * Only `invalid_grant` retires a connection, and the exclusions are the substantive part. A\n * transport failure, a bare 500 or an unparseable body means the vendor said NOTHING about the\n * grant, and retiring a working connection because we could not reach a vendor for thirty seconds\n * would be a self-inflicted outage. `invalid_client` is excluded for a different reason: it is the\n * APPLICATION's own registration being rejected, one operator's misconfiguration affecting every\n * connection at once — marking each person's account invalid would blame all of them for something\n * none of them can fix.\n *\n * The mark is best-effort and the ORIGINAL error is always re-thrown: the caller needs the real\n * cause, and a bookkeeping write that failed must not replace it with a different story.\n */\n private async renewOrRetire(\n credentialId: string,\n query: OrganizationProviderCredentialQuery,\n request: Parameters<ProviderOAuth2RefresherPort['refreshGrant']>[0],\n ): Promise<ProviderOAuth2Grant> {\n try {\n return await this.refresher!.refreshGrant(request);\n } catch (error) {\n if (providerOAuth2GrantWasPermanentlyRejected(error)) {\n try {\n await this.systemAccess.updateAsSystem(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n credentialId,\n {\n validationState: ProviderCredentialValidationState.INVALID,\n lastValidatedAt: new Date(),\n // The vendor's own code, and nothing derived from the credential. This field is\n // CLIENT-READABLE, so anything token-shaped reaching it would publish a secret onto\n // the screen that displays it.\n validationError: 'The provider rejected the stored authorization (invalid_grant). Reconnect the account.',\n },\n {\n scopeContext: { organizationId: query.organizationId },\n // Both of these are `.excludeFromUpdate()`; without the allow-list the row would go\n // INVALID carrying no reason and no timestamp — see `recordCredentialUse`.\n preserveServerInjectedFields: ['lastValidatedAt', 'validationError'],\n },\n );\n } catch (markError) {\n this.logger.warn?.(\n '[organization-provider-credential] a grant was permanently rejected and the row could not be marked',\n { providerRef: query.providerRef, secretSlug: query.secretSlug, credentialId, error: describeCaughtError(markError) },\n );\n }\n }\n throw error;\n }\n }\n\n /**\n * Record that a delegated authorization was GRANTED, distinct from the row's own `_SET` event.\n *\n * Emitted HERE and nowhere else, because this is the only place that holds the three facts an\n * auditor wants and the row does not: the scopes the vendor actually issued, which account they\n * were issued for, and whether this replaced a connection that already existed. By the time the\n * resource's own write hook sees the row, the value is sealed and none of it is recoverable.\n *\n * Best-effort, like every other emission on this path. The grant is already stored and the person\n * has already authorized it; failing their connection because a trail write did not land would\n * turn a completed authorization into an error and invite them to grant it a second time.\n */\n private async emitConnectionGranted(\n query: OrganizationProviderCredentialQuery,\n grant: ProviderOAuth2Grant,\n credentialId: string,\n replacedExistingConnection: boolean,\n ): Promise<void> {\n if (!this.auditLogs) {\n return;\n }\n try {\n await this.auditLogs.logOrganizationProviderConnectionGranted({\n organizationId: query.organizationId,\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n credentialId,\n grantedScopes: grant.grantedScopes,\n accountRef: grant.accountRef,\n replacedExistingConnection,\n });\n } catch (error) {\n this.logger.warn?.(\n '[organization-provider-credential] a connection was granted and the audit event could not be emitted',\n { providerRef: query.providerRef, secretSlug: query.secretSlug, credentialId, error: describeCaughtError(error) },\n );\n }\n }\n\n /**\n * Persist a renewed grant through the resource's own WRITE door.\n *\n * The plaintext goes in and the CUSTOM IMPLEMENTATION seals it — the same hook that seals a\n * credential a person types. Sealing here instead would be a second sealing site for one\n * invariant, and it does not merely duplicate: `updateAsSystem` reaches the service tier, so a\n * pre-sealed value arrives at that hook and the envelope REFUSES it (\"double-sealing would hand\n * the envelope itself to the provider\"). Every refresh would have thrown at the write-back.\n *\n * `secretSetAt` therefore moves, and that is correct rather than tolerated: the field is defined\n * as \"when the stored VALUE last changed\", and a renewal changes it. An earlier version of this\n * method held it still on the theory that it should mean \"when a HUMAN last supplied a value\" —\n * that is a different field, and inventing the behaviour without the field was the error.\n *\n * NOT best-effort. A refresh that is not persisted happens again on every call, and against a\n * vendor that rotates the refresh token each one invalidates the last — so the connection breaks\n * while every individual exchange succeeds.\n */\n private async persistRenewedGrant(\n query: OrganizationProviderCredentialQuery,\n credentialId: string,\n renewed: ProviderOAuth2Grant,\n ): Promise<void> {\n await this.systemAccess.updateAsSystem(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n credentialId,\n { secretValue: serializeProviderOAuth2Grant(renewed) },\n { scopeContext: { organizationId: query.organizationId } },\n );\n }\n\n /**\n * Turn an envelope failure into the operator-facing statement.\n *\n * Exposed so the registry can distinguish \"this tenant has no credential\" (fall through to the\n * environment) from \"this tenant HAS one and it is broken\" (refuse, loudly) without importing the\n * envelope's error type and re-deriving the distinction. One definition, one meaning.\n */\n public static isUnopenableCredential(error: unknown): error is ProviderCredentialEnvelopeError {\n return error instanceof ProviderCredentialEnvelopeError;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"organization-provider-credential-store.backend.service.js","sourceRoot":"","sources":["../../../../../src/security/connected-accounts/services/organization-provider-credential-store.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The organization-provider-credential STORE — the port implementation the registry consults.\n *\n * ## What makes the isolation structural rather than a filter\n *\n * Three independent mechanisms have to agree before a credential is handed back, and none of them\n * is a predicate somebody has to remember to write at each call site:\n *\n * 1. **The scope FK is injected by the context machinery.** The read goes through `readAsSystem`\n * with the organization in the system scope map, so `buildContextualFilter` adds the tenant\n * clause itself. A caller cannot omit it, because the caller never writes it.\n * 2. **The filter names the organization explicitly as well.** Belt and braces, deliberately: the\n * contextual filter is injected by a mechanism that exists TWICE (a Mongo implementation and a\n * PostgreSQL one), so a regression in one adapter is a bypass in that adapter alone. The explicit\n * clause is adapter-independent and would still scope the read.\n * 3. **The envelope is BOUND to the row identity.** Even a read that returned another tenant's row\n * would fail to OPEN it — the associated data is the organization, provider and slug, so the seal\n * itself refuses. This is the one that holds when the other two are wrong, which is why it exists.\n *\n * ## The store never accepts a caller-supplied organization from a request\n *\n * `organizationId` arrives from the calling code's trusted execution scope. The port cannot verify\n * it — nothing at this tier can — so the honest statement is that the guarantee holds one level up,\n * and the envelope binding is what keeps a mistake there from becoming a cross-tenant credential\n * disclosure rather than merely a failed read.\n */\n\nimport { inject, injectable, optional } from 'inversify';\nimport {\n CoreResourceType,\n ProviderCredentialResolutionSource,\n ProviderCredentialValidationState,\n serializeProviderOAuth2Grant,\n type ProviderOAuth2Grant,\n type OrganizationProviderCredential,\n} from '@wildo-ai/saas-models';\n\nimport { ExternalProvider_Connection_DelegationMode, ExternalProvider_Connection_OwnerScope } from '@wildo-ai/external-connectors-models';\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 { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport type { SystemAccessBackendService } from '~wildo-backend-lib/base-classes/services/services/system-access.backend.service';\nimport type { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';\nimport { describeCaughtError } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\n\nimport {\n ProviderCredentialEnvelopeError,\n openProviderCredential,\n} from '../utils/provider-credential-envelope.backend.utils';\nimport { resolveStoredCredentialValue } from '../utils/stored-credential-value.backend.utils';\nimport { providerOAuth2GrantWasPermanentlyRejected } from './provider-oauth2-exchange.backend';\nimport type { ProviderOAuth2RefresherPort } from '../provider-oauth2-refresher.port';\nimport type {\n OrganizationProviderCredentialQuery,\n OrganizationProviderCredentialResolution,\n OrganizationProviderCredentialResolverPort,\n} from '../organization-provider-credential-resolver.port';\n\n@injectable()\nexport class OrganizationProviderCredentialStoreBackendService implements OrganizationProviderCredentialResolverPort {\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.AppConfigService) private readonly appConfigService: AppConfigurationService,\n @inject(SAAS_SERVICE_TYPES.SystemAccessService) private readonly systemAccess: SystemAccessBackendService,\n /**\n * OPTIONAL and lazily used, mirroring `SystemAccessBackendService`'s own treatment of it: audit\n * emission must never be the reason a provider call fails, and a minimal test container must\n * still be able to construct this service.\n */\n @inject(SAAS_SERVICE_TYPES.AuditLogsService) @optional() private readonly auditLogs?: AuditLogsBackendService,\n /**\n * Appended LAST, deliberately: a parameter inserted mid-signature silently reassigns every\n * positional argument after it, and this constructor is called positionally by several harnesses.\n *\n * OPTIONAL, and its absence is not a degradation — a store without one resolves every pasted\n * credential and every non-expiring token exactly as before. Only an EXPIRING grant needs it, and\n * that case refuses by name rather than sending a stale token.\n */\n @inject(SAAS_SERVICE_TYPES.ProviderOAuth2Refresher) @optional() private readonly refresher?: ProviderOAuth2RefresherPort,\n ) {}\n\n /**\n * The organization's own credential, opened, or `undefined` when the tenant has not set one.\n *\n * See the port's JSDoc for why \"absent\" returns and \"present but unopenable\" throws.\n */\n public async resolveOrganizationCredential(\n query: OrganizationProviderCredentialQuery,\n ): Promise<OrganizationProviderCredentialResolution | undefined> {\n const row = await this.readCredentialRow(query);\n if (!row) {\n return undefined;\n }\n\n // A disabled credential is a tenant's deliberate \"do not spend this\" and must read as ABSENT, so\n // the registry falls through to the deployment environment exactly as it would for a tenant that\n // never configured one. Throwing instead would make disabling a credential break the integration\n // rather than park it, which is the opposite of what an operator reaches for during an incident.\n if (row.enabled === false) {\n this.logger.debug?.(\n '[organization-provider-credential] credential is disabled; treating as absent',\n { organizationId: query.organizationId, providerRef: query.providerRef, secretSlug: query.secretSlug },\n );\n return undefined;\n }\n\n const plaintext = openProviderCredential(\n row.secretValue,\n this.appConfigService.secrets.security.session.encryptionKey,\n {\n ownerScope: ExternalProvider_Connection_OwnerScope.ORGANIZATION,\n ownerId: query.organizationId,\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n },\n );\n\n // What is STORED is not always what goes on the wire: an OAuth2 grant is a JSON document whose\n // access token is one field. Returning the plaintext directly would put that document on the\n // wire as a bearer token, and the vendor's 401 would name a credential problem rather than a\n // serialization one. One shared resolver, because both stores hold both shapes.\n const describeRow = `organization '${query.organizationId}', provider '${query.providerRef}', slug '${query.secretSlug}'`;\n const resolved = resolveStoredCredentialValue(plaintext, describeRow, this.refresher !== undefined);\n if (resolved.needsRefresh) {\n // The renewal round trip and the write-back, in that order. The exchange belongs to the\n // refresher (it needs the contract and the application's registration); persisting belongs\n // here (it needs the table, the envelope key and the scope map). Neither half is where the\n // other's inputs are, which is why this is two components rather than one.\n const renewed = await this.renewOrRetire(row._id, query, {\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n target: {\n ownerScope: ExternalProvider_Connection_OwnerScope.ORGANIZATION,\n ownerId: query.organizationId,\n delegation: ExternalProvider_Connection_DelegationMode.SERVICE,\n },\n grant: resolved.grant!,\n // From the ROW. The authorization record that first held these expired ten minutes after\n // the connect; a templated token URL is still templated an hour later, so without this a\n // Microsoft or regional connection renews into `needs a value for 'cloud'`.\n connectionParameters: row.connectionParameters,\n });\n await this.persistRenewedGrant(query, row._id, renewed);\n return { value: renewed.accessToken, credentialId: row._id };\n }\n\n return { value: resolved.wireValue, credentialId: row._id };\n }\n\n /**\n * The row, read through the system door.\n *\n * `readAsSystem` bypasses the CALLER's role check, not the tenant boundary — an outbound provider\n * call legitimately happens on a batch, a queue consumer or an anonymous webhook return leg, none\n * of which holds an ORG_ADMIN role, and all of which must still resolve the tenant's credential.\n * The organization travels in the system scope map, which is the channel both the contextual\n * filter and the enrichment actually consume.\n */\n private async readCredentialRow(\n query: OrganizationProviderCredentialQuery,\n ): Promise<OrganizationProviderCredential | null> {\n return this.systemAccess.readAsSystem<OrganizationProviderCredential>(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n {\n organizationId: query.organizationId,\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n },\n { scopeContext: { organizationId: query.organizationId } },\n );\n }\n\n /**\n * Record that a credential was spent, and what the provider thought of it.\n *\n * Best-effort in both halves and deliberately so: an outbound provider call has already happened\n * by the time this runs, and failing the caller because a bookkeeping write did not land would\n * turn a successful integration into an error. Every failure is logged with the row named.\n *\n * The audit event is emitted for BOTH sources, including the deployment-environment fallback,\n * because \"this tenant is silently acting as the shared principal\" is the condition worth seeing\n * and it is invisible if only the interesting case is recorded.\n */\n public async recordCredentialUse(use: {\n organizationId: string;\n providerRef: string;\n secretSlug: string;\n source: ProviderCredentialResolutionSource;\n credentialId?: string;\n /** What the provider said. Absent means the outcome is not yet known to the caller. */\n outcome?: { accepted: boolean; providerMessage?: string };\n }): Promise<void> {\n await this.emitUseAudit(use);\n\n // Only a tenant's OWN credential has a row to stamp. A deployment-environment resolution has\n // nothing to write to, and inventing a row for it would create a credential the tenant never set.\n if (use.source !== ProviderCredentialResolutionSource.ORGANIZATION_CREDENTIAL || !use.credentialId) {\n return;\n }\n\n const now = new Date();\n const patch: Record<string, unknown> = { lastUsedAt: now };\n if (use.outcome) {\n patch.validationState = use.outcome.accepted\n ? ProviderCredentialValidationState.VALID\n : ProviderCredentialValidationState.INVALID;\n patch.lastValidatedAt = now;\n // Truncated to the schema's own bound. The provider's message describes the CREDENTIAL's\n // status and must never be derived from the credential itself — a caller passing the secret\n // here would publish it to a client-readable field, which is why this is documented at the\n // one place a provider string enters the row.\n patch.validationError = use.outcome.accepted\n ? undefined\n : (use.outcome.providerMessage ?? '').slice(0, 500) || undefined;\n }\n\n try {\n await this.systemAccess.updateAsSystem(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n use.credentialId,\n patch,\n {\n scopeContext: { organizationId: use.organizationId },\n /*\n * `lastUsedAt`, `lastValidatedAt` and `validationError` are all\n * `.excludeFromCreate().excludeFromUpdate()`, so the repository's strict `requestDto.parse`\n * drops them before persistence unless they are allow-listed here.\n *\n * The automatic diff that populates this list covers fields a custom-impl PREFIX hook\n * injected — which is how `secretSetAt` reaches the row on a write. Nothing populates it\n * for a payload a caller passes directly, which is what this is, so the omission was\n * silent in the worst way: `validationState` is NOT excluded and moved correctly, so the\n * row went INVALID while the timestamp and the provider's explanation of WHY vanished.\n * A person looking at a credential marked invalid with no reason and no last-use time is\n * being told less than the code believes it recorded.\n */\n preserveServerInjectedFields: ['lastUsedAt', 'lastValidatedAt', 'validationError'],\n },\n );\n } catch (error) {\n this.logger.warn?.(\n '[organization-provider-credential] failed to record credential use',\n {\n organizationId: use.organizationId,\n providerRef: use.providerRef,\n secretSlug: use.secretSlug,\n credentialId: use.credentialId,\n error: describeCaughtError(error),\n },\n );\n }\n }\n\n private async emitUseAudit(use: {\n organizationId: string;\n providerRef: string;\n secretSlug: string;\n source: ProviderCredentialResolutionSource;\n credentialId?: string;\n }): Promise<void> {\n if (!this.auditLogs) {\n return;\n }\n try {\n await this.auditLogs.logOrganizationProviderCredentialUsed({\n organizationId: use.organizationId,\n providerRef: use.providerRef,\n secretSlug: use.secretSlug,\n resolvedFrom: use.source,\n credentialId: use.credentialId,\n });\n } catch (error) {\n this.logger.warn?.(\n '[organization-provider-credential] failed to emit credential-use audit event',\n {\n organizationId: use.organizationId,\n providerRef: use.providerRef,\n error: describeCaughtError(error),\n },\n );\n }\n }\n\n\n /**\n * Record a grant the authorization exchange just minted, replacing one already stored.\n *\n * The plaintext goes in and the resource's own WRITE DOOR seals it — the same hook that seals a\n * credential a person types, and the same reason `persistRenewedGrant` hands over plaintext:\n * `createAsSystem` / `updateAsSystem` reach the SERVICE tier, so a pre-sealed value arrives at\n * that hook and the envelope refuses to double-seal.\n *\n * ## Reconnecting REPLACES rather than adding a second row\n *\n * The business key is (organizationId, providerRef, secretSlug) and it is UNIQUE, so a second connect would\n * violate the index. Read-then-write is a race, and the honest statement is that the index is what\n * decides it: two simultaneous connects mean one of them loses, which is the correct outcome —\n * a person who authorized twice gets one connection, not two half-connections.\n *\n * @returns the credential row's id, so the caller can name it in an audit event.\n */\n public async storeGrant(\n query: OrganizationProviderCredentialQuery,\n grant: ProviderOAuth2Grant,\n connectionParameters?: Readonly<Record<string, string>>,\n ): Promise<string> {\n const existing = await this.readCredentialRow(query);\n const secretValue = serializeProviderOAuth2Grant(grant);\n const scopeContext = { organizationId: query.organizationId };\n\n if (existing) {\n // `connectionParameters` is `.excludeFromUpdate()` — it describes the ACCOUNT the grant is\n // for, and re-authorizing against a different directory is a different connection. A\n // reconnect that changed them would point the refresh somewhere the token was not issued.\n await this.systemAccess.updateAsSystem(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n existing._id,\n {\n secretValue,\n enabled: true,\n // Clearing the mark is part of reconnecting, not a separate concern. A row retired by\n // `renewOrRetire` would otherwise keep `validationState: INVALID` forever — so somebody\n // who did exactly what the screen told them to do would reconnect successfully and still\n // be shown a broken connection.\n validationState: ProviderCredentialValidationState.UNVALIDATED,\n validationError: undefined,\n },\n { scopeContext, preserveServerInjectedFields: ['validationError'] },\n );\n await this.emitConnectionGranted(query, grant, existing._id, true);\n return existing._id;\n }\n\n const created = await this.systemAccess.createAsSystem<OrganizationProviderCredential>(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n {\n organizationId: query.organizationId,\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n secretValue,\n ...(connectionParameters === undefined ? {} : { connectionParameters }),\n },\n { scopeContext },\n );\n await this.emitConnectionGranted(query, grant, created._id, false);\n return created._id;\n }\n\n /**\n * Store a credential somebody TYPED, as opposed to one an exchange minted.\n *\n * The other half of `storeGrant`, and separate from it because the two differ in every way that\n * matters: a grant is a JSON document with an expiry and a refresh token, this is one opaque value;\n * a grant arrives from a vendor, this arrives from a person; a grant can be renewed, this can only\n * be replaced. Serialising a typed key through the grant envelope would put\n * `wildo-oauth2-grant:{...}` on the wire as a bearer token.\n *\n * PLAINTEXT to the write door, which seals. Handing a pre-sealed value to `createAsSystem` reaches\n * the service tier where the sealing hook refuses to double-seal — so the write would throw after\n * the person had already typed their key.\n *\n * Replaces rather than duplicates: the business key is (owner, provider, slug), so re-entering a\n * rotated key is the ordinary case and a second create would violate the index. Re-entering also\n * RE-ENABLES and clears any validation mark, because somebody who has just supplied a working key\n * should not be shown a broken connection.\n */\n public async storeDeclaredSecret(query: OrganizationProviderCredentialQuery, secretValue: string): Promise<string> {\n const existing = await this.readCredentialRow(query);\n const scopeContext = { organizationId: query.organizationId };\n\n if (existing) {\n await this.systemAccess.updateAsSystem(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n existing._id,\n {\n secretValue,\n enabled: true,\n validationState: ProviderCredentialValidationState.UNVALIDATED,\n validationError: undefined,\n },\n { scopeContext, preserveServerInjectedFields: ['validationError'] },\n );\n return existing._id;\n }\n\n const created = await this.systemAccess.createAsSystem<OrganizationProviderCredential>(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n {\n organizationId: query.organizationId,\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n secretValue,\n },\n { scopeContext },\n );\n return created._id;\n }\n\n /**\n * Renew the grant, and RETIRE the connection when the vendor says it is finished.\n *\n * Without this the refresh call was unguarded, and the failure was slow and silent in the worst\n * direction. A vendor that permanently rejects a refresh token — the person removed the app at the\n * vendor, an administrator revoked it, the token aged past its absolute lifetime — throws, the\n * error propagates out of the resolve, and NOTHING touches the row. `validationState` stays where\n * it was, so the connected-accounts screen goes on showing the account as connected, every call\n * fails identically forever, and the person is never told the one thing they could act on.\n *\n * Only `invalid_grant` retires a connection, and the exclusions are the substantive part. A\n * transport failure, a bare 500 or an unparseable body means the vendor said NOTHING about the\n * grant, and retiring a working connection because we could not reach a vendor for thirty seconds\n * would be a self-inflicted outage. `invalid_client` is excluded for a different reason: it is the\n * APPLICATION's own registration being rejected, one operator's misconfiguration affecting every\n * connection at once — marking each person's account invalid would blame all of them for something\n * none of them can fix.\n *\n * The mark is best-effort and the ORIGINAL error is always re-thrown: the caller needs the real\n * cause, and a bookkeeping write that failed must not replace it with a different story.\n */\n private async renewOrRetire(\n credentialId: string,\n query: OrganizationProviderCredentialQuery,\n request: Parameters<ProviderOAuth2RefresherPort['refreshGrant']>[0],\n ): Promise<ProviderOAuth2Grant> {\n try {\n return await this.refresher!.refreshGrant(request);\n } catch (error) {\n if (providerOAuth2GrantWasPermanentlyRejected(error)) {\n try {\n await this.systemAccess.updateAsSystem(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n credentialId,\n {\n validationState: ProviderCredentialValidationState.INVALID,\n lastValidatedAt: new Date(),\n // The vendor's own code, and nothing derived from the credential. This field is\n // CLIENT-READABLE, so anything token-shaped reaching it would publish a secret onto\n // the screen that displays it.\n validationError: 'The provider rejected the stored authorization (invalid_grant). Reconnect the account.',\n },\n {\n scopeContext: { organizationId: query.organizationId },\n // Both of these are `.excludeFromUpdate()`; without the allow-list the row would go\n // INVALID carrying no reason and no timestamp — see `recordCredentialUse`.\n preserveServerInjectedFields: ['lastValidatedAt', 'validationError'],\n },\n );\n } catch (markError) {\n this.logger.warn?.(\n '[organization-provider-credential] a grant was permanently rejected and the row could not be marked',\n { providerRef: query.providerRef, secretSlug: query.secretSlug, credentialId, error: describeCaughtError(markError) },\n );\n }\n }\n throw error;\n }\n }\n\n /**\n * Record that a delegated authorization was GRANTED, distinct from the row's own `_SET` event.\n *\n * Emitted HERE and nowhere else, because this is the only place that holds the three facts an\n * auditor wants and the row does not: the scopes the vendor actually issued, which account they\n * were issued for, and whether this replaced a connection that already existed. By the time the\n * resource's own write hook sees the row, the value is sealed and none of it is recoverable.\n *\n * Best-effort, like every other emission on this path. The grant is already stored and the person\n * has already authorized it; failing their connection because a trail write did not land would\n * turn a completed authorization into an error and invite them to grant it a second time.\n */\n private async emitConnectionGranted(\n query: OrganizationProviderCredentialQuery,\n grant: ProviderOAuth2Grant,\n credentialId: string,\n replacedExistingConnection: boolean,\n ): Promise<void> {\n if (!this.auditLogs) {\n return;\n }\n try {\n await this.auditLogs.logOrganizationProviderConnectionGranted({\n organizationId: query.organizationId,\n providerRef: query.providerRef,\n secretSlug: query.secretSlug,\n credentialId,\n grantedScopes: grant.grantedScopes,\n accountRef: grant.accountRef,\n replacedExistingConnection,\n });\n } catch (error) {\n this.logger.warn?.(\n '[organization-provider-credential] a connection was granted and the audit event could not be emitted',\n { providerRef: query.providerRef, secretSlug: query.secretSlug, credentialId, error: describeCaughtError(error) },\n );\n }\n }\n\n /**\n * Persist a renewed grant through the resource's own WRITE door.\n *\n * The plaintext goes in and the CUSTOM IMPLEMENTATION seals it — the same hook that seals a\n * credential a person types. Sealing here instead would be a second sealing site for one\n * invariant, and it does not merely duplicate: `updateAsSystem` reaches the service tier, so a\n * pre-sealed value arrives at that hook and the envelope REFUSES it (\"double-sealing would hand\n * the envelope itself to the provider\"). Every refresh would have thrown at the write-back.\n *\n * `secretSetAt` therefore moves, and that is correct rather than tolerated: the field is defined\n * as \"when the stored VALUE last changed\", and a renewal changes it. An earlier version of this\n * method held it still on the theory that it should mean \"when a HUMAN last supplied a value\" —\n * that is a different field, and inventing the behaviour without the field was the error.\n *\n * NOT best-effort. A refresh that is not persisted happens again on every call, and against a\n * vendor that rotates the refresh token each one invalidates the last — so the connection breaks\n * while every individual exchange succeeds.\n */\n private async persistRenewedGrant(\n query: OrganizationProviderCredentialQuery,\n credentialId: string,\n renewed: ProviderOAuth2Grant,\n ): Promise<void> {\n await this.systemAccess.updateAsSystem(\n CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n credentialId,\n { secretValue: serializeProviderOAuth2Grant(renewed) },\n { scopeContext: { organizationId: query.organizationId } },\n );\n }\n\n /**\n * Turn an envelope failure into the operator-facing statement.\n *\n * Exposed so the registry can distinguish \"this tenant has no credential\" (fall through to the\n * environment) from \"this tenant HAS one and it is broken\" (refuse, loudly) without importing the\n * envelope's error type and re-deriving the distinction. One definition, one meaning.\n */\n public static isUnopenableCredential(error: unknown): error is ProviderCredentialEnvelopeError {\n return error instanceof ProviderCredentialEnvelopeError;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organization-provider-credentials.custom-impl.backend.service.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"organization-provider-credentials.custom-impl.backend.service.d.ts","sourceRoot":"","sources":["../../../../../src/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAkBH,OAAO,EAEL,KAAK,0CAA0C,EAChD,MAAM,4GAA4G,CAAC;AAqZpH,yEAAyE;AACzE,wBAAgB,6CAA6C,IAAI,0CAA0C,EAAE,CAM5G"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organization-provider-credentials.custom-impl.backend.service.js","sourceRoot":"","sources":["../../../../../../src/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAGH,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,SAAS,EACT,2BAA2B,EAC3B,gCAAgC,EAChC,4BAA4B,EAC5B,sBAAsB,EACtB,kCAAkC,GAEnC,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,sCAAsC,EAAE,MAAM,sCAAsC,CAAC;AAE9F,OAAO,EACL,yCAAyC,GAE1C,MAAM,4GAA4G,CAAC;AAIpH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AAGpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,4EAA4E,CAAC;AACjH,OAAO,EAAE,2BAA2B,EAAE,MAAM,8EAA8E,CAAC;AAE3H,OAAO,EAAE,sBAAsB,EAAE,MAAM,qDAAqD,CAAC;AAS7F;;;;;;;;;;;;;GAaG;AACH,SAAS,oBAAoB,CAC3B,KAA0C,EAC1C,gBAAuC,EACvC,KAAmD;IAEnD,MAAM,OAAO,GAAG,KAAK,CAAC,aAA2D,CAAC;IAElF,qEAAqE;IACrE,EAAE;IACF,6FAA6F;IAC7F,2FAA2F;IAC3F,kGAAkG;IAClG,qCAAqC;IACrC,EAAE;IACF,iGAAiG;IACjG,4FAA4F;IAC5F,gGAAgG;IAChG,gGAAgG;IAChG,mDAAmD;IACnD,MAAM,cAAc,GAClB,CAAC,OAAO,OAAO,EAAE,cAAc,KAAK,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC;WACpE,gBAAgB,CAAC,oBAAoB,EAAE,CAAC,kCAAkC,CAAC,gBAAgB,CAAC,aAAa,CAAU,CAAC,CAAC;IAE1H,MAAM,WAAW,GACf,CAAC,OAAO,KAAK,EAAE,WAAW,KAAK,QAAQ,IAAI,KAAK,CAAC,WAAW,CAAC;WAC1D,CAAC,OAAO,OAAO,EAAE,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAElF,MAAM,UAAU,GACd,CAAC,OAAO,KAAK,EAAE,UAAU,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC;WACxD,CAAC,OAAO,OAAO,EAAE,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEhF,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,CAAC,cAAc,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU,EAAE,CAAC;QACzF,8FAA8F;QAC9F,uFAAuF;QACvF,MAAM,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,aAAa,EAAE,gBAAgB,EAAE;YAC7E,sBAAsB,EAAE,2BAA2B,CAAC,aAAa;YACjE,OAAO,EAAE;gBACP,OAAO,EACL,gGAAgG;sBAC9F,oGAAoG;sBACpG,mGAAmG;gBACvG,iBAAiB,EAAE,OAAO,CAAC,cAAc,CAAC;gBAC1C,cAAc,EAAE,OAAO,CAAC,WAAW,CAAC;gBACpC,aAAa,EAAE,OAAO,CAAC,UAAU,CAAC;aACnC;SACF,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;AACrD,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,kBAAkB,CACzB,KAA0C,EAC1C,gBAAuC,EACvC,KAAmD,EACnD,SAAoB;IAEpB,MAAM,OAAO,GAAG,KAAK,IAAI,SAAS,CAAC;IACnC,MAAM,QAAQ,GAAG,OAAO,EAAE,WAAW,CAAC;IAEtC,8FAA8F;IAC9F,sCAAsC;IACtC,EAAE;IACF,+FAA+F;IAC/F,mGAAmG;IACnG,iGAAiG;IACjG,6FAA6F;IAC7F,gGAAgG;IAChG,0BAA0B;IAC1B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,mGAAmG;IACnG,+FAA+F;IAC/F,4EAA4E;IAC5E,IAAI,QAAQ,KAAK,sBAAsB,EAAE,CAAC;QACxC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,OAAkC,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,EAAE,gBAAgB,EAAE;YAC1E,sBAAsB,EAAE,2BAA2B,CAAC,UAAU;YAC9D,OAAO,EAAE,EAAE,OAAO,EAAE,uEAAuE,EAAE;SAC9F,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAA0B,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAE9F,MAAM,YAAY,GAAG,gBAAgB,EAAE,YAAY,EAAE,MAAM,CAAC;IAE5D,OAAO;QACL,GAAG,OAAO;QACV,WAAW,EAAE,sBAAsB,CACjC,QAAQ,EACR,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,aAAa,EAChD;YACE,UAAU,EAAE,sCAAsC,CAAC,YAAY;YAC/D,OAAO,EAAE,QAAQ,CAAC,cAAc;YAChC,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,UAAU,EAAE,QAAQ,CAAC,UAAU;SAChC,CACF;QACD,kGAAkG;QAClG,+FAA+F;QAC/F,mFAAmF;QACnF,WAAW,EAAE,IAAI,IAAI,EAAE;QACvB,iGAAiG;QACjG,4FAA4F;QAC5F,mEAAmE;QACnE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvD,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,wBAAwB,CACrC,SAAoB;AACpB;;;;;GAKG;AACH,SAE0E,EAC1E,GAA+C,EAC/C,mBAAqC,EACrC,gBAAuC,EACvC,KAAmD;IAEnD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;QAClF,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAClB,+GAA+G,EAC/G,EAAE,SAAS,EAAE,CACd,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAA0B,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;QAC9F,MAAM,MAAM,GAAG;YACb,cAAc,EAAE,GAAG,CAAC,cAAc;YAClC,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,YAAY,EAAE,GAAG,CAAC,GAAG;SACtB,CAAC;QACF,IAAI,SAAS,KAAK,sBAAsB,CAAC,oCAAoC,EAAE,CAAC;YAC9E,MAAM,SAAS,CAAC,oCAAoC,CAClD,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,EAC3D,gBAAgB,CACjB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,CAAC,wCAAwC,CACtD;gBACE,GAAG,MAAM;gBACT,SAAS,EAAE,mBAAmB,CAAC,gBAAgB,CAAC;gBAChD,mBAAmB,EAAE,mBAAmB,EAAE,WAAW,EAAE;aACxD,EACD,gBAAgB,CACjB,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,iEAAiE,EAAE;YACtF,SAAS;YACT,YAAY,EAAE,GAAG,CAAC,GAAG;YACrB,GAAG,2BAA2B,CAAC,KAAK,CAAC;SACtC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,6BAA6B;IACpC,MAAM,OAAO,GAAG,CAAC,SAA0C,EAAE,SAAoB,EAAE,EAAE,CACnF,yCAAyC,CAAC;QACxC,aAAa,EAAE;YACb,kBAAkB,EAAE,gBAAgB,CAAC,wBAAwB;YAC7D,mBAAmB,EAAE,qBAAqB,CAAC,MAAM;YACjD,WAAW,EAAE,4BAA4B,CAAC,QAAQ;YAClD,kBAAkB,EAAE,IAAI;SACzB;QACD,UAAU,EAAE,uDAAuD;QACnE;;;;;;;;;;;;;;WAcG;QACH,mBAAmB,EAAE,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC;QAClE,QAAQ,EAAE;YACR,oBAAoB,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,CAClF,kBAAkB,CAAC,KAA4C,EAAE,gBAAgB,EAAE,KAAK,EAAE,SAAS,CAAC;YACtG,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE;gBACrF,MAAM,wBAAwB,CAC5B,SAAS,EACT,sBAAsB,CAAC,oCAAoC,EAC3D,OAAqD,EACrD,SAAS,EACT,gBAAgB,EAChB,KAAK,CACN,CAAC;gBACF,OAAO,OAAO,CAAC;YACjB,CAAC;SACF;KACF,CAAC,CAAC;IACL,OAAO,OAAgE,CAAC;AAC1E,CAAC;AAED;;;;;;GAMG;AACH,SAAS,6BAA6B;IACpC,MAAM,OAAO,GAAG,CAAC,SAA0C,EAAE,SAAoB,EAAE,EAAE,CACnF,yCAAyC,CAAC;QACxC,aAAa,EAAE;YACb,kBAAkB,EAAE,gBAAgB,CAAC,wBAAwB;YAC7D,mBAAmB,EAAE,qBAAqB,CAAC,MAAM;YACjD,WAAW,EAAE,4BAA4B,CAAC,QAAQ;YAClD,kBAAkB,EAAE,IAAI;SACzB;QACD,UAAU,EAAE,uDAAuD;QACnE;;;;;;;;;;;;;;WAcG;QACH,mBAAmB,EAAE,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC;QAClE,QAAQ,EAAE;YACR,oBAAoB,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE;gBAClF,MAAM,MAAM,GAAG,kBAAkB,CAC/B,KAA4C,EAC5C,gBAAgB,EAChB,KAAK,EACL,SAAS,CACV,CAAC;gBACF,2FAA2F;gBAC3F,2FAA2F;gBAC3F,qBAAqB,CAAC,GAAG,CAAC,gBAAgB,EAAE;oBAC1C,OAAO,EAAE,MAAM,EAAE,WAAW,KAAK,SAAS;oBAC1C,mBAAmB,EAAG,KAAK,CAAC,aAA4D,EAAE,WAAW;iBACtG,CAAC,CAAC;gBACH,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE;gBACrF,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;gBAC3D,qBAAqB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;gBAC/C,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;oBACpB,MAAM,wBAAwB,CAC5B,SAAS,EACT,sBAAsB,CAAC,wCAAwC,EAC/D,OAAqD,EACrD,MAAM,CAAC,mBAAmB,EAC1B,gBAAgB,EAChB,KAAK,CACN,CAAC;gBACJ,CAAC;gBACD,OAAO,OAAO,CAAC;YACjB,CAAC;SACF;KACF,CAAC,CAAC;IACL,OAAO,OAAgE,CAAC;AAC1E,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,6BAA6B;IACpC,MAAM,OAAO,GAAG,CAAC,SAA0C,EAAE,SAAoB,EAAE,EAAE,CACnF,yCAAyC,CAAC;QACxC,aAAa,EAAE;YACb,kBAAkB,EAAE,gBAAgB,CAAC,wBAAwB;YAC7D,mBAAmB,EAAE,qBAAqB,CAAC,MAAM;YACjD,WAAW,EAAE,4BAA4B,CAAC,QAAQ;YAClD,kBAAkB,EAAE,IAAI;SACzB;QACD,UAAU,EAAE,8CAA8C;QAC1D,QAAQ,EAAE;YACR,qBAAqB,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE;gBACnF,6FAA6F;gBAC7F,yDAAyD;gBACzD,MAAM,QAAQ,GAAG,KAAK,CAAC,aAA2D,CAAC;gBACnF,MAAM,YAAY,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBAEhF,IAAI,CAAC,QAAQ,EAAE,cAAc,IAAI,CAAC,YAAY,EAAE,CAAC;oBAC/C,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAClB,iHAAiH,EACjH,EAAE,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAC7D,CAAC;oBACF,OAAO,MAAM,CAAC;gBAChB,CAAC;gBAED,IAAI,CAAC;oBACH,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,CAA0B,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;oBAC9F,MAAM,SAAS,CAAC,wCAAwC,CACtD;wBACE,cAAc,EAAE,QAAQ,CAAC,cAAc;wBACvC,WAAW,EAAE,QAAQ,CAAC,WAAW;wBACjC,UAAU,EAAE,QAAQ,CAAC,UAAU;wBAC/B,YAAY;wBACZ,MAAM,EAAE,gCAAgC,CAAC,qBAAqB;wBAC9D,SAAS,EAAE,mBAAmB,CAAC,gBAAgB,CAAC;qBACjD,EACD,gBAAgB,CACjB,CAAC;gBACJ,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,0EAA0E,EAAE;wBAC/F,YAAY;wBACZ,GAAG,2BAA2B,CAAC,KAAK,CAAC;qBACtC,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,MAAM,CAAC;YAChB,CAAC;SACF;KACF,CAAC,CAAC;IACL,OAAO,OAAgE,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,MAAM,qBAAqB,GAAG,IAAI,OAAO,EAA4D,CAAC;AAEtG,yEAAyE;AACzE,MAAM,UAAU,6CAA6C;IAC3D,OAAO;QACL,6BAA6B,EAAE;QAC/B,6BAA6B,EAAE;QAC/B,6BAA6B,EAAE;KAChC,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The WRITE path for an organization's provider credential: seal on the way in, audit on the way\n * out.\n *\n * ## Without this file the resource stores plaintext\n *\n * The schema declares `secretValue` as `.isWriteOnlySecret()`, which governs how the value is\n * PRESENTED (redacted at the client boundary, and a round-tripped mask means \"keep the stored\n * secret\"). It says nothing about how the value is STORED — a write-only-secret field lands in the\n * database exactly as the client typed it. Sealing it is this hook's job, and it is the only place\n * that job is done, so a credential reaching persistence unsealed means this registration did not\n * resolve.\n *\n * ⚠️ A custom implementation resolves by an EXACT operation-path key embedding the resource, the\n * operation, the variant TYPE and the default/variant-key slot. A registration naming a combination\n * the resource configuration does not declare resolves nothing and silently never runs, while the\n * route still answers 200 — here that would mean every credential persisted in plaintext behind a\n * green suite. The pins in `__tests__/organization-provider-credentials-write-path.backend.test.ts`\n * assert these registrations against the REAL resource configuration for that reason.\n *\n * ## The DELETE doors — enumerated, because only one of them reaches this file\n *\n * | Door | Path | This hook |\n * |---|---|---|\n * | A tenant administrator revoking a credential | service tier, `DELETE` default variant | RUNS |\n * | The ORGANIZATIONS purge cascade (both the batch's route-less default door and the super-admin's `admin` door reach the same cascade) | `deleteChildrenImmediate` → the RAW repository | does NOT run |\n *\n * Door 2 is not an oversight and not a hole in the ERASURE: the cascade removes the rows, which is\n * what matters, and `services-registry-handler.backend.service.ts` documents the raw-repository\n * route explicitly (\"VARIANT-AGNOSTIC CASCADE: the onParentDelete teardown deletes children directly\n * through the RAW repository\"). What door 2 has no way to produce is a per-credential AUDIT event,\n * because the service tier — where custom implementations live — is bypassed entirely. Emitting one\n * would need a cascade-tier audit hook in the framework, which is outside this resource. The tenant\n * purge is itself audited as `ORGANIZATION_DELETED`, so the destruction is on the record; what is\n * missing is the enumeration of WHICH third parties the tenant held credentials for at that moment.\n * Recorded as its own issue rather than left for a reader to discover from an absence.\n */\n\nimport type { Container } from 'inversify';\nimport {\n CoreAuditableEventType,\n CoreResourceOperation,\n CoreResourceType,\n ErrorType,\n ErrorCustomMessageReference,\n ProviderCredentialDeletionReason,\n ResourceOperationVariantType,\n WRITE_ONLY_SECRET_MASK,\n coreResourceShared_FieldIdentifier,\n type OrganizationProviderCredential,\n} from '@wildo-ai/saas-models';\n\nimport { ExternalProvider_Connection_OwnerScope } from '@wildo-ai/external-connectors-models';\n\nimport {\n createResourceCustomServiceImplementation,\n type ResourceCustomServiceImplementationFactory,\n} from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation.factory.backend';\nimport type { ResourceOperation_CustomImplementation_Utils } from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation-base.backend.service';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport type { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';\nimport { resolveAuditActorId } from '~wildo-backend-lib/compliance/audit-trails/utils/audit-actor.backend.utils';\nimport { projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\n\nimport { sealProviderCredential } from '../utils/provider-credential-envelope.backend.utils';\n\n/** The row identity the seal binds to, resolved from whichever channel actually carries each part. */\ninterface CredentialWriteIdentity {\n organizationId: string;\n providerRef: string;\n secretSlug: string;\n}\n\n/**\n * Resolve the row identity for a write.\n *\n * The three parts come from three DIFFERENT places, and that is the reason this is a function rather\n * than three property reads:\n *\n * - `organizationId` is injected by the context machinery from the request SCOPE, so on CREATE it is\n * not in the input payload at all. The execution context's context-resource map is the\n * authoritative channel — the same one `buildContextualFilter` and `enrichDataWithContext` read —\n * which is what makes the seal bind to the tenant the framework will actually store the row under,\n * rather than to one a caller could name in a body field.\n * - `providerRef` / `secretSlug` are client-supplied on CREATE and `.excludeFromUpdate()` afterwards,\n * so on UPDATE they must come from the pre-fetched current row.\n */\nfunction resolveWriteIdentity(\n input: Record<string, unknown> | undefined,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n): CredentialWriteIdentity {\n const current = utils.currentObject as OrganizationProviderCredential | undefined;\n\n // Two sources, and the request BODY is deliberately not one of them.\n //\n // On UPDATE the stored row is authoritative — it is what the framework already persisted. On\n // CREATE the execution context's context-resource map is, because that is the same channel\n // `enrichDataWithContext` reads when it injects the scope FK, so the seal binds to the tenant the\n // row will actually be stored under.\n //\n // A `payload.organizationId` fallback was here and was REMOVED: it fails safe (a seal bound to a\n // body-supplied tenant is simply unopenable later, so the outcome is a denial rather than a\n // disclosure) but it is still the request choosing what the seal binds to, which is exactly the\n // authorship this hook exists to keep out of a caller's hands. With no fallback, a context that\n // cannot name the tenant is a REFUSAL — see below.\n const organizationId =\n (typeof current?.organizationId === 'string' && current.organizationId)\n || executionContext.getContextResourceId?.(coreResourceShared_FieldIdentifier[CoreResourceType.ORGANIZATIONS] as never);\n\n const providerRef =\n (typeof input?.providerRef === 'string' && input.providerRef)\n || (typeof current?.providerRef === 'string' ? current.providerRef : undefined);\n\n const secretSlug =\n (typeof input?.secretSlug === 'string' && input.secretSlug)\n || (typeof current?.secretSlug === 'string' ? current.secretSlug : undefined);\n\n if (typeof organizationId !== 'string' || !organizationId || !providerRef || !secretSlug) {\n // Fail CLOSED. Sealing under a partial identity would produce a credential bound to the wrong\n // row — unopenable at resolution time, and indistinguishable then from a tampered one.\n throw utils.errorBuilder.buildError(ErrorType.CONFIGURATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.CONFIGURATION,\n context: {\n message:\n 'Cannot seal an organization provider credential: the row identity is incomplete. All three of '\n + 'organizationId, providerRef and secretSlug must be resolvable, because the seal is bound to them. '\n + 'The organization is read from the execution scope or the stored row, never from the request body.',\n hasOrganizationId: Boolean(organizationId),\n hasProviderRef: Boolean(providerRef),\n hasSecretSlug: Boolean(secretSlug),\n },\n });\n }\n\n return { organizationId, providerRef, secretSlug };\n}\n\n/**\n * Seal `secretValue` if the write carries one.\n *\n * An ABSENT `secretValue` is normal on UPDATE and must pass through untouched: the framework strips\n * the field when a client echoes back the redaction mask, which is how \"edit the description without\n * retyping the secret\" works. Re-sealing nothing would be harmless; treating absence as an error\n * would break the ordinary edit.\n */\nfunction sealIncomingSecret(\n input: Record<string, unknown> | undefined,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n container: Container,\n): Record<string, unknown> | undefined {\n const payload = input ?? undefined;\n const incoming = payload?.secretValue;\n\n // ABSENT means \"no change\", and only absent. `null` is deliberately NOT treated as absent and\n // falls through to the refusal below.\n //\n // That distinction became load-bearing the moment `secretValue` was declared authoritative: an\n // authoritative field's post-prefix value is always carried past the repository's strict re-parse,\n // so passing a `null` through here would push it INTO persistence rather than letting the schema\n // reject it. The row would then hold a null where `z.string().min(1)` is required, and every\n // later read would throw in `transformOutput` — a write that answers success and leaves the row\n // permanently unreadable.\n if (incoming === undefined) {\n return payload;\n }\n\n // Defence in depth. The framework strips the mask sentinel before this hook runs, so reaching here\n // with the mask means that strip did not happen — and sealing the mask would store the literal\n // bullet characters as the tenant's credential, then hand them to a vendor.\n if (incoming === WRITE_ONLY_SECRET_MASK) {\n const { secretValue: _discarded, ...rest } = payload as Record<string, unknown>;\n return rest;\n }\n\n if (typeof incoming !== 'string' || incoming.length === 0) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: 'An organization provider credential value must be a non-empty string.' },\n });\n }\n\n const identity = resolveWriteIdentity(payload, executionContext, utils);\n const appConfig = container.get<AppConfigurationService>(SAAS_SERVICE_TYPES.AppConfigService);\n\n const actingUserId = executionContext?.initiatorIds?.userId;\n\n return {\n ...payload,\n secretValue: sealProviderCredential(\n incoming,\n appConfig.secrets.security.session.encryptionKey,\n {\n ownerScope: ExternalProvider_Connection_OwnerScope.ORGANIZATION,\n ownerId: identity.organizationId,\n providerRef: identity.providerRef,\n secretSlug: identity.secretSlug,\n },\n ),\n // Server-owned provenance. Both are `.excludeFromCreate().excludeFromUpdate()`, so returning them\n // here is what carries them past the strict re-parse — the same mechanism api-key minting uses\n // for its hashed material, and declared explicitly in `authoritativeFields` below.\n secretSetAt: new Date(),\n // Only when there IS an acting user. Writing the key with an `undefined` value would preserve an\n // explicit `undefined` past the re-parse rather than leaving the field absent, and \"absent\"\n // is the honest representation of a write with no human behind it.\n ...(actingUserId ? { setByUserId: actingUserId } : {}),\n };\n}\n\n/**\n * Emit the lifecycle event for a completed write.\n *\n * Best-effort in the same posture as every other audit emission in the engine: the credential has\n * already been written, and turning a logging failure into a 500 would tell the tenant their write\n * failed when it did not.\n */\nasync function emitCredentialWriteAudit(\n container: Container,\n /**\n * WHICH grant event this write is. Typed as the audit vocabulary's own two members rather than a\n * bespoke `'set' | 'rotated'` pair: the distinction already has a named runtime source, and a\n * second spelling of it would be a closed vocabulary with no home and one more thing to keep in\n * step with the event names.\n */\n eventType:\n | typeof CoreAuditableEventType.ORGANIZATION_PROVIDER_CREDENTIAL_SET\n | typeof CoreAuditableEventType.ORGANIZATION_PROVIDER_CREDENTIAL_ROTATED,\n row: OrganizationProviderCredential | undefined,\n previousSecretSetAt: Date | undefined,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n): Promise<void> {\n if (!row || typeof row._id !== 'string' || typeof row.organizationId !== 'string') {\n utils.logger.error?.(\n 'An organization provider credential was written but the row could not be identified — audit event not emitted',\n { eventType },\n );\n return;\n }\n\n try {\n const auditLogs = container.get<AuditLogsBackendService>(SAAS_SERVICE_TYPES.AuditLogsService);\n const common = {\n organizationId: row.organizationId,\n providerRef: row.providerRef,\n secretSlug: row.secretSlug,\n credentialId: row._id,\n };\n if (eventType === CoreAuditableEventType.ORGANIZATION_PROVIDER_CREDENTIAL_SET) {\n await auditLogs.logOrganizationProviderCredentialSet(\n { ...common, setBy: resolveAuditActorId(executionContext) },\n executionContext,\n );\n } else {\n await auditLogs.logOrganizationProviderCredentialRotated(\n {\n ...common,\n rotatedBy: resolveAuditActorId(executionContext),\n previousSecretSetAt: previousSecretSetAt?.toISOString(),\n },\n executionContext,\n );\n }\n } catch (error) {\n utils.logger.error?.('Failed to emit the organization provider credential audit event', {\n eventType,\n credentialId: row._id,\n ...projectCaughtErrorLogFields(error),\n });\n }\n}\n\n/**\n * CREATE — the tenant grants this application authority toward a third party for the first time.\n */\nfunction createCredentialCreateFactory(): ResourceCustomServiceImplementationFactory {\n const factory = (_registry: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n operationIdentifier: CoreResourceOperation.CREATE,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: 'organizationProviderCredentials.create.seal-and-audit',\n /**\n * The three fields this hook OWNS, declared rather than inferred.\n *\n * `preserveServerInjectedFields` is normally derived by diffing the prefix output against a\n * snapshot of the payload keys taken BEFORE the prefix ran, so only keys the hook INTRODUCED\n * survive the repository's strict re-parse. That inference has a documented hole: a caller\n * reaching the service tier with the key already present — MCP `callTool` forwards its\n * arguments with no strict parse — puts it into the snapshot, the hook's value is then not\n * classified as introduced, and the repository strips it while the operation answers success.\n *\n * For `secretSetAt` / `setByUserId` that would silently lose the provenance of a credential,\n * which is the first thing an incident asks for. For `secretValue` the declaration says the\n * thing that matters most in this file: whatever a caller sent, what reaches persistence is\n * the POST-prefix value — the sealed envelope — and never the plaintext they supplied.\n */\n authoritativeFields: ['secretValue', 'secretSetAt', 'setByUserId'],\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) =>\n sealIncomingSecret(input as Record<string, unknown> | undefined, executionContext, utils, container),\n postfixCoreOperations: async (_id, created, executionContext, _operationPath, utils) => {\n await emitCredentialWriteAudit(\n container,\n CoreAuditableEventType.ORGANIZATION_PROVIDER_CREDENTIAL_SET,\n created as OrganizationProviderCredential | undefined,\n undefined,\n executionContext,\n utils,\n );\n return created;\n },\n },\n });\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n/**\n * UPDATE — a rotation, or an ordinary metadata edit.\n *\n * The two are distinguished by whether the write actually carried a NEW secret. An edit that only\n * changes the description emits nothing: a rotation event on a description change would make the\n * one signal a compromise investigation depends on unusable.\n */\nfunction createCredentialUpdateFactory(): ResourceCustomServiceImplementationFactory {\n const factory = (_registry: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n operationIdentifier: CoreResourceOperation.UPDATE,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: 'organizationProviderCredentials.update.seal-and-audit',\n /**\n * The three fields this hook OWNS, declared rather than inferred.\n *\n * `preserveServerInjectedFields` is normally derived by diffing the prefix output against a\n * snapshot of the payload keys taken BEFORE the prefix ran, so only keys the hook INTRODUCED\n * survive the repository's strict re-parse. That inference has a documented hole: a caller\n * reaching the service tier with the key already present — MCP `callTool` forwards its\n * arguments with no strict parse — puts it into the snapshot, the hook's value is then not\n * classified as introduced, and the repository strips it while the operation answers success.\n *\n * For `secretSetAt` / `setByUserId` that would silently lose the provenance of a credential,\n * which is the first thing an incident asks for. For `secretValue` the declaration says the\n * thing that matters most in this file: whatever a caller sent, what reaches persistence is\n * the POST-prefix value — the sealed envelope — and never the plaintext they supplied.\n */\n authoritativeFields: ['secretValue', 'secretSetAt', 'setByUserId'],\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const sealed = sealIncomingSecret(\n input as Record<string, unknown> | undefined,\n executionContext,\n utils,\n container,\n );\n // Bridge to the postfix, keyed by this operation's execution context. Carries only WHETHER\n // the value moved and WHEN the previous one was set — never a secret, in either direction.\n ROTATION_BRIDGE_BY_EC.set(executionContext, {\n rotated: sealed?.secretValue !== undefined,\n previousSecretSetAt: (utils.currentObject as OrganizationProviderCredential | undefined)?.secretSetAt,\n });\n return sealed;\n },\n postfixCoreOperations: async (_id, updated, executionContext, _operationPath, utils) => {\n const bridge = ROTATION_BRIDGE_BY_EC.get(executionContext);\n ROTATION_BRIDGE_BY_EC.delete(executionContext);\n if (bridge?.rotated) {\n await emitCredentialWriteAudit(\n container,\n CoreAuditableEventType.ORGANIZATION_PROVIDER_CREDENTIAL_ROTATED,\n updated as OrganizationProviderCredential | undefined,\n bridge.previousSecretSetAt,\n executionContext,\n utils,\n );\n }\n return updated;\n },\n },\n });\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n/**\n * DELETE — a tenant administrator revoking the grant.\n *\n * `ADMINISTRATOR_REVOKED` unconditionally, and that is CORRECT rather than an assumption: the\n * cascade door never reaches this hook (see the module header), so every delete that arrives here is\n * a deliberate service-tier revocation. If a future change routed a cascade through the service\n * tier, this constant would become a lie — which is why the door table above is pinned by a test\n * rather than left as prose.\n */\nfunction createCredentialDeleteFactory(): ResourceCustomServiceImplementationFactory {\n const factory = (_registry: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n operationIdentifier: CoreResourceOperation.DELETE,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: 'organizationProviderCredentials.delete.audit',\n handlers: {\n postfixCoreOperations: async (id, result, executionContext, _operationPath, utils) => {\n // The pre-deletion snapshot: after the row is gone, the provider and slug are unrecoverable,\n // so an event naming only the id would identify nothing.\n const snapshot = utils.currentObject as OrganizationProviderCredential | undefined;\n const credentialId = snapshot?._id ?? (typeof id === 'string' ? id : undefined);\n\n if (!snapshot?.organizationId || !credentialId) {\n utils.logger.error?.(\n 'An organization provider credential was deleted but the subject could not be resolved — audit event not emitted',\n { addressedIdType: Array.isArray(id) ? 'array' : typeof id },\n );\n return result;\n }\n\n try {\n const auditLogs = container.get<AuditLogsBackendService>(SAAS_SERVICE_TYPES.AuditLogsService);\n await auditLogs.logOrganizationProviderCredentialDeleted(\n {\n organizationId: snapshot.organizationId,\n providerRef: snapshot.providerRef,\n secretSlug: snapshot.secretSlug,\n credentialId,\n reason: ProviderCredentialDeletionReason.ADMINISTRATOR_REVOKED,\n deletedBy: resolveAuditActorId(executionContext),\n },\n executionContext,\n );\n } catch (error) {\n utils.logger.error?.('Failed to emit the organization provider credential deletion audit event', {\n credentialId,\n ...projectCaughtErrorLogFields(error),\n });\n }\n return result;\n },\n },\n });\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n/**\n * Prefix→postfix bridge for the UPDATE hook, keyed by the per-operation execution-context instance.\n *\n * A `WeakMap` so an abandoned operation cannot retain the entry, mirroring the api-key mint bridge.\n * It deliberately carries no secret: only a boolean and a timestamp cross it.\n */\nconst ROTATION_BRIDGE_BY_EC = new WeakMap<object, { rotated: boolean; previousSecretSetAt?: Date }>();\n\n/** Every write door of the organization-provider-credential resource. */\nexport function createOrganizationProviderCredentialFactories(): ResourceCustomServiceImplementationFactory[] {\n return [\n createCredentialCreateFactory(),\n createCredentialUpdateFactory(),\n createCredentialDeleteFactory(),\n ];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"organization-provider-credentials.custom-impl.backend.service.js","sourceRoot":"","sources":["../../../../../src/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The WRITE path for an organization's provider credential: seal on the way in, audit on the way\n * out.\n *\n * ## Without this file the resource stores plaintext\n *\n * The schema declares `secretValue` as `.isWriteOnlySecret()`, which governs how the value is\n * PRESENTED (redacted at the client boundary, and a round-tripped mask means \"keep the stored\n * secret\"). It says nothing about how the value is STORED — a write-only-secret field lands in the\n * database exactly as the client typed it. Sealing it is this hook's job, and it is the only place\n * that job is done, so a credential reaching persistence unsealed means this registration did not\n * resolve.\n *\n * ⚠️ A custom implementation resolves by an EXACT operation-path key embedding the resource, the\n * operation, the variant TYPE and the default/variant-key slot. A registration naming a combination\n * the resource configuration does not declare resolves nothing and silently never runs, while the\n * route still answers 200 — here that would mean every credential persisted in plaintext behind a\n * green suite. The pins in `__tests__/organization-provider-credentials-write-path.backend.test.ts`\n * assert these registrations against the REAL resource configuration for that reason.\n *\n * ## The DELETE doors — enumerated, because only one of them reaches this file\n *\n * | Door | Path | This hook |\n * |---|---|---|\n * | A tenant administrator revoking a credential | service tier, `DELETE` default variant | RUNS |\n * | The ORGANIZATIONS purge cascade (both the batch's route-less default door and the super-admin's `admin` door reach the same cascade) | `deleteChildrenImmediate` → the RAW repository | does NOT run |\n *\n * Door 2 is not an oversight and not a hole in the ERASURE: the cascade removes the rows, which is\n * what matters, and `services-registry-handler.backend.service.ts` documents the raw-repository\n * route explicitly (\"VARIANT-AGNOSTIC CASCADE: the onParentDelete teardown deletes children directly\n * through the RAW repository\"). What door 2 has no way to produce is a per-credential AUDIT event,\n * because the service tier — where custom implementations live — is bypassed entirely. Emitting one\n * would need a cascade-tier audit hook in the framework, which is outside this resource. The tenant\n * purge is itself audited as `ORGANIZATION_DELETED`, so the destruction is on the record; what is\n * missing is the enumeration of WHICH third parties the tenant held credentials for at that moment.\n * Recorded as its own issue rather than left for a reader to discover from an absence.\n */\n\nimport type { Container } from 'inversify';\nimport {\n CoreAuditableEventType,\n CoreResourceOperation,\n CoreResourceType,\n ErrorType,\n ErrorCustomMessageReference,\n ProviderCredentialDeletionReason,\n ResourceOperationVariantType,\n WRITE_ONLY_SECRET_MASK,\n coreResourceShared_FieldIdentifier,\n type OrganizationProviderCredential,\n} from '@wildo-ai/saas-models';\n\nimport { ExternalProvider_Connection_OwnerScope } from '@wildo-ai/external-connectors-models';\n\nimport {\n createResourceCustomServiceImplementation,\n type ResourceCustomServiceImplementationFactory,\n} from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation.factory.backend';\nimport type { ResourceOperation_CustomImplementation_Utils } from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation-base.backend.service';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport type { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';\nimport { resolveAuditActorId } from '~wildo-backend-lib/compliance/audit-trails/utils/audit-actor.backend.utils';\nimport { projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\n\nimport { sealProviderCredential } from '../utils/provider-credential-envelope.backend.utils';\n\n/** The row identity the seal binds to, resolved from whichever channel actually carries each part. */\ninterface CredentialWriteIdentity {\n organizationId: string;\n providerRef: string;\n secretSlug: string;\n}\n\n/**\n * Resolve the row identity for a write.\n *\n * The three parts come from three DIFFERENT places, and that is the reason this is a function rather\n * than three property reads:\n *\n * - `organizationId` is injected by the context machinery from the request SCOPE, so on CREATE it is\n * not in the input payload at all. The execution context's context-resource map is the\n * authoritative channel — the same one `buildContextualFilter` and `enrichDataWithContext` read —\n * which is what makes the seal bind to the tenant the framework will actually store the row under,\n * rather than to one a caller could name in a body field.\n * - `providerRef` / `secretSlug` are client-supplied on CREATE and `.excludeFromUpdate()` afterwards,\n * so on UPDATE they must come from the pre-fetched current row.\n */\nfunction resolveWriteIdentity(\n input: Record<string, unknown> | undefined,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n): CredentialWriteIdentity {\n const current = utils.currentObject as OrganizationProviderCredential | undefined;\n\n // Two sources, and the request BODY is deliberately not one of them.\n //\n // On UPDATE the stored row is authoritative — it is what the framework already persisted. On\n // CREATE the execution context's context-resource map is, because that is the same channel\n // `enrichDataWithContext` reads when it injects the scope FK, so the seal binds to the tenant the\n // row will actually be stored under.\n //\n // A `payload.organizationId` fallback was here and was REMOVED: it fails safe (a seal bound to a\n // body-supplied tenant is simply unopenable later, so the outcome is a denial rather than a\n // disclosure) but it is still the request choosing what the seal binds to, which is exactly the\n // authorship this hook exists to keep out of a caller's hands. With no fallback, a context that\n // cannot name the tenant is a REFUSAL — see below.\n const organizationId =\n (typeof current?.organizationId === 'string' && current.organizationId)\n || executionContext.getContextResourceId?.(coreResourceShared_FieldIdentifier[CoreResourceType.ORGANIZATIONS] as never);\n\n const providerRef =\n (typeof input?.providerRef === 'string' && input.providerRef)\n || (typeof current?.providerRef === 'string' ? current.providerRef : undefined);\n\n const secretSlug =\n (typeof input?.secretSlug === 'string' && input.secretSlug)\n || (typeof current?.secretSlug === 'string' ? current.secretSlug : undefined);\n\n if (typeof organizationId !== 'string' || !organizationId || !providerRef || !secretSlug) {\n // Fail CLOSED. Sealing under a partial identity would produce a credential bound to the wrong\n // row — unopenable at resolution time, and indistinguishable then from a tampered one.\n throw utils.errorBuilder.buildError(ErrorType.CONFIGURATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.CONFIGURATION,\n context: {\n message:\n 'Cannot seal an organization provider credential: the row identity is incomplete. All three of '\n + 'organizationId, providerRef and secretSlug must be resolvable, because the seal is bound to them. '\n + 'The organization is read from the execution scope or the stored row, never from the request body.',\n hasOrganizationId: Boolean(organizationId),\n hasProviderRef: Boolean(providerRef),\n hasSecretSlug: Boolean(secretSlug),\n },\n });\n }\n\n return { organizationId, providerRef, secretSlug };\n}\n\n/**\n * Seal `secretValue` if the write carries one.\n *\n * An ABSENT `secretValue` is normal on UPDATE and must pass through untouched: the framework strips\n * the field when a client echoes back the redaction mask, which is how \"edit the description without\n * retyping the secret\" works. Re-sealing nothing would be harmless; treating absence as an error\n * would break the ordinary edit.\n */\nfunction sealIncomingSecret(\n input: Record<string, unknown> | undefined,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n container: Container,\n): Record<string, unknown> | undefined {\n const payload = input ?? undefined;\n const incoming = payload?.secretValue;\n\n // ABSENT means \"no change\", and only absent. `null` is deliberately NOT treated as absent and\n // falls through to the refusal below.\n //\n // That distinction became load-bearing the moment `secretValue` was declared authoritative: an\n // authoritative field's post-prefix value is always carried past the repository's strict re-parse,\n // so passing a `null` through here would push it INTO persistence rather than letting the schema\n // reject it. The row would then hold a null where `z.string().min(1)` is required, and every\n // later read would throw in `transformOutput` — a write that answers success and leaves the row\n // permanently unreadable.\n if (incoming === undefined) {\n return payload;\n }\n\n // Defence in depth. The framework strips the mask sentinel before this hook runs, so reaching here\n // with the mask means that strip did not happen — and sealing the mask would store the literal\n // bullet characters as the tenant's credential, then hand them to a vendor.\n if (incoming === WRITE_ONLY_SECRET_MASK) {\n const { secretValue: _discarded, ...rest } = payload as Record<string, unknown>;\n return rest;\n }\n\n if (typeof incoming !== 'string' || incoming.length === 0) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: 'An organization provider credential value must be a non-empty string.' },\n });\n }\n\n const identity = resolveWriteIdentity(payload, executionContext, utils);\n const appConfig = container.get<AppConfigurationService>(SAAS_SERVICE_TYPES.AppConfigService);\n\n const actingUserId = executionContext?.initiatorIds?.userId;\n\n return {\n ...payload,\n secretValue: sealProviderCredential(\n incoming,\n appConfig.secrets.security.session.encryptionKey,\n {\n ownerScope: ExternalProvider_Connection_OwnerScope.ORGANIZATION,\n ownerId: identity.organizationId,\n providerRef: identity.providerRef,\n secretSlug: identity.secretSlug,\n },\n ),\n // Server-owned provenance. Both are `.excludeFromCreate().excludeFromUpdate()`, so returning them\n // here is what carries them past the strict re-parse — the same mechanism api-key minting uses\n // for its hashed material, and declared explicitly in `authoritativeFields` below.\n secretSetAt: new Date(),\n // Only when there IS an acting user. Writing the key with an `undefined` value would preserve an\n // explicit `undefined` past the re-parse rather than leaving the field absent, and \"absent\"\n // is the honest representation of a write with no human behind it.\n ...(actingUserId ? { setByUserId: actingUserId } : {}),\n };\n}\n\n/**\n * Emit the lifecycle event for a completed write.\n *\n * Best-effort in the same posture as every other audit emission in the engine: the credential has\n * already been written, and turning a logging failure into a 500 would tell the tenant their write\n * failed when it did not.\n */\nasync function emitCredentialWriteAudit(\n container: Container,\n /**\n * WHICH grant event this write is. Typed as the audit vocabulary's own two members rather than a\n * bespoke `'set' | 'rotated'` pair: the distinction already has a named runtime source, and a\n * second spelling of it would be a closed vocabulary with no home and one more thing to keep in\n * step with the event names.\n */\n eventType:\n | typeof CoreAuditableEventType.ORGANIZATION_PROVIDER_CREDENTIAL_SET\n | typeof CoreAuditableEventType.ORGANIZATION_PROVIDER_CREDENTIAL_ROTATED,\n row: OrganizationProviderCredential | undefined,\n previousSecretSetAt: Date | undefined,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n): Promise<void> {\n if (!row || typeof row._id !== 'string' || typeof row.organizationId !== 'string') {\n utils.logger.error?.(\n 'An organization provider credential was written but the row could not be identified — audit event not emitted',\n { eventType },\n );\n return;\n }\n\n try {\n const auditLogs = container.get<AuditLogsBackendService>(SAAS_SERVICE_TYPES.AuditLogsService);\n const common = {\n organizationId: row.organizationId,\n providerRef: row.providerRef,\n secretSlug: row.secretSlug,\n credentialId: row._id,\n };\n if (eventType === CoreAuditableEventType.ORGANIZATION_PROVIDER_CREDENTIAL_SET) {\n await auditLogs.logOrganizationProviderCredentialSet(\n { ...common, setBy: resolveAuditActorId(executionContext) },\n executionContext,\n );\n } else {\n await auditLogs.logOrganizationProviderCredentialRotated(\n {\n ...common,\n rotatedBy: resolveAuditActorId(executionContext),\n previousSecretSetAt: previousSecretSetAt?.toISOString(),\n },\n executionContext,\n );\n }\n } catch (error) {\n utils.logger.error?.('Failed to emit the organization provider credential audit event', {\n eventType,\n credentialId: row._id,\n ...projectCaughtErrorLogFields(error),\n });\n }\n}\n\n/**\n * CREATE — the tenant grants this application authority toward a third party for the first time.\n */\nfunction createCredentialCreateFactory(): ResourceCustomServiceImplementationFactory {\n const factory = (_registry: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n operationIdentifier: CoreResourceOperation.CREATE,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: 'organizationProviderCredentials.create.seal-and-audit',\n /**\n * The three fields this hook OWNS, declared rather than inferred.\n *\n * `preserveServerInjectedFields` is normally derived by diffing the prefix output against a\n * snapshot of the payload keys taken BEFORE the prefix ran, so only keys the hook INTRODUCED\n * survive the repository's strict re-parse. That inference has a documented hole: a caller\n * reaching the service tier with the key already present — MCP `callTool` forwards its\n * arguments with no strict parse — puts it into the snapshot, the hook's value is then not\n * classified as introduced, and the repository strips it while the operation answers success.\n *\n * For `secretSetAt` / `setByUserId` that would silently lose the provenance of a credential,\n * which is the first thing an incident asks for. For `secretValue` the declaration says the\n * thing that matters most in this file: whatever a caller sent, what reaches persistence is\n * the POST-prefix value — the sealed envelope — and never the plaintext they supplied.\n */\n authoritativeFields: ['secretValue', 'secretSetAt', 'setByUserId'],\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) =>\n sealIncomingSecret(input as Record<string, unknown> | undefined, executionContext, utils, container),\n postfixCoreOperations: async (_id, created, executionContext, _operationPath, utils) => {\n await emitCredentialWriteAudit(\n container,\n CoreAuditableEventType.ORGANIZATION_PROVIDER_CREDENTIAL_SET,\n created as OrganizationProviderCredential | undefined,\n undefined,\n executionContext,\n utils,\n );\n return created;\n },\n },\n });\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n/**\n * UPDATE — a rotation, or an ordinary metadata edit.\n *\n * The two are distinguished by whether the write actually carried a NEW secret. An edit that only\n * changes the description emits nothing: a rotation event on a description change would make the\n * one signal a compromise investigation depends on unusable.\n */\nfunction createCredentialUpdateFactory(): ResourceCustomServiceImplementationFactory {\n const factory = (_registry: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n operationIdentifier: CoreResourceOperation.UPDATE,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: 'organizationProviderCredentials.update.seal-and-audit',\n /**\n * The three fields this hook OWNS, declared rather than inferred.\n *\n * `preserveServerInjectedFields` is normally derived by diffing the prefix output against a\n * snapshot of the payload keys taken BEFORE the prefix ran, so only keys the hook INTRODUCED\n * survive the repository's strict re-parse. That inference has a documented hole: a caller\n * reaching the service tier with the key already present — MCP `callTool` forwards its\n * arguments with no strict parse — puts it into the snapshot, the hook's value is then not\n * classified as introduced, and the repository strips it while the operation answers success.\n *\n * For `secretSetAt` / `setByUserId` that would silently lose the provenance of a credential,\n * which is the first thing an incident asks for. For `secretValue` the declaration says the\n * thing that matters most in this file: whatever a caller sent, what reaches persistence is\n * the POST-prefix value — the sealed envelope — and never the plaintext they supplied.\n */\n authoritativeFields: ['secretValue', 'secretSetAt', 'setByUserId'],\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const sealed = sealIncomingSecret(\n input as Record<string, unknown> | undefined,\n executionContext,\n utils,\n container,\n );\n // Bridge to the postfix, keyed by this operation's execution context. Carries only WHETHER\n // the value moved and WHEN the previous one was set — never a secret, in either direction.\n ROTATION_BRIDGE_BY_EC.set(executionContext, {\n rotated: sealed?.secretValue !== undefined,\n previousSecretSetAt: (utils.currentObject as OrganizationProviderCredential | undefined)?.secretSetAt,\n });\n return sealed;\n },\n postfixCoreOperations: async (_id, updated, executionContext, _operationPath, utils) => {\n const bridge = ROTATION_BRIDGE_BY_EC.get(executionContext);\n ROTATION_BRIDGE_BY_EC.delete(executionContext);\n if (bridge?.rotated) {\n await emitCredentialWriteAudit(\n container,\n CoreAuditableEventType.ORGANIZATION_PROVIDER_CREDENTIAL_ROTATED,\n updated as OrganizationProviderCredential | undefined,\n bridge.previousSecretSetAt,\n executionContext,\n utils,\n );\n }\n return updated;\n },\n },\n });\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n/**\n * DELETE — a tenant administrator revoking the grant.\n *\n * `ADMINISTRATOR_REVOKED` unconditionally, and that is CORRECT rather than an assumption: the\n * cascade door never reaches this hook (see the module header), so every delete that arrives here is\n * a deliberate service-tier revocation. If a future change routed a cascade through the service\n * tier, this constant would become a lie — which is why the door table above is pinned by a test\n * rather than left as prose.\n */\nfunction createCredentialDeleteFactory(): ResourceCustomServiceImplementationFactory {\n const factory = (_registry: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: CoreResourceType.ORG_PROVIDER_CREDENTIALS,\n operationIdentifier: CoreResourceOperation.DELETE,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: 'organizationProviderCredentials.delete.audit',\n handlers: {\n postfixCoreOperations: async (id, result, executionContext, _operationPath, utils) => {\n // The pre-deletion snapshot: after the row is gone, the provider and slug are unrecoverable,\n // so an event naming only the id would identify nothing.\n const snapshot = utils.currentObject as OrganizationProviderCredential | undefined;\n const credentialId = snapshot?._id ?? (typeof id === 'string' ? id : undefined);\n\n if (!snapshot?.organizationId || !credentialId) {\n utils.logger.error?.(\n 'An organization provider credential was deleted but the subject could not be resolved — audit event not emitted',\n { addressedIdType: Array.isArray(id) ? 'array' : typeof id },\n );\n return result;\n }\n\n try {\n const auditLogs = container.get<AuditLogsBackendService>(SAAS_SERVICE_TYPES.AuditLogsService);\n await auditLogs.logOrganizationProviderCredentialDeleted(\n {\n organizationId: snapshot.organizationId,\n providerRef: snapshot.providerRef,\n secretSlug: snapshot.secretSlug,\n credentialId,\n reason: ProviderCredentialDeletionReason.ADMINISTRATOR_REVOKED,\n deletedBy: resolveAuditActorId(executionContext),\n },\n executionContext,\n );\n } catch (error) {\n utils.logger.error?.('Failed to emit the organization provider credential deletion audit event', {\n credentialId,\n ...projectCaughtErrorLogFields(error),\n });\n }\n return result;\n },\n },\n });\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n/**\n * Prefix→postfix bridge for the UPDATE hook, keyed by the per-operation execution-context instance.\n *\n * A `WeakMap` so an abandoned operation cannot retain the entry, mirroring the api-key mint bridge.\n * It deliberately carries no secret: only a boolean and a timestamp cross it.\n */\nconst ROTATION_BRIDGE_BY_EC = new WeakMap<object, { rotated: boolean; previousSecretSetAt?: Date }>();\n\n/** Every write door of the organization-provider-credential resource. */\nexport function createOrganizationProviderCredentialFactories(): ResourceCustomServiceImplementationFactory[] {\n return [\n createCredentialCreateFactory(),\n createCredentialUpdateFactory(),\n createCredentialDeleteFactory(),\n ];\n}\n"]}
|
package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-oauth2-exchange.backend.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"provider-oauth2-exchange.backend.d.ts","sourceRoot":"","sources":["../../../../../src/security/connected-accounts/services/provider-oauth2-exchange.backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAgC,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAK/F,sGAAsG;AACtG,qBAAa,2BAA4B,SAAQ,KAAK;IACpD;;;;;;;;;;;OAWG;IACH,SAAgB,eAAe,CAAC,EAAE,MAAM,CAAC;gBAE7B,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM;CAKtD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yCAAyC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEjF;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,wBAAwB,IAAI,kBAAkB,CAU7D;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAK9E;AAED,kEAAkE;AAClE,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACtD,WAAW,EAAE,MAAM,GAClB,MAAM,CAaR;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kGAAkG;IAClG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,qFAAqF;IACrF,QAAQ,CAAC,oBAAoB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAgCrF;AAaD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,oBAAoB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,kBAAkB,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACjH,OAAO,CAAC,mBAAmB,CAAC,CAO9B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,kBAAkB,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE,GAClE,OAAO,CAAC,mBAAmB,CAAC,CAoB9B"}
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { createHash, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
24
24
|
import { ProviderStoredCredentialKind } from '@wildo-ai/saas-models';
|
|
25
|
+
import { readResponseTextWithinDeadline } from '../../../security/outbound/outbound-request-deadline.backend.utils.js';
|
|
26
|
+
import { FEDERATED_AUTH_PROVIDER_REQUEST_TIMEOUT_MS } from '../../../security/authentications/models/federated-auth-transport.backend.definitions.js';
|
|
25
27
|
/** Raised when an exchange cannot be built or completed. Never carries a token or a client secret. */
|
|
26
28
|
export class ProviderOAuth2ExchangeError extends Error {
|
|
27
29
|
/**
|
|
@@ -203,7 +205,20 @@ async function postToTokenEndpoint(input, parameters) {
|
|
|
203
205
|
client_secret: input.clientSecret,
|
|
204
206
|
});
|
|
205
207
|
const doFetch = input.fetchImpl ?? fetch;
|
|
208
|
+
/*
|
|
209
|
+
* THE DEADLINE. This exchange had no bound until 2026-09-09.
|
|
210
|
+
*
|
|
211
|
+
* A person is parked on the connect callback while it runs, so a vendor that accepts a connection
|
|
212
|
+
* and never answers does not slow this down — it strands the connect flow for as long as the
|
|
213
|
+
* socket lives, and Node's `fetch` supplies no deadline of its own.
|
|
214
|
+
*
|
|
215
|
+
* The body read is raced against the same signal rather than left to the transport, because
|
|
216
|
+
* `fetchImpl` is a SEAM: honouring an abort on an in-flight body read is a property of the
|
|
217
|
+
* implementation, and this module is written so the implementation can be replaced.
|
|
218
|
+
*/
|
|
219
|
+
const deadline = AbortSignal.timeout(FEDERATED_AUTH_PROVIDER_REQUEST_TIMEOUT_MS);
|
|
206
220
|
let response;
|
|
221
|
+
let text;
|
|
207
222
|
try {
|
|
208
223
|
response = await doFetch(tokenUrl, {
|
|
209
224
|
method: 'POST',
|
|
@@ -214,13 +229,14 @@ async function postToTokenEndpoint(input, parameters) {
|
|
|
214
229
|
accept: 'application/json',
|
|
215
230
|
},
|
|
216
231
|
body: body.toString(),
|
|
232
|
+
signal: deadline,
|
|
217
233
|
});
|
|
234
|
+
text = await readResponseTextWithinDeadline(response, deadline);
|
|
218
235
|
}
|
|
219
236
|
catch (error) {
|
|
220
237
|
throw new ProviderOAuth2ExchangeError(`Could not reach the token endpoint for provider '${input.providerRef}' at ${tokenUrl}: `
|
|
221
238
|
+ `${error instanceof Error ? error.message : 'unknown transport failure'}.`);
|
|
222
239
|
}
|
|
223
|
-
const text = await response.text();
|
|
224
240
|
let payload;
|
|
225
241
|
try {
|
|
226
242
|
payload = JSON.parse(text);
|
package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-oauth2-exchange.backend.js","sourceRoot":"","sources":["../../../../../../src/security/connected-accounts/services/provider-oauth2-exchange.backend.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The OAuth2 authorization-code exchange, as three pure-ish functions.\n *\n * This is the half of the connect flow that has no HTTP route, no session and no database: build the\n * URL a person is sent to, turn the code they come back with into a grant, and renew a grant that is\n * about to expire. The route, the state record and the store are a thin shell around it.\n *\n * Written as functions over an explicit contract rather than as a service with injected collaborators\n * for one reason: every interesting failure here is a WRONG STRING — a placeholder that was never\n * resolved, a scope set that silently shrank, a redirect URI that does not match the one registered.\n * Those are answerable by a unit test only if the inputs are arguments, and they are the failures\n * that reach a person as \"the vendor says no\" with nothing local to look at.\n *\n * ## What this deliberately does NOT do\n *\n * It does not store anything, does not read a credential, and does not decide WHO may connect. The\n * connection target (whose account is being connected) and its admissibility are decided before this\n * is reached, by the same two gates every other credential path goes through.\n *\n * assurance-control: WILDO.IDENTITY.DELEGATED_AUTHORIZATION — the authorization exchange by which a\n * principal grants this application access to a third party on their behalf.\n */\n\nimport { createHash, randomBytes, timingSafeEqual } from 'node:crypto';\n\nimport type { ProviderRestOAuth2 } from '@wildo-ai/external-connectors-models';\nimport { ProviderStoredCredentialKind, type ProviderOAuth2Grant } from '@wildo-ai/saas-models';\n\n/** Raised when an exchange cannot be built or completed. Never carries a token or a client secret. */\nexport class ProviderOAuth2ExchangeError extends Error {\n /**\n * The vendor's own OAuth2 error code, when the failure was one the vendor NAMED.\n *\n * Carried structurally rather than only inside the message, because one caller has to act on it\n * differently from every other failure: a grant the vendor has permanently rejected must stop\n * presenting itself as a working connection, while a token endpoint that was merely unreachable\n * must not. Both arrive here as the same class, and a message substring is not something to branch\n * a person's account state on.\n *\n * Absent for transport failures, unparseable bodies and bare HTTP statuses — cases where the\n * vendor said nothing about the grant, and where assuming anything about it would be a guess.\n */\n public readonly oauth2ErrorCode?: string;\n\n constructor(message: string, oauth2ErrorCode?: string) {\n super(message);\n this.name = 'ProviderOAuth2ExchangeError';\n this.oauth2ErrorCode = oauth2ErrorCode;\n }\n}\n\n/**\n * Is this failure the vendor saying the grant itself is finished?\n *\n * TRUE for exactly one code. `invalid_grant` is defined as an authorization grant or refresh token\n * that is invalid, expired, revoked, or was issued to another client — every one of which is\n * permanent for THIS connection and none of which a retry improves.\n * spec-cite: RFC 6749 §5.2 (invalid_grant).\n *\n * Deliberately NOT `invalid_client`, and that exclusion is the substantive half. `invalid_client`\n * means the APPLICATION's own registration was rejected — a wrong client secret, a deleted vendor\n * app — which is an operator's problem affecting every connection at once. Treating it as a dead\n * grant would mark every person's account invalid and invite them all to reconnect, which cannot\n * work and would blame them for a misconfiguration they cannot see.\n *\n * Also FALSE for every failure the vendor did not name: a transport error, a non-JSON body, a bare\n * 500. A vendor that was unreachable has said nothing about the grant, and a connection must not be\n * retired on our inability to ask.\n */\nexport function providerOAuth2GrantWasPermanentlyRejected(error: unknown): boolean {\n return error instanceof ProviderOAuth2ExchangeError && error.oauth2ErrorCode === 'invalid_grant';\n}\n\n/**\n * The PKCE pair for one authorization attempt.\n *\n * PKCE is applied to EVERY exchange, including confidential-client ones that hold a secret, and that\n * is a deliberate default rather than a requirement of the grant type. It costs one hash and it\n * closes authorization-code interception, which is reachable here because the code arrives on a\n * redirect through the person's own browser — a channel this application does not control.\n * spec-cite: RFC 7636 §4.1–4.2 (code_verifier, code_challenge, S256).\n */\nexport interface ProviderOAuth2Pkce {\n readonly verifier: string;\n readonly challenge: string;\n readonly method: 'S256';\n}\n\nexport function createProviderOAuth2Pkce(): ProviderOAuth2Pkce {\n // 32 bytes base64url is 43 characters — the minimum the specification allows for a verifier, and\n // the length every major vendor's documentation uses.\n // spec-cite: RFC 7636 §4.1 (code_verifier: 43–128 characters).\n const verifier = randomBytes(32).toString('base64url');\n return {\n verifier,\n challenge: createHash('sha256').update(verifier).digest('base64url'),\n method: 'S256',\n };\n}\n\n/**\n * Compare two opaque values in constant time.\n *\n * Used for the `state` echo. A plain `===` leaks the position of the first differing byte through\n * timing, and `state` is the CSRF defence for the whole flow: an attacker who can guess it can graft\n * their own authorization code onto somebody else's connect attempt.\n */\nexport function providerOAuth2ValuesMatch(left: string, right: string): boolean {\n const a = Buffer.from(left, 'utf8');\n const b = Buffer.from(right, 'utf8');\n if (a.length !== b.length) return false;\n return timingSafeEqual(a, b);\n}\n\n/** A fresh, unguessable `state` for one authorization attempt. */\nexport function createProviderOAuth2State(): string {\n return randomBytes(32).toString('base64url');\n}\n\n/**\n * Resolve the `{placeholder}` holes an endpoint carries from the connection's own parameters.\n *\n * REFUSES on a missing value rather than leaving the brace in place. A URL still carrying\n * `{tenantId}` is not a URL: it would be sent to the person's browser, fail to resolve as a\n * hostname, and present as \"the vendor is down\" — a very long way from \"nobody asked which\n * directory\". 21 of the 96 vendors that recovered both endpoints are in this population.\n */\nexport function resolveEndpointPlaceholders(\n url: string,\n connectionParameters: Readonly<Record<string, string>>,\n providerRef: string,\n): string {\n return url.replace(/\\{([A-Za-z_][A-Za-z0-9_]*)\\}/g, (_match, name: string) => {\n const value = connectionParameters[name];\n if (value === undefined || value === '') {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${providerRef}' needs a value for '${name}' before its OAuth2 endpoints are usable — `\n + `'${url}' still carries the placeholder. This is a fact about the ACCOUNT being connected `\n + '(which cloud, which directory, which region), so it is asked for at connect time and is not '\n + 'application configuration.',\n );\n }\n return encodeURIComponent(value);\n });\n}\n\nexport interface BuildAuthorizeUrlInput {\n readonly oauth2: ProviderRestOAuth2;\n readonly providerRef: string;\n readonly clientId: string;\n /** Where the vendor sends the person back. Must be byte-identical to what is registered there. */\n readonly redirectUri: string;\n readonly state: string;\n readonly pkce: ProviderOAuth2Pkce;\n /** Values for the endpoints' `{placeholders}`, supplied by whoever is connecting. */\n readonly connectionParameters?: Readonly<Record<string, string>>;\n /**\n * Scopes to request. Falls back to the vendor's own catalogue-declared set.\n *\n * Overridable because the catalogue's set is what the SOURCE asked for across every action it\n * described, which is routinely broader than one application needs — and an over-broad consent\n * screen is a thing a person refuses.\n */\n readonly scopes?: readonly string[];\n}\n\n/**\n * The URL a person is sent to in order to grant access.\n *\n * Query parameters are MERGED into whatever the vendor's own authorize URL already carries rather\n * than appended blindly. That is not tidiness: Slack's catalogue-declared authorize URL arrives with\n * a `?user_scope=…` query string baked in, so appending `?client_id=…` would produce a URL with two\n * `?` and a vendor that rejects it. One vendor of 129 does this today, which is exactly the kind of\n * single-instance shape that a naive concatenation gets wrong forever.\n */\nexport function buildProviderOAuth2AuthorizeUrl(input: BuildAuthorizeUrlInput): string {\n const resolved = resolveEndpointPlaceholders(\n input.oauth2.authorizeUrl,\n input.connectionParameters ?? {},\n input.providerRef,\n );\n\n let url: URL;\n try {\n url = new URL(resolved);\n } catch {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${input.providerRef}' declares an authorize URL that is not a URL: '${resolved}'. `\n + 'Correct it in the provider\\'s authored supplement rather than at the call site.',\n );\n }\n\n const scopes = input.scopes ?? input.oauth2.scopes ?? [];\n url.searchParams.set('response_type', 'code');\n url.searchParams.set('client_id', input.clientId);\n url.searchParams.set('redirect_uri', input.redirectUri);\n url.searchParams.set('state', input.state);\n url.searchParams.set('code_challenge', input.pkce.challenge);\n url.searchParams.set('code_challenge_method', input.pkce.method);\n if (scopes.length > 0) {\n // Space-delimited, which is the specification's encoding; `URLSearchParams` percent-encodes the\n // spaces. Vendors that want commas are a per-vendor deviation and belong in an authored\n // supplement, not in a guess here.\n // spec-cite: RFC 6749 §3.3 (scope is expressed as a list of space-delimited strings).\n url.searchParams.set('scope', scopes.join(' '));\n }\n return url.toString();\n}\n\n/** What a token endpoint gives back, before it becomes a stored grant. */\ninterface TokenEndpointResponse {\n readonly access_token?: unknown;\n readonly refresh_token?: unknown;\n readonly expires_in?: unknown;\n readonly scope?: unknown;\n readonly token_type?: unknown;\n readonly error?: unknown;\n readonly error_description?: unknown;\n}\n\nexport interface TokenExchangeInput {\n readonly oauth2: ProviderRestOAuth2;\n readonly providerRef: string;\n readonly clientId: string;\n readonly clientSecret: string;\n readonly connectionParameters?: Readonly<Record<string, string>>;\n readonly fetchImpl?: typeof fetch;\n}\n\n/**\n * Turn the authorization code into a grant.\n *\n * The client credentials go in the BODY (`client_secret_post`) rather than a Basic header. Both are\n * specified and a server must support Basic, but the body form is what every major vendor's own\n * documentation shows and what their sandboxes accept; a vendor that requires Basic is a per-vendor\n * deviation for an authored supplement.\n * spec-cite: RFC 6749 §2.3.1 (client_secret_basic is required of servers; the body form is permitted).\n */\nexport async function exchangeProviderOAuth2Code(\n input: TokenExchangeInput & { readonly code: string; readonly redirectUri: string; readonly pkceVerifier: string },\n): Promise<ProviderOAuth2Grant> {\n return postToTokenEndpoint(input, {\n grant_type: 'authorization_code',\n code: input.code,\n redirect_uri: input.redirectUri,\n code_verifier: input.pkceVerifier,\n });\n}\n\n/**\n * Renew a grant that is expiring.\n *\n * Carries the PREVIOUS grant's refresh token forward when the vendor does not return a new one.\n * That is the difference between a connection that survives and one that dies on its second\n * refresh: some vendors rotate the refresh token on every use and return the replacement, and\n * others return only an access token and expect the original refresh token to be reused. Dropping\n * it in the second case leaves a grant that cannot be refreshed again, and the failure arrives an\n * hour later with nothing pointing at this function.\n * spec-cite: RFC 6749 §6 (the authorization server MAY issue a new refresh token).\n */\nexport async function refreshProviderOAuth2Grant(\n input: TokenExchangeInput & { readonly grant: ProviderOAuth2Grant },\n): Promise<ProviderOAuth2Grant> {\n if (input.grant.refreshToken === undefined) {\n throw new ProviderOAuth2ExchangeError(\n `The stored grant for provider '${input.providerRef}' has no refresh token, so it cannot be renewed. `\n + 'Reconnect the account. This is not a fault: several vendors issue non-expiring tokens with no '\n + 'refresh, and a grant that reaches here has both an expiry and no way to renew it.',\n );\n }\n const renewed = await postToTokenEndpoint(input, {\n grant_type: 'refresh_token',\n refresh_token: input.grant.refreshToken,\n });\n return {\n ...renewed,\n refreshToken: renewed.refreshToken ?? input.grant.refreshToken,\n // The vendor need not restate the account or the scopes on a refresh; losing them would make a\n // renewed connection describe itself less well than a fresh one.\n accountRef: renewed.accountRef ?? input.grant.accountRef,\n grantedScopes: renewed.grantedScopes ?? input.grant.grantedScopes,\n };\n}\n\nasync function postToTokenEndpoint(\n input: TokenExchangeInput,\n parameters: Readonly<Record<string, string>>,\n): Promise<ProviderOAuth2Grant> {\n const tokenUrl = resolveEndpointPlaceholders(\n input.oauth2.tokenUrl,\n input.connectionParameters ?? {},\n input.providerRef,\n );\n\n const body = new URLSearchParams({\n ...parameters,\n client_id: input.clientId,\n client_secret: input.clientSecret,\n });\n\n const doFetch = input.fetchImpl ?? fetch;\n let response: Response;\n try {\n response = await doFetch(tokenUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/x-www-form-urlencoded',\n // Several vendors default to form-encoded responses without it, and one that does is\n // indistinguishable from a malformed body at the parse below.\n accept: 'application/json',\n },\n body: body.toString(),\n });\n } catch (error) {\n throw new ProviderOAuth2ExchangeError(\n `Could not reach the token endpoint for provider '${input.providerRef}' at ${tokenUrl}: `\n + `${error instanceof Error ? error.message : 'unknown transport failure'}.`,\n );\n }\n\n const text = await response.text();\n let payload: TokenEndpointResponse;\n try {\n payload = JSON.parse(text) as TokenEndpointResponse;\n } catch {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${input.providerRef}' answered its token endpoint with a non-JSON body (HTTP ${response.status}). `\n + 'The body is not reproduced here because a token endpoint\\'s response carries credentials.',\n );\n }\n\n // An OAuth2 error can arrive with HTTP 200 — several vendors do this, Slack among them — so the\n // status is not the authority on whether the exchange succeeded. Checking only `response.ok`\n // would treat `{\"ok\":false,\"error\":\"invalid_code\"}` as a grant and store a row with no token.\n if (typeof payload.error === 'string') {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${input.providerRef}' refused the token exchange: ${payload.error}`\n + `${typeof payload.error_description === 'string' ? ` — ${payload.error_description}` : ''}.`,\n // The one failure the vendor NAMED. Carried structurally so a caller can tell a dead grant\n // from an unreachable endpoint without matching on prose.\n payload.error,\n );\n }\n if (!response.ok) {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${input.providerRef}' answered HTTP ${response.status} to the token exchange with no error code.`,\n );\n }\n if (typeof payload.access_token !== 'string' || payload.access_token.length === 0) {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${input.providerRef}' answered the token exchange without an access token. `\n + 'Storing the response would create a connection that cannot authenticate anything.',\n );\n }\n\n return {\n kind: ProviderStoredCredentialKind.OAUTH2_GRANT,\n accessToken: payload.access_token,\n refreshToken: typeof payload.refresh_token === 'string' && payload.refresh_token.length > 0\n ? payload.refresh_token\n : undefined,\n expiresAt: typeof payload.expires_in === 'number' && Number.isFinite(payload.expires_in)\n ? new Date(Date.now() + payload.expires_in * 1000).toISOString()\n : undefined,\n // What the vendor actually GRANTED, which is not always what was asked for. Space-delimited per\n // the specification; a vendor returning a comma-separated string is a per-vendor deviation.\n // spec-cite: RFC 6749 §5.1 (scope, present if different from the one requested).\n grantedScopes: typeof payload.scope === 'string' && payload.scope.length > 0\n ? payload.scope.split(/\\s+/).filter((scope) => scope.length > 0)\n : undefined,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"provider-oauth2-exchange.backend.js","sourceRoot":"","sources":["../../../../../src/security/connected-accounts/services/provider-oauth2-exchange.backend.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The OAuth2 authorization-code exchange, as three pure-ish functions.\n *\n * This is the half of the connect flow that has no HTTP route, no session and no database: build the\n * URL a person is sent to, turn the code they come back with into a grant, and renew a grant that is\n * about to expire. The route, the state record and the store are a thin shell around it.\n *\n * Written as functions over an explicit contract rather than as a service with injected collaborators\n * for one reason: every interesting failure here is a WRONG STRING — a placeholder that was never\n * resolved, a scope set that silently shrank, a redirect URI that does not match the one registered.\n * Those are answerable by a unit test only if the inputs are arguments, and they are the failures\n * that reach a person as \"the vendor says no\" with nothing local to look at.\n *\n * ## What this deliberately does NOT do\n *\n * It does not store anything, does not read a credential, and does not decide WHO may connect. The\n * connection target (whose account is being connected) and its admissibility are decided before this\n * is reached, by the same two gates every other credential path goes through.\n *\n * assurance-control: WILDO.IDENTITY.DELEGATED_AUTHORIZATION — the authorization exchange by which a\n * principal grants this application access to a third party on their behalf.\n */\n\nimport { createHash, randomBytes, timingSafeEqual } from 'node:crypto';\n\nimport type { ProviderRestOAuth2 } from '@wildo-ai/external-connectors-models';\nimport { ProviderStoredCredentialKind, type ProviderOAuth2Grant } from '@wildo-ai/saas-models';\n\nimport { readResponseTextWithinDeadline } from '~wildo-backend-lib/security/outbound/outbound-request-deadline.backend.utils';\nimport { FEDERATED_AUTH_PROVIDER_REQUEST_TIMEOUT_MS } from '~wildo-backend-lib/security/authentications/models/federated-auth-transport.backend.definitions';\n\n/** Raised when an exchange cannot be built or completed. Never carries a token or a client secret. */\nexport class ProviderOAuth2ExchangeError extends Error {\n /**\n * The vendor's own OAuth2 error code, when the failure was one the vendor NAMED.\n *\n * Carried structurally rather than only inside the message, because one caller has to act on it\n * differently from every other failure: a grant the vendor has permanently rejected must stop\n * presenting itself as a working connection, while a token endpoint that was merely unreachable\n * must not. Both arrive here as the same class, and a message substring is not something to branch\n * a person's account state on.\n *\n * Absent for transport failures, unparseable bodies and bare HTTP statuses — cases where the\n * vendor said nothing about the grant, and where assuming anything about it would be a guess.\n */\n public readonly oauth2ErrorCode?: string;\n\n constructor(message: string, oauth2ErrorCode?: string) {\n super(message);\n this.name = 'ProviderOAuth2ExchangeError';\n this.oauth2ErrorCode = oauth2ErrorCode;\n }\n}\n\n/**\n * Is this failure the vendor saying the grant itself is finished?\n *\n * TRUE for exactly one code. `invalid_grant` is defined as an authorization grant or refresh token\n * that is invalid, expired, revoked, or was issued to another client — every one of which is\n * permanent for THIS connection and none of which a retry improves.\n * spec-cite: RFC 6749 §5.2 (invalid_grant).\n *\n * Deliberately NOT `invalid_client`, and that exclusion is the substantive half. `invalid_client`\n * means the APPLICATION's own registration was rejected — a wrong client secret, a deleted vendor\n * app — which is an operator's problem affecting every connection at once. Treating it as a dead\n * grant would mark every person's account invalid and invite them all to reconnect, which cannot\n * work and would blame them for a misconfiguration they cannot see.\n *\n * Also FALSE for every failure the vendor did not name: a transport error, a non-JSON body, a bare\n * 500. A vendor that was unreachable has said nothing about the grant, and a connection must not be\n * retired on our inability to ask.\n */\nexport function providerOAuth2GrantWasPermanentlyRejected(error: unknown): boolean {\n return error instanceof ProviderOAuth2ExchangeError && error.oauth2ErrorCode === 'invalid_grant';\n}\n\n/**\n * The PKCE pair for one authorization attempt.\n *\n * PKCE is applied to EVERY exchange, including confidential-client ones that hold a secret, and that\n * is a deliberate default rather than a requirement of the grant type. It costs one hash and it\n * closes authorization-code interception, which is reachable here because the code arrives on a\n * redirect through the person's own browser — a channel this application does not control.\n * spec-cite: RFC 7636 §4.1–4.2 (code_verifier, code_challenge, S256).\n */\nexport interface ProviderOAuth2Pkce {\n readonly verifier: string;\n readonly challenge: string;\n readonly method: 'S256';\n}\n\nexport function createProviderOAuth2Pkce(): ProviderOAuth2Pkce {\n // 32 bytes base64url is 43 characters — the minimum the specification allows for a verifier, and\n // the length every major vendor's documentation uses.\n // spec-cite: RFC 7636 §4.1 (code_verifier: 43–128 characters).\n const verifier = randomBytes(32).toString('base64url');\n return {\n verifier,\n challenge: createHash('sha256').update(verifier).digest('base64url'),\n method: 'S256',\n };\n}\n\n/**\n * Compare two opaque values in constant time.\n *\n * Used for the `state` echo. A plain `===` leaks the position of the first differing byte through\n * timing, and `state` is the CSRF defence for the whole flow: an attacker who can guess it can graft\n * their own authorization code onto somebody else's connect attempt.\n */\nexport function providerOAuth2ValuesMatch(left: string, right: string): boolean {\n const a = Buffer.from(left, 'utf8');\n const b = Buffer.from(right, 'utf8');\n if (a.length !== b.length) return false;\n return timingSafeEqual(a, b);\n}\n\n/** A fresh, unguessable `state` for one authorization attempt. */\nexport function createProviderOAuth2State(): string {\n return randomBytes(32).toString('base64url');\n}\n\n/**\n * Resolve the `{placeholder}` holes an endpoint carries from the connection's own parameters.\n *\n * REFUSES on a missing value rather than leaving the brace in place. A URL still carrying\n * `{tenantId}` is not a URL: it would be sent to the person's browser, fail to resolve as a\n * hostname, and present as \"the vendor is down\" — a very long way from \"nobody asked which\n * directory\". 21 of the 96 vendors that recovered both endpoints are in this population.\n */\nexport function resolveEndpointPlaceholders(\n url: string,\n connectionParameters: Readonly<Record<string, string>>,\n providerRef: string,\n): string {\n return url.replace(/\\{([A-Za-z_][A-Za-z0-9_]*)\\}/g, (_match, name: string) => {\n const value = connectionParameters[name];\n if (value === undefined || value === '') {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${providerRef}' needs a value for '${name}' before its OAuth2 endpoints are usable — `\n + `'${url}' still carries the placeholder. This is a fact about the ACCOUNT being connected `\n + '(which cloud, which directory, which region), so it is asked for at connect time and is not '\n + 'application configuration.',\n );\n }\n return encodeURIComponent(value);\n });\n}\n\nexport interface BuildAuthorizeUrlInput {\n readonly oauth2: ProviderRestOAuth2;\n readonly providerRef: string;\n readonly clientId: string;\n /** Where the vendor sends the person back. Must be byte-identical to what is registered there. */\n readonly redirectUri: string;\n readonly state: string;\n readonly pkce: ProviderOAuth2Pkce;\n /** Values for the endpoints' `{placeholders}`, supplied by whoever is connecting. */\n readonly connectionParameters?: Readonly<Record<string, string>>;\n /**\n * Scopes to request. Falls back to the vendor's own catalogue-declared set.\n *\n * Overridable because the catalogue's set is what the SOURCE asked for across every action it\n * described, which is routinely broader than one application needs — and an over-broad consent\n * screen is a thing a person refuses.\n */\n readonly scopes?: readonly string[];\n}\n\n/**\n * The URL a person is sent to in order to grant access.\n *\n * Query parameters are MERGED into whatever the vendor's own authorize URL already carries rather\n * than appended blindly. That is not tidiness: Slack's catalogue-declared authorize URL arrives with\n * a `?user_scope=…` query string baked in, so appending `?client_id=…` would produce a URL with two\n * `?` and a vendor that rejects it. One vendor of 129 does this today, which is exactly the kind of\n * single-instance shape that a naive concatenation gets wrong forever.\n */\nexport function buildProviderOAuth2AuthorizeUrl(input: BuildAuthorizeUrlInput): string {\n const resolved = resolveEndpointPlaceholders(\n input.oauth2.authorizeUrl,\n input.connectionParameters ?? {},\n input.providerRef,\n );\n\n let url: URL;\n try {\n url = new URL(resolved);\n } catch {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${input.providerRef}' declares an authorize URL that is not a URL: '${resolved}'. `\n + 'Correct it in the provider\\'s authored supplement rather than at the call site.',\n );\n }\n\n const scopes = input.scopes ?? input.oauth2.scopes ?? [];\n url.searchParams.set('response_type', 'code');\n url.searchParams.set('client_id', input.clientId);\n url.searchParams.set('redirect_uri', input.redirectUri);\n url.searchParams.set('state', input.state);\n url.searchParams.set('code_challenge', input.pkce.challenge);\n url.searchParams.set('code_challenge_method', input.pkce.method);\n if (scopes.length > 0) {\n // Space-delimited, which is the specification's encoding; `URLSearchParams` percent-encodes the\n // spaces. Vendors that want commas are a per-vendor deviation and belong in an authored\n // supplement, not in a guess here.\n // spec-cite: RFC 6749 §3.3 (scope is expressed as a list of space-delimited strings).\n url.searchParams.set('scope', scopes.join(' '));\n }\n return url.toString();\n}\n\n/** What a token endpoint gives back, before it becomes a stored grant. */\ninterface TokenEndpointResponse {\n readonly access_token?: unknown;\n readonly refresh_token?: unknown;\n readonly expires_in?: unknown;\n readonly scope?: unknown;\n readonly token_type?: unknown;\n readonly error?: unknown;\n readonly error_description?: unknown;\n}\n\nexport interface TokenExchangeInput {\n readonly oauth2: ProviderRestOAuth2;\n readonly providerRef: string;\n readonly clientId: string;\n readonly clientSecret: string;\n readonly connectionParameters?: Readonly<Record<string, string>>;\n readonly fetchImpl?: typeof fetch;\n}\n\n/**\n * Turn the authorization code into a grant.\n *\n * The client credentials go in the BODY (`client_secret_post`) rather than a Basic header. Both are\n * specified and a server must support Basic, but the body form is what every major vendor's own\n * documentation shows and what their sandboxes accept; a vendor that requires Basic is a per-vendor\n * deviation for an authored supplement.\n * spec-cite: RFC 6749 §2.3.1 (client_secret_basic is required of servers; the body form is permitted).\n */\nexport async function exchangeProviderOAuth2Code(\n input: TokenExchangeInput & { readonly code: string; readonly redirectUri: string; readonly pkceVerifier: string },\n): Promise<ProviderOAuth2Grant> {\n return postToTokenEndpoint(input, {\n grant_type: 'authorization_code',\n code: input.code,\n redirect_uri: input.redirectUri,\n code_verifier: input.pkceVerifier,\n });\n}\n\n/**\n * Renew a grant that is expiring.\n *\n * Carries the PREVIOUS grant's refresh token forward when the vendor does not return a new one.\n * That is the difference between a connection that survives and one that dies on its second\n * refresh: some vendors rotate the refresh token on every use and return the replacement, and\n * others return only an access token and expect the original refresh token to be reused. Dropping\n * it in the second case leaves a grant that cannot be refreshed again, and the failure arrives an\n * hour later with nothing pointing at this function.\n * spec-cite: RFC 6749 §6 (the authorization server MAY issue a new refresh token).\n */\nexport async function refreshProviderOAuth2Grant(\n input: TokenExchangeInput & { readonly grant: ProviderOAuth2Grant },\n): Promise<ProviderOAuth2Grant> {\n if (input.grant.refreshToken === undefined) {\n throw new ProviderOAuth2ExchangeError(\n `The stored grant for provider '${input.providerRef}' has no refresh token, so it cannot be renewed. `\n + 'Reconnect the account. This is not a fault: several vendors issue non-expiring tokens with no '\n + 'refresh, and a grant that reaches here has both an expiry and no way to renew it.',\n );\n }\n const renewed = await postToTokenEndpoint(input, {\n grant_type: 'refresh_token',\n refresh_token: input.grant.refreshToken,\n });\n return {\n ...renewed,\n refreshToken: renewed.refreshToken ?? input.grant.refreshToken,\n // The vendor need not restate the account or the scopes on a refresh; losing them would make a\n // renewed connection describe itself less well than a fresh one.\n accountRef: renewed.accountRef ?? input.grant.accountRef,\n grantedScopes: renewed.grantedScopes ?? input.grant.grantedScopes,\n };\n}\n\nasync function postToTokenEndpoint(\n input: TokenExchangeInput,\n parameters: Readonly<Record<string, string>>,\n): Promise<ProviderOAuth2Grant> {\n const tokenUrl = resolveEndpointPlaceholders(\n input.oauth2.tokenUrl,\n input.connectionParameters ?? {},\n input.providerRef,\n );\n\n const body = new URLSearchParams({\n ...parameters,\n client_id: input.clientId,\n client_secret: input.clientSecret,\n });\n\n const doFetch = input.fetchImpl ?? fetch;\n\n /*\n * THE DEADLINE. This exchange had no bound until 2026-09-09.\n *\n * A person is parked on the connect callback while it runs, so a vendor that accepts a connection\n * and never answers does not slow this down — it strands the connect flow for as long as the\n * socket lives, and Node's `fetch` supplies no deadline of its own.\n *\n * The body read is raced against the same signal rather than left to the transport, because\n * `fetchImpl` is a SEAM: honouring an abort on an in-flight body read is a property of the\n * implementation, and this module is written so the implementation can be replaced.\n */\n const deadline = AbortSignal.timeout(FEDERATED_AUTH_PROVIDER_REQUEST_TIMEOUT_MS);\n let response: Response;\n let text: string;\n try {\n response = await doFetch(tokenUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/x-www-form-urlencoded',\n // Several vendors default to form-encoded responses without it, and one that does is\n // indistinguishable from a malformed body at the parse below.\n accept: 'application/json',\n },\n body: body.toString(),\n signal: deadline,\n });\n\n text = await readResponseTextWithinDeadline(response, deadline);\n } catch (error) {\n throw new ProviderOAuth2ExchangeError(\n `Could not reach the token endpoint for provider '${input.providerRef}' at ${tokenUrl}: `\n + `${error instanceof Error ? error.message : 'unknown transport failure'}.`,\n );\n }\n\n let payload: TokenEndpointResponse;\n try {\n payload = JSON.parse(text) as TokenEndpointResponse;\n } catch {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${input.providerRef}' answered its token endpoint with a non-JSON body (HTTP ${response.status}). `\n + 'The body is not reproduced here because a token endpoint\\'s response carries credentials.',\n );\n }\n\n // An OAuth2 error can arrive with HTTP 200 — several vendors do this, Slack among them — so the\n // status is not the authority on whether the exchange succeeded. Checking only `response.ok`\n // would treat `{\"ok\":false,\"error\":\"invalid_code\"}` as a grant and store a row with no token.\n if (typeof payload.error === 'string') {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${input.providerRef}' refused the token exchange: ${payload.error}`\n + `${typeof payload.error_description === 'string' ? ` — ${payload.error_description}` : ''}.`,\n // The one failure the vendor NAMED. Carried structurally so a caller can tell a dead grant\n // from an unreachable endpoint without matching on prose.\n payload.error,\n );\n }\n if (!response.ok) {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${input.providerRef}' answered HTTP ${response.status} to the token exchange with no error code.`,\n );\n }\n if (typeof payload.access_token !== 'string' || payload.access_token.length === 0) {\n throw new ProviderOAuth2ExchangeError(\n `Provider '${input.providerRef}' answered the token exchange without an access token. `\n + 'Storing the response would create a connection that cannot authenticate anything.',\n );\n }\n\n return {\n kind: ProviderStoredCredentialKind.OAUTH2_GRANT,\n accessToken: payload.access_token,\n refreshToken: typeof payload.refresh_token === 'string' && payload.refresh_token.length > 0\n ? payload.refresh_token\n : undefined,\n expiresAt: typeof payload.expires_in === 'number' && Number.isFinite(payload.expires_in)\n ? new Date(Date.now() + payload.expires_in * 1000).toISOString()\n : undefined,\n // What the vendor actually GRANTED, which is not always what was asked for. Space-delimited per\n // the specification; a vendor returning a comma-separated string is a per-vendor deviation.\n // spec-cite: RFC 6749 §5.1 (scope, present if different from the one requested).\n grantedScopes: typeof payload.scope === 'string' && payload.scope.length > 0\n ? payload.scope.split(/\\s+/).filter((scope) => scope.length > 0)\n : undefined,\n };\n}\n"]}
|
|
@@ -99,6 +99,20 @@ export declare class ProviderOAuth2PendingAuthorizationBackendService {
|
|
|
99
99
|
* attacker that a `state` was valid but expired confirms they hold a real one.
|
|
100
100
|
*/
|
|
101
101
|
consume(state: string): Promise<ProviderOAuth2PendingAuthorization | null>;
|
|
102
|
+
/**
|
|
103
|
+
* Read the attempt WITHOUT taking it — for the callback, which must not consume.
|
|
104
|
+
*
|
|
105
|
+
* The callback authenticates nobody and finishes nothing; all it needs is the frontend to send the
|
|
106
|
+
* person back to, which is recorded here. Consuming there would burn the attempt before the
|
|
107
|
+
* authenticated half could redeem it, and that is not hypothetical: while the callback both
|
|
108
|
+
* consumed and authenticated, a failed authentication left the person unable even to retry — the
|
|
109
|
+
* state was already gone.
|
|
110
|
+
*
|
|
111
|
+
* The single-use guarantee is UNCHANGED and still lives in {@link consume}, which the completion
|
|
112
|
+
* route calls. This one hands back a copy and defends nothing on its own, so treat what it returns
|
|
113
|
+
* as unverified: it says an attempt with that `state` exists, never that this caller may finish it.
|
|
114
|
+
*/
|
|
115
|
+
peek(state: string): Promise<ProviderOAuth2PendingAuthorization | null>;
|
|
102
116
|
/**
|
|
103
117
|
* Namespaced, so nothing else in the cache can be addressed by supplying a crafted `state`.
|
|
104
118
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-oauth2-pending-authorization.backend.service.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"provider-oauth2-pending-authorization.backend.service.d.ts","sourceRoot":"","sources":["../../../../../src/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,sCAAsC,CAAC;AAG9F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qDAAqD,CAAC;AACxF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAC;AAElG;;;;;;;GAOG;AACH,eAAO,MAAM,mCAAmC,MAAM,CAAC;AAIvD,MAAM,WAAW,kCAAkC;IACjD,yCAAyC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,iCAAiC,CAAC;IACnD,6FAA6F;IAC7F,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,8FAA8F;IAC9F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uFAAuF;IACvF,QAAQ,CAAC,oBAAoB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,kGAAkG;IAClG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,qBACa,gDAAgD;IAEhB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADA,KAAK,EAAE,YAAY,EACzB,MAAM,EAAE,aAAa;IAG3E;;;;;OAKG;IACU,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,kCAAkC,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhG;;;;;;OAMG;IACU,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kCAAkC,GAAG,IAAI,CAAC;IAIvF;;;;;;;;;;;;OAYG;IACU,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kCAAkC,GAAG,IAAI,CAAC;IAIpF;;;;;;OAMG;IACH,OAAO,CAAC,MAAM;CAGf"}
|
|
@@ -86,6 +86,22 @@ let ProviderOAuth2PendingAuthorizationBackendService = class ProviderOAuth2Pendi
|
|
|
86
86
|
async consume(state) {
|
|
87
87
|
return this.redis.getDel(this.keyFor(state));
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Read the attempt WITHOUT taking it — for the callback, which must not consume.
|
|
91
|
+
*
|
|
92
|
+
* The callback authenticates nobody and finishes nothing; all it needs is the frontend to send the
|
|
93
|
+
* person back to, which is recorded here. Consuming there would burn the attempt before the
|
|
94
|
+
* authenticated half could redeem it, and that is not hypothetical: while the callback both
|
|
95
|
+
* consumed and authenticated, a failed authentication left the person unable even to retry — the
|
|
96
|
+
* state was already gone.
|
|
97
|
+
*
|
|
98
|
+
* The single-use guarantee is UNCHANGED and still lives in {@link consume}, which the completion
|
|
99
|
+
* route calls. This one hands back a copy and defends nothing on its own, so treat what it returns
|
|
100
|
+
* as unverified: it says an attempt with that `state` exists, never that this caller may finish it.
|
|
101
|
+
*/
|
|
102
|
+
async peek(state) {
|
|
103
|
+
return this.redis.get(this.keyFor(state));
|
|
104
|
+
}
|
|
89
105
|
/**
|
|
90
106
|
* Namespaced, so nothing else in the cache can be addressed by supplying a crafted `state`.
|
|
91
107
|
*
|