@wildo-ai/saas-backend-lib 1.1.12 → 1.1.13
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/base-classes/models/manual-controllers.backend.definition.d.ts.map +1 -1
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.js +2 -0
- package/dist/esm/base-classes/models/manual-controllers.backend.definition.js.map +1 -1
- package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts +4 -0
- package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts.map +1 -1
- package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js +20 -5
- package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts +3 -0
- 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-registry.backend.service.js +10 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts +22 -0
- 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-custom-implementation.factory.backend.js +25 -1
- package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts +38 -3
- 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-operation-transaction-persistence.backend.utils.js +68 -5
- package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js.map +1 -1
- package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts +2 -2
- 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 +6 -3
- 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/services-registry-handler.backend.service.d.ts +83 -0
- 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 +217 -14
- package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts +32 -0
- package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js +36 -0
- package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts +38 -0
- package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js +83 -0
- package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts +36 -0
- package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js +51 -0
- package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts +46 -0
- package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js +68 -0
- package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts +27 -0
- package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js +42 -3
- package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts +26 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js +10 -0
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts +10 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js +60 -28
- package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js.map +1 -1
- package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts +90 -0
- package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts.map +1 -0
- package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js +373 -0
- package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js.map +1 -0
- package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts +29 -2
- package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts.map +1 -1
- package/dist/esm/compliance/approval-seals/decision-presentation.backend.js +40 -3
- package/dist/esm/compliance/approval-seals/decision-presentation.backend.js.map +1 -1
- package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.d.ts.map +1 -1
- package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js +34 -6
- package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts +30 -6
- package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js +67 -22
- package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js +18 -1
- package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts +66 -1
- package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js +161 -14
- package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts +47 -0
- package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts.map +1 -1
- package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.js.map +1 -1
- package/dist/esm/external-providers/services/content-safety.backend.service.d.ts +27 -2
- package/dist/esm/external-providers/services/content-safety.backend.service.d.ts.map +1 -1
- package/dist/esm/external-providers/services/content-safety.backend.service.js +46 -1
- package/dist/esm/external-providers/services/content-safety.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 +2 -0
- package/dist/esm/external-providers/services/embeddings.backend.service.js.map +1 -1
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +11 -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 +23 -0
- package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
- package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts +19 -1
- package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts.map +1 -1
- package/dist/esm/external-providers/services/provider-service-account-token.backend.js +41 -1
- package/dist/esm/external-providers/services/provider-service-account-token.backend.js.map +1 -1
- package/dist/esm/files/utils/file-parent-read-context.backend.d.ts +27 -2
- package/dist/esm/files/utils/file-parent-read-context.backend.d.ts.map +1 -1
- package/dist/esm/files/utils/file-parent-read-context.backend.js +23 -4
- package/dist/esm/files/utils/file-parent-read-context.backend.js.map +1 -1
- package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts +26 -0
- package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts.map +1 -1
- package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js +100 -8
- package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js.map +1 -1
- package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts +3 -1
- package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts.map +1 -1
- package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js +8 -2
- package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js.map +1 -1
- package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts +43 -0
- 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 +37 -0
- package/dist/esm/flows-actors/models/function-tools.backend.definitions.js.map +1 -1
- package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts +7 -0
- package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js +8 -3
- package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/agents.backend.service.d.ts +31 -6
- package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/agents.backend.service.js +78 -30
- package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js +4 -0
- package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts +28 -2
- 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 +132 -22
- package/dist/esm/flows-actors/services/conversational-execution.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js +12 -8
- package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts +5 -0
- 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 +18 -2
- package/dist/esm/flows-actors/services/flows-actors-registry.service.js.map +1 -1
- package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts +33 -0
- 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 +58 -0
- package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts +12 -1
- package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js +23 -4
- package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts +12 -1
- package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js +55 -17
- package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts +22 -1
- package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js +52 -9
- package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts +79 -0
- package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts.map +1 -0
- package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js +211 -0
- package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js.map +1 -0
- package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts +2 -2
- package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts.map +1 -1
- package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js +9 -1
- package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/inject/models/container.d.ts.map +1 -1
- package/dist/esm/inject/models/container.js +6 -0
- package/dist/esm/inject/models/container.js.map +1 -1
- package/dist/esm/inject/models/service-types.d.ts +5 -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/monitoring/observability/models/observability.backend.schemas.d.ts +5 -0
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/models/observability.backend.schemas.js.map +1 -1
- package/dist/esm/monitoring/observability/services/metrics.service.d.ts +34 -1
- package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -1
- package/dist/esm/monitoring/observability/services/metrics.service.js +49 -0
- package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -1
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts +6 -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 +15 -4
- package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.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.custom-impl.backend.service.js +3 -1
- package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/runtime/services/http-server.backend.service.d.ts +3 -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 +11 -3
- package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -1
- package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts +22 -0
- package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts.map +1 -1
- package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js +54 -0
- package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js.map +1 -1
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts +51 -0
- 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-password-reset.backend.service.js +87 -15
- package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js.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/siem-delivery-dlq.custom-impl.backend.service.js +5 -2
- package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js.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 +65 -24
- package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts +64 -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 +84 -2
- package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js.map +1 -1
- package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts +14 -0
- 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 +13 -5
- package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js +6 -2
- package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts +7 -0
- package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js +65 -20
- package/dist/esm/users/services/user-force-password-reset.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-role-administration.custom-impl.backend.service.js +11 -4
- package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js.map +1 -1
- package/dist/esm/users/services/user-self-custom-implementations.backend.d.ts.map +1 -1
- package/dist/esm/users/services/user-self-custom-implementations.backend.js +4 -2
- package/dist/esm/users/services/user-self-custom-implementations.backend.js.map +1 -1
- package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.d.ts.map +1 -1
- package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js +16 -0
- package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +10 -10
|
@@ -43,17 +43,27 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
43
43
|
* cannot settle the row.
|
|
44
44
|
*/
|
|
45
45
|
import { createHash } from 'node:crypto';
|
|
46
|
-
import { inject, injectable } from 'inversify';
|
|
46
|
+
import { inject, injectable, optional } from 'inversify';
|
|
47
47
|
import { inboundDeliveryCarriesChatInput, CoreResourceType, ErrorType, InboundChannelKind, InboundDeliveryAttemptOutcome, InboundDeliveryBodyRedaction, InboundDeliveryStatus, InboundSenderAssurance, InboundDeliveryUnroutableReason, InboundResolvedScopeKind, SortOrder, isAuthorityConferringOrganizationStatus, isAuthorityConferringUserStatus, isWildoBackendError, } from '@wildo-ai/saas-models';
|
|
48
48
|
import { SAAS_SERVICE_TYPES } from '../../inject/models/service-types.js';
|
|
49
49
|
import { InboundScopeStandingPolicy } from '../../inbound/models/inbound-engine-handler.backend.js';
|
|
50
50
|
import { RepositoryArrayAdditionPlacement } from '../../base-classes/services/repositories/repository-guarded-mutation.backend.types.js';
|
|
51
|
+
import { storedBodyFileIdOf } from './inbound-delivery-stored-body.backend.service.js';
|
|
51
52
|
export var InboundDeliveryInsertOutcome;
|
|
52
53
|
(function (InboundDeliveryInsertOutcome) {
|
|
53
54
|
InboundDeliveryInsertOutcome["INSERTED"] = "inserted";
|
|
54
55
|
/** The event is already stored — under this scope or the other. Nothing was written. */
|
|
55
56
|
InboundDeliveryInsertOutcome["DUPLICATE"] = "duplicate";
|
|
56
57
|
})(InboundDeliveryInsertOutcome || (InboundDeliveryInsertOutcome = {}));
|
|
58
|
+
/**
|
|
59
|
+
* What one redaction writes on a stored row (#3395): the body emptied and why ({@link bodyRedactionFields}), and a body
|
|
60
|
+
* stored outside the row released with it, in the same compare-and-swap. `clear` rather than a `null` in `set`: it is the
|
|
61
|
+
* one spelling both adapters read alike. The store deletes the released file once the swap has won
|
|
62
|
+
* ({@link InboundDeliveryStoreBackendService} `discardStoredBodyOf`).
|
|
63
|
+
*/
|
|
64
|
+
function bodyRedactionMutation(redaction, now) {
|
|
65
|
+
return { set: bodyRedactionFields(redaction, now), clear: ['storedBody', 'storedBodyFile'] };
|
|
66
|
+
}
|
|
57
67
|
/** The fields one redaction writes: the body emptied, and why. */
|
|
58
68
|
function bodyRedactionFields(redaction, now) {
|
|
59
69
|
return {
|
|
@@ -121,14 +131,17 @@ function normalize(row) {
|
|
|
121
131
|
bodyRedactedAt: row.bodyRedactedAt ?? null,
|
|
122
132
|
bodyRedaction: row.bodyRedaction ?? null,
|
|
123
133
|
bodyHeldByExecutionId: row.bodyHeldByExecutionId ?? null,
|
|
134
|
+
storedBody: row.storedBody ?? null,
|
|
124
135
|
};
|
|
125
136
|
}
|
|
126
137
|
let InboundDeliveryStoreBackendService = class InboundDeliveryStoreBackendService {
|
|
127
138
|
repositoriesRegistry;
|
|
139
|
+
storedBodies;
|
|
128
140
|
/** The store's clock. A property rather than a constructor argument so DI never tries to inject it; tests replace it. */
|
|
129
141
|
clock = () => new Date();
|
|
130
|
-
constructor(repositoriesRegistry) {
|
|
142
|
+
constructor(repositoriesRegistry, storedBodies) {
|
|
131
143
|
this.repositoriesRegistry = repositoriesRegistry;
|
|
144
|
+
this.storedBodies = storedBodies;
|
|
132
145
|
}
|
|
133
146
|
/** Read one row where it lives. */
|
|
134
147
|
async read(location) {
|
|
@@ -161,6 +174,9 @@ let InboundDeliveryStoreBackendService = class InboundDeliveryStoreBackendServic
|
|
|
161
174
|
// what a person wrote to the bot for the delivery's whole retention period would only be a copy of it. A chat command
|
|
162
175
|
// that reached none is the same (#2666 S7 L1): with no connection to post with, nobody can even answer it.
|
|
163
176
|
const chatMessageNeverRun = unroutable && inboundDeliveryCarriesChatInput(delivery);
|
|
177
|
+
// #3395: a body larger than the row was written and linked by the receiver; the row names it. A chat message that is
|
|
178
|
+
// never run keeps no body at all, so it names none, and the receiver deletes what it wrote.
|
|
179
|
+
const storedBody = chatMessageNeverRun ? undefined : delivery.storedBody;
|
|
164
180
|
const row = {
|
|
165
181
|
_id: id,
|
|
166
182
|
sourceKind: delivery.sourceKind,
|
|
@@ -171,7 +187,10 @@ let InboundDeliveryStoreBackendService = class InboundDeliveryStoreBackendServic
|
|
|
171
187
|
...(delivery.providerDeliveryId !== undefined ? { providerDeliveryId: delivery.providerDeliveryId } : {}),
|
|
172
188
|
...(delivery.signedAt !== undefined ? { signedAt: delivery.signedAt } : {}),
|
|
173
189
|
receivedAt: delivery.receivedAt,
|
|
174
|
-
rawBody: chatMessageNeverRun ? '' : delivery.rawBody.toString('base64'),
|
|
190
|
+
rawBody: chatMessageNeverRun || storedBody ? '' : delivery.rawBody.toString('base64'),
|
|
191
|
+
...(storedBody
|
|
192
|
+
? { storedBody: { sha256: storedBody.sha256, byteLength: storedBody.byteLength }, storedBodyFile: { fileId: storedBody.fileId, updatedAt: now } }
|
|
193
|
+
: { storedBody: null }),
|
|
175
194
|
headers: delivery.headers,
|
|
176
195
|
subjectKeys: [...(delivery.subjectKeys ?? [])],
|
|
177
196
|
resolvedScope: delivery.resolvedScope,
|
|
@@ -239,13 +258,18 @@ let InboundDeliveryStoreBackendService = class InboundDeliveryStoreBackendServic
|
|
|
239
258
|
*/
|
|
240
259
|
async markProcessed(location, leased, options = {}) {
|
|
241
260
|
const now = this.clock();
|
|
242
|
-
|
|
261
|
+
const redaction = options.redactBody ? bodyRedactionMutation(options.redactBody, now) : undefined;
|
|
262
|
+
const processed = await this.settle(location, leased, {
|
|
243
263
|
set: {
|
|
244
264
|
status: InboundDeliveryStatus.PROCESSED, terminalAt: now, leaseExpiresAt: null, nextAttemptAt: null, updatedAt: now,
|
|
245
|
-
...(
|
|
265
|
+
...(redaction?.set ?? {}),
|
|
246
266
|
},
|
|
267
|
+
...(redaction ? { clear: redaction.clear } : {}),
|
|
247
268
|
arrayAdditions: [{ path: 'attempts', values: [{ at: now, outcome: InboundDeliveryAttemptOutcome.PROCESSED }], placement: RepositoryArrayAdditionPlacement.TAIL, distinctOnly: false }],
|
|
248
269
|
});
|
|
270
|
+
if (processed && redaction)
|
|
271
|
+
await this.discardStoredBodyOf(leased);
|
|
272
|
+
return processed;
|
|
249
273
|
}
|
|
250
274
|
/**
|
|
251
275
|
* Empty a chat message's raw body AT ONCE, while the attempt still runs (#2665 S6, plans B4, V3): the dispatcher's
|
|
@@ -255,7 +279,10 @@ let InboundDeliveryStoreBackendService = class InboundDeliveryStoreBackendServic
|
|
|
255
279
|
*/
|
|
256
280
|
async redactBody(location, leased, redaction) {
|
|
257
281
|
const now = this.clock();
|
|
258
|
-
const
|
|
282
|
+
const mutation = bodyRedactionMutation(redaction, now);
|
|
283
|
+
const redacted = await this.repositoriesRegistry.atomicGuardedMutation(location.resourceType, { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount }, { set: { ...mutation.set, updatedAt: now }, clear: mutation.clear });
|
|
284
|
+
if (redacted)
|
|
285
|
+
await this.discardStoredBodyOf(leased);
|
|
259
286
|
return redacted ? normalize(redacted) : null;
|
|
260
287
|
}
|
|
261
288
|
/**
|
|
@@ -316,15 +343,20 @@ let InboundDeliveryStoreBackendService = class InboundDeliveryStoreBackendServic
|
|
|
316
343
|
*/
|
|
317
344
|
async markFailed(location, leased, errorCode, retryAt, options = {}) {
|
|
318
345
|
const now = this.clock();
|
|
319
|
-
|
|
346
|
+
const redaction = !retryAt && options.redactBodyIfDead ? bodyRedactionMutation(options.redactBodyIfDead, now) : undefined;
|
|
347
|
+
const failed = await this.settle(location, leased, {
|
|
320
348
|
set: retryAt
|
|
321
349
|
? { status: InboundDeliveryStatus.RETRY_SCHEDULED, nextAttemptAt: retryAt, leaseExpiresAt: null, updatedAt: now }
|
|
322
350
|
: {
|
|
323
351
|
status: InboundDeliveryStatus.DEAD, terminalAt: now, nextAttemptAt: null, leaseExpiresAt: null, updatedAt: now,
|
|
324
|
-
...(
|
|
352
|
+
...(redaction?.set ?? {}),
|
|
325
353
|
},
|
|
354
|
+
...(redaction ? { clear: redaction.clear } : {}),
|
|
326
355
|
arrayAdditions: [{ path: 'attempts', values: [{ at: now, outcome: InboundDeliveryAttemptOutcome.FAILED, errorCode: errorCode.slice(0, 200) }], placement: RepositoryArrayAdditionPlacement.TAIL, distinctOnly: false }],
|
|
327
356
|
});
|
|
357
|
+
if (failed && redaction)
|
|
358
|
+
await this.discardStoredBodyOf(leased);
|
|
359
|
+
return failed;
|
|
328
360
|
}
|
|
329
361
|
/**
|
|
330
362
|
* Operator replay: `DEAD` → `RECEIVED`, once, with a fresh retry budget, recording who and why. The
|
|
@@ -494,6 +526,15 @@ let InboundDeliveryStoreBackendService = class InboundDeliveryStoreBackendServic
|
|
|
494
526
|
return null;
|
|
495
527
|
return isUser ? InboundDeliveryUnroutableReason.USER_WITHOUT_AUTHORITY : InboundDeliveryUnroutableReason.ORGANIZATION_WITHOUT_AUTHORITY;
|
|
496
528
|
}
|
|
529
|
+
/**
|
|
530
|
+
* A redaction won its compare-and-swap (#3395): the body the row named outside itself is deleted now, as its in-row copy
|
|
531
|
+
* just was. The row no longer names the file, so whatever this cannot delete is swept by the files cleanup.
|
|
532
|
+
*/
|
|
533
|
+
async discardStoredBodyOf(before) {
|
|
534
|
+
const fileId = storedBodyFileIdOf(before);
|
|
535
|
+
if (fileId && this.storedBodies)
|
|
536
|
+
await this.storedBodies.discard(fileId, 'body_redacted');
|
|
537
|
+
}
|
|
497
538
|
async settle(location, leased, mutation) {
|
|
498
539
|
const settled = await this.repositoriesRegistry.atomicGuardedMutation(location.resourceType, { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount }, mutation);
|
|
499
540
|
return settled ? normalize(settled) : null;
|
|
@@ -502,7 +543,9 @@ let InboundDeliveryStoreBackendService = class InboundDeliveryStoreBackendServic
|
|
|
502
543
|
InboundDeliveryStoreBackendService = __decorate([
|
|
503
544
|
injectable(),
|
|
504
545
|
__param(0, inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)),
|
|
505
|
-
|
|
546
|
+
__param(1, inject(SAAS_SERVICE_TYPES.InboundDeliveryStoredBodyService)),
|
|
547
|
+
__param(1, optional()),
|
|
548
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
506
549
|
], InboundDeliveryStoreBackendService);
|
|
507
550
|
export { InboundDeliveryStoreBackendService };
|
|
508
551
|
//# sourceMappingURL=inbound-delivery-store.backend.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbound-delivery-store.backend.service.js","sourceRoot":"","sources":["../../../../src/inbound/services/inbound-delivery-store.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The inbound delivery store (#1596): insert-once, lease, settle, replay — every transition one\n * atomic statement on the infrastructure tier, on MongoDB and PostgreSQL alike.\n *\n * ## I2 — one dedup key, stored at most once, durably\n *\n * What the ledger guarantees is that one event is STORED once, so it never starts a second, independent\n * run. The handler itself runs AT LEAST once: a worker that crashes after `handle()` returned but before\n * the row settled, or a handler that throws after some of its writes, is retried. Handlers must therefore\n * be idempotent per delivery (`ctx.delivery.id` is the natural key). The lease is renewed while a\n * handler runs, so a slow handler is not taken over by a second worker while it is still working.\n *\n * The row's `_id` is DERIVED from `(sourceKey, dedupKey)` ({@link inboundDeliveryIdFor}), so the\n * primary key itself is the collision: a second insert of the same event fails on the key before any\n * handler exists, on both adapters, however many workers race it. The `(sourceKey, dedupKey)`\n * business-key set carries the same identity as a declared unique index, so the ledger's identity is\n * visible in the schema rather than only in this function.\n *\n * The two scope variants are two tables, so neither index spans both. The pipeline resolves scope\n * BEFORE inserting and reads the OTHER variant by the derived id first; an event already stored under\n * either scope is a duplicate. The residual, stated rather than hidden: two copies of one event that\n * arrive in the same instant AND resolve to different scopes (the organization mapping changed between\n * two reads microseconds apart) can each insert into their own table. Concurrent copies of one event\n * resolve identically in every case this repository has — the resolver reads the same payload\n * against the same state — so the window needs a concurrent write to the routing data itself.\n *\n * ## Fencing\n *\n * Every settle is a compare-and-swap on `_id` + `status` + `attemptCount`, and every lease increments\n * `attemptCount` (the billing outbox's discipline). A worker whose lease expired and was taken over\n * cannot settle the row.\n */\nimport { createHash } from 'node:crypto';\nimport { inject, injectable } from 'inversify';\nimport {\n InboundChatInputKind,\n inboundDeliveryCarriesChatInput,\n CoreResourceType,\n ErrorType,\n InboundChannelKind,\n InboundDeliveryAttemptOutcome,\n InboundDeliveryBodyRedaction,\n InboundDeliveryStatus,\n InboundSenderAssurance,\n InboundDeliveryUnroutableReason,\n InboundResolvedScopeKind,\n SortOrder,\n isAuthorityConferringOrganizationStatus,\n isAuthorityConferringUserStatus,\n isWildoBackendError,\n type InboundChatCommandRunResult,\n type InboundDeliveryBase,\n type InboundDeliveryBodyHolder,\n type OrganizationStatus,\n type InboundDeliveryResolvedScope,\n type ResourceType,\n type UserStatus,\n} from '@wildo-ai/saas-models';\n\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport { InboundScopeStandingPolicy } from '~wildo-backend-lib/inbound/models/inbound-engine-handler.backend';\nimport { RepositoryArrayAdditionPlacement } from '~wildo-backend-lib/base-classes/services/repositories/repository-guarded-mutation.backend.types';\n\n/** A stored delivery as the store returns it: the base row plus its variant's scope FK. */\n/** A delivery a wake made due: where it is, and when it is due, which a trailing re-read holds to its window (#2909). */\nexport interface InboundDeliveryWakeup extends InboundDeliveryLocation {\n readonly dueAt: Date;\n}\n\nexport type InboundDeliveryRow = InboundDeliveryBase & {\n readonly organizationId?: string;\n readonly applicationId?: string;\n};\n\n/** Where a row lives. */\nexport interface InboundDeliveryLocation {\n readonly resourceType: ResourceType;\n readonly id: string;\n}\n\nexport enum InboundDeliveryInsertOutcome {\n INSERTED = 'inserted',\n /** The event is already stored — under this scope or the other. Nothing was written. */\n DUPLICATE = 'duplicate',\n}\n\nexport type InboundDeliveryInsertResult =\n | { readonly outcome: InboundDeliveryInsertOutcome.INSERTED; readonly location: InboundDeliveryLocation; readonly row: InboundDeliveryRow }\n | { readonly outcome: InboundDeliveryInsertOutcome.DUPLICATE; readonly location: InboundDeliveryLocation };\n\n/** What a new row carries; the store fills the lifecycle fields. */\nexport interface NewInboundDelivery {\n readonly sourceKind: InboundDeliveryBase['sourceKind'];\n readonly sourceKey: string;\n readonly handlerRef: string;\n readonly dedupKey: string;\n readonly orderingKey: string | null;\n readonly providerDeliveryId?: string;\n readonly signedAt?: Date;\n readonly receivedAt: Date;\n readonly rawBody: Buffer;\n readonly headers: Record<string, string>;\n /** The people the payload names, as the handler declared them and the receiver normalized them (#1642). Omitted: none. */\n readonly subjectKeys?: readonly string[];\n readonly resolvedScope: InboundDeliveryResolvedScope;\n /**\n * The channel it arrived on and how much is known about its sender (#1630). Omitted by the endpoint\n * receiver: an endpoint delivery IS a webhook, stored only after its signature verified.\n */\n readonly channel?: InboundChannelKind;\n readonly senderAssurance?: InboundSenderAssurance;\n /** The conversation thread a channel delivery was recorded in. */\n readonly threadId?: string | null;\n /** What a person wrote to the bot that the delivery carries (#2665 S6 V4, #2666 S7): set by the receiver at receipt. */\n readonly chatInput?: InboundChatInputKind;\n /**\n * The delivery may not start before this instant (#2909): a re-read trigger's trailing delivery waits for the next\n * coalescing window. Stored on the row, so nothing that makes the row due later can start it earlier ({@link notBeforeOf}).\n * Omitted, it is due at receipt.\n */\n readonly notBefore?: Date;\n}\n\n/**\n * What emptying a chat message's raw body records (#2665 S6, plans B4, V3): the conversation whose transcript holds it,\n * or nothing, for a message answered without a turn.\n */\nexport interface InboundDeliveryBodyRedactionInput {\n readonly heldByExecutionId?: string;\n /** The record the delivery's handler kept its body as (#3395 received-email rows, #3394 an SMS provider event row). */\n readonly heldBy?: InboundDeliveryBodyHolder;\n}\n\n/** The fields one redaction writes: the body emptied, and why. */\nfunction bodyRedactionFields(redaction: InboundDeliveryBodyRedactionInput, now: Date): Record<string, unknown> {\n return {\n rawBody: '',\n bodyRedactedAt: now,\n bodyRedaction: redaction.heldByExecutionId\n ? InboundDeliveryBodyRedaction.HELD_BY_CONVERSATION\n : redaction.heldBy ?? InboundDeliveryBodyRedaction.NOT_KEPT,\n bodyHeldByExecutionId: redaction.heldByExecutionId ?? null,\n };\n}\n\n/**\n * Whether the owner of the scope a delivery runs in may still act — an organization, or since #1629 a person. The three\n * answers mean the same for both scopes.\n */\nexport enum InboundScopeOwnerStanding {\n CONFERS_AUTHORITY = 'confers_authority',\n WITHOUT_AUTHORITY = 'without_authority',\n NOT_FOUND = 'not_found',\n}\n\n/** How long a worker holds a `PROCESSING` row before the sweep may take it back. Renewed while the handler runs. */\nexport const INBOUND_DELIVERY_LEASE_MS = 30 * 60 * 1000;\n\n/** The derived primary key: 24 hex characters, valid as a MongoDB ObjectId and as PostgreSQL `text`. */\nexport function inboundDeliveryIdFor(sourceKey: string, dedupKey: string): string {\n return createHash('sha256').update(JSON.stringify(['inbound-delivery', sourceKey, dedupKey])).digest('hex').slice(0, 24);\n}\n\n/**\n * The variant a resolved scope stores in. An `UNROUTABLE` delivery belongs to the application that received it,\n * and so does a person's delivery (#1629): no organization owns it, and the application's operators administer it.\n */\nexport function inboundDeliveryResourceTypeFor(scope: InboundDeliveryResolvedScope): ResourceType {\n return scope.kind === InboundResolvedScopeKind.ORGANIZATION\n ? CoreResourceType.ORGANIZATION_INBOUND_DELIVERIES\n : CoreResourceType.APPLICATION_INBOUND_DELIVERIES;\n}\n\n/**\n * The earliest instant `row` may be made due, as epoch milliseconds: `at`, or the row's `notBefore` when that is later\n * (#2909 review N1). Every write that sets a due time goes through it and the lease checks it, so a re-read trigger's\n * trailing delivery is never started before its coalescing window, however it is woken. A row with no `notBefore` is\n * unaffected.\n */\nfunction notBeforeOf(row: Pick<InboundDeliveryRow, 'notBefore'>, at: Date): number {\n const notBefore = row.notBefore ?? null;\n return notBefore === null ? at.getTime() : Math.max(at.getTime(), notBefore.getTime());\n}\n\nconst VARIANTS: readonly ResourceType[] = [CoreResourceType.ORGANIZATION_INBOUND_DELIVERIES, CoreResourceType.APPLICATION_INBOUND_DELIVERIES];\n\n/** Restore absent nullable fields as null: MongoDB may leave a cleared path absent (#1076). */\nfunction normalize(row: InboundDeliveryRow): InboundDeliveryRow {\n return {\n ...row,\n orderingKey: row.orderingKey ?? null,\n nextAttemptAt: row.nextAttemptAt ?? null,\n notBefore: row.notBefore ?? null,\n leaseExpiresAt: row.leaseExpiresAt ?? null,\n terminalAt: row.terminalAt ?? null,\n attempts: row.attempts ?? [],\n replays: row.replays ?? [],\n attemptCount: row.attemptCount ?? 0,\n budgetBaseAttemptCount: row.budgetBaseAttemptCount ?? 0,\n chatInput: row.chatInput ?? null,\n commandRunStartedAt: row.commandRunStartedAt ?? null,\n commandRunResult: row.commandRunResult ?? null,\n commandRunAuditedAt: row.commandRunAuditedAt ?? null,\n bodyRedactedAt: row.bodyRedactedAt ?? null,\n bodyRedaction: row.bodyRedaction ?? null,\n bodyHeldByExecutionId: row.bodyHeldByExecutionId ?? null,\n };\n}\n\n@injectable()\nexport class InboundDeliveryStoreBackendService {\n /** The store's clock. A property rather than a constructor argument so DI never tries to inject it; tests replace it. */\n clock: () => Date = () => new Date();\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)\n private readonly repositoriesRegistry: Pick<RepositoriesRegistryHandlerBackendService, 'readUnscopedByKey' | 'insertDocumentForInfrastructure' | 'atomicGuardedMutation' | 'findManyForInfrastructure'>,\n ) {}\n\n /** Read one row where it lives. */\n async read(location: InboundDeliveryLocation): Promise<InboundDeliveryRow | null> {\n const row = await this.repositoriesRegistry.readUnscopedByKey<InboundDeliveryRow>(location.resourceType, { _id: location.id });\n return row ? normalize(row) : null;\n }\n\n /** Find a delivery by id in either variant. */\n async locate(id: string): Promise<{ location: InboundDeliveryLocation; row: InboundDeliveryRow } | null> {\n for (const resourceType of VARIANTS) {\n const row = await this.read({ resourceType, id });\n if (row) return { location: { resourceType, id }, row };\n }\n return null;\n }\n\n /**\n * Insert a verified delivery ONCE (I2). `applicationId` fills the application variant's scope FK;\n * an organization row carries its `organizationId`.\n */\n async insert(delivery: NewInboundDelivery, applicationId: string): Promise<InboundDeliveryInsertResult> {\n const id = inboundDeliveryIdFor(delivery.sourceKey, delivery.dedupKey);\n const resourceType = inboundDeliveryResourceTypeFor(delivery.resolvedScope);\n\n const existing = await this.locate(id);\n if (existing) return { outcome: InboundDeliveryInsertOutcome.DUPLICATE, location: existing.location };\n\n const unroutable = delivery.resolvedScope.kind === InboundResolvedScopeKind.UNROUTABLE;\n const now = this.clock();\n // #2665 S6 review L11: a chat message that reached no organization never runs and cannot be replayed (only a DEAD\n // delivery can), and READ withholds its body. So it is stored without one: nothing would ever read it, and keeping\n // what a person wrote to the bot for the delivery's whole retention period would only be a copy of it. A chat command\n // that reached none is the same (#2666 S7 L1): with no connection to post with, nobody can even answer it.\n const chatMessageNeverRun = unroutable && inboundDeliveryCarriesChatInput(delivery);\n const row: Record<string, unknown> = {\n _id: id,\n sourceKind: delivery.sourceKind,\n sourceKey: delivery.sourceKey,\n handlerRef: delivery.handlerRef,\n dedupKey: delivery.dedupKey,\n orderingKey: delivery.orderingKey,\n ...(delivery.providerDeliveryId !== undefined ? { providerDeliveryId: delivery.providerDeliveryId } : {}),\n ...(delivery.signedAt !== undefined ? { signedAt: delivery.signedAt } : {}),\n receivedAt: delivery.receivedAt,\n rawBody: chatMessageNeverRun ? '' : delivery.rawBody.toString('base64'),\n headers: delivery.headers,\n subjectKeys: [...(delivery.subjectKeys ?? [])],\n resolvedScope: delivery.resolvedScope,\n channel: delivery.channel ?? InboundChannelKind.WEBHOOK,\n senderAssurance: delivery.senderAssurance ?? InboundSenderAssurance.SOURCE_SIGNED,\n threadId: delivery.threadId ?? null,\n chatInput: delivery.chatInput ?? null,\n ...(chatMessageNeverRun ? bodyRedactionFields({}, now) : { bodyRedactedAt: null, bodyRedaction: null, bodyHeldByExecutionId: null }),\n status: unroutable ? InboundDeliveryStatus.UNROUTABLE : InboundDeliveryStatus.RECEIVED,\n attemptCount: 0,\n attempts: [],\n nextAttemptAt: unroutable ? null : (delivery.notBefore ?? delivery.receivedAt),\n notBefore: delivery.notBefore ?? null,\n leaseExpiresAt: null,\n budgetStartedAt: delivery.receivedAt,\n budgetBaseAttemptCount: 0,\n terminalAt: unroutable ? now : null,\n replays: [],\n createdAt: now,\n updatedAt: now,\n ...(delivery.resolvedScope.kind === InboundResolvedScopeKind.ORGANIZATION\n ? { organizationId: delivery.resolvedScope.organizationId }\n : { applicationId }),\n };\n try {\n const inserted = await this.repositoriesRegistry.insertDocumentForInfrastructure<InboundDeliveryRow>(resourceType, row);\n return { outcome: InboundDeliveryInsertOutcome.INSERTED, location: { resourceType, id }, row: normalize(inserted) };\n } catch (error) {\n // A concurrent copy of the same event won the primary key (or the business-key index): that is\n // the ledger doing its job, not a failure.\n if (isWildoBackendError(error) && error.type === ErrorType.CONFLICT) {\n return { outcome: InboundDeliveryInsertOutcome.DUPLICATE, location: { resourceType, id } };\n }\n throw error;\n }\n }\n\n /**\n * Take a due row for one attempt: `RECEIVED` / `RETRY_SCHEDULED` whose next attempt is due, or a\n * `PROCESSING` row whose lease expired. Returns the leased row, or `null` when another worker moved\n * it first or it is not due.\n */\n async lease(location: InboundDeliveryLocation, due: InboundDeliveryRow): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const isDue = due.status === InboundDeliveryStatus.PROCESSING\n ? due.leaseExpiresAt !== null && due.leaseExpiresAt.getTime() <= now.getTime()\n : (due.status === InboundDeliveryStatus.RECEIVED || due.status === InboundDeliveryStatus.RETRY_SCHEDULED)\n && due.nextAttemptAt !== null && due.nextAttemptAt.getTime() <= now.getTime()\n && notBeforeOf(due, now) <= now.getTime();\n if (!isDue) return null;\n const leased = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: due.status, attemptCount: due.attemptCount },\n {\n set: { status: InboundDeliveryStatus.PROCESSING, leaseExpiresAt: new Date(now.getTime() + INBOUND_DELIVERY_LEASE_MS), nextAttemptAt: null, updatedAt: now },\n increment: { attemptCount: 1 },\n },\n );\n return leased ? normalize(leased) : null;\n }\n\n /**\n * The leased attempt completed. `null` when this worker no longer holds the lease.\n *\n * With `redactBody` (a chat-conversation delivery, #2665 S6 plan V3) the raw body is emptied in the SAME compare-and-swap,\n * so a chat message that settled has one copy at most, its conversation's transcript, whatever the handler did. Every\n * other settle keeps the body: a failure or a DEAD delivery keeps it for the replay that is its remedy, except a chat\n * COMMAND that dies ({@link markFailed}).\n */\n async markProcessed(location: InboundDeliveryLocation, leased: InboundDeliveryRow, options: { readonly redactBody?: InboundDeliveryBodyRedactionInput } = {}): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n return this.settle(location, leased, {\n set: {\n status: InboundDeliveryStatus.PROCESSED, terminalAt: now, leaseExpiresAt: null, nextAttemptAt: null, updatedAt: now,\n ...(options.redactBody ? bodyRedactionFields(options.redactBody, now) : {}),\n },\n arrayAdditions: [{ path: 'attempts', values: [{ at: now, outcome: InboundDeliveryAttemptOutcome.PROCESSED }], placement: RepositoryArrayAdditionPlacement.TAIL, distinctOnly: false }],\n });\n }\n\n /**\n * Empty a chat message's raw body AT ONCE, while the attempt still runs (#2665 S6, plans B4, V3): the dispatcher's\n * `ctx.chat.converse()` does it when the chat door answers that the conversation's transcript has taken the message (a\n * turn started, or the message was already there), so a handler that throws afterwards leaves no second copy for its\n * retry. Fenced on the lease like every move of a leased row. `null` when this worker no longer holds the lease.\n */\n async redactBody(location: InboundDeliveryLocation, leased: InboundDeliveryRow, redaction: InboundDeliveryBodyRedactionInput): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const redacted = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount },\n { set: { ...bodyRedactionFields(redaction, now), updatedAt: now } },\n );\n return redacted ? normalize(redacted) : null;\n }\n\n /**\n * A chat command's write starts (#2666 S7, design N1): a compare-and-swap on the lease (PROCESSING, this attempt's\n * count) AND on no start recorded yet. So two attempts, or two `ctx.chat.runCommand()` calls in one, start it once, and a\n * retry that finds the start without an outcome knows the write may have run. Recorded BEFORE the dispatch, after every\n * refusal that can be decided in advance. `null` when the swap lost: the lease is gone, or a start is already recorded.\n */\n async startCommandRun(location: InboundDeliveryLocation, leased: InboundDeliveryRow): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const started = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount, commandRunStartedAt: null },\n { set: { commandRunStartedAt: now, updatedAt: now } },\n );\n return started ? normalize(started) : null;\n }\n\n /**\n * What a chat command did (#2666 S7): recorded under the lease, and only while no outcome is recorded, so the FIRST\n * outcome stands. A retry answers it (a RAN answers as ALREADY_RAN) and never records a second. `null` when the swap\n * lost: the lease is gone, or an outcome is already recorded.\n */\n async recordCommandRunResult(location: InboundDeliveryLocation, leased: InboundDeliveryRow, result: InboundChatCommandRunResult): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const recorded = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount, commandRunResult: null },\n { set: { commandRunResult: result, updatedAt: now } },\n );\n return recorded ? normalize(recorded) : null;\n }\n\n /**\n * The chat command's `CHAT_COMMAND_RUN` row was written (#2666 S7, design N5): recorded under the lease, once. A retry\n * that finds an outcome without this writes the row then, so a crash between the outcome and the row never loses the\n * only evidence of a command, and a retry after the row never writes a second. `null` when the swap lost.\n */\n async markCommandRunAudited(location: InboundDeliveryLocation, leased: InboundDeliveryRow): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const marked = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount, commandRunAuditedAt: null },\n { set: { commandRunAuditedAt: now, updatedAt: now } },\n );\n return marked ? normalize(marked) : null;\n }\n\n /**\n * The leased attempt could not run yet (#2665 S6, plans B5, V5): `PROCESSING` → `RECEIVED`, due at `nextAttemptAt`.\n * The attempt the lease spent is undone by advancing `budgetBaseAttemptCount` by exactly one (the mechanism a replay\n * uses; the attempt count itself never goes down, because the lease's fence IS the count), so waiting on a busy chat\n * conversation spends none of the handler's retries and forgives no earlier failure. No attempt is recorded, nothing\n * is audited and nothing is enqueued: the recheck sweep, or the conversation's settled reply, brings it back. `RECEIVED`,\n * not `RETRY_SCHEDULED`, so `wakeOrderingSuccessor` and `wakeEarliestOnOrderingKey` may hurry it. `null` when this worker\n * no longer holds the lease.\n */\n async releaseNotYet(location: InboundDeliveryLocation, leased: InboundDeliveryRow, nextAttemptAt: Date): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const released = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount },\n {\n set: { status: InboundDeliveryStatus.RECEIVED, nextAttemptAt, leaseExpiresAt: null, updatedAt: now },\n increment: { budgetBaseAttemptCount: 1 },\n },\n );\n return released ? normalize(released) : null;\n }\n\n /**\n * The leased attempt failed. With `retryAt` the row is `RETRY_SCHEDULED`; without it the budget is\n * spent and the row is `DEAD`. `errorCode` is a classification, never an error message.\n *\n * `redactBodyIfDead` empties the raw body in the SAME compare-and-swap when the row dies, never on a retry (#2666 S7\n * slice review F3): a chat COMMAND's text is worth keeping only while it can still run, and a DEAD one can be replayed\n * only inside the command's staleness window, which the person can cover by typing it again.\n */\n async markFailed(\n location: InboundDeliveryLocation,\n leased: InboundDeliveryRow,\n errorCode: string,\n retryAt: Date | null,\n options: { readonly redactBodyIfDead?: InboundDeliveryBodyRedactionInput } = {},\n ): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n return this.settle(location, leased, {\n set: retryAt\n ? { status: InboundDeliveryStatus.RETRY_SCHEDULED, nextAttemptAt: retryAt, leaseExpiresAt: null, updatedAt: now }\n : {\n status: InboundDeliveryStatus.DEAD, terminalAt: now, nextAttemptAt: null, leaseExpiresAt: null, updatedAt: now,\n ...(options.redactBodyIfDead ? bodyRedactionFields(options.redactBodyIfDead, now) : {}),\n },\n arrayAdditions: [{ path: 'attempts', values: [{ at: now, outcome: InboundDeliveryAttemptOutcome.FAILED, errorCode: errorCode.slice(0, 200) }], placement: RepositoryArrayAdditionPlacement.TAIL, distinctOnly: false }],\n });\n }\n\n /**\n * Operator replay: `DEAD` → `RECEIVED`, once, with a fresh retry budget, recording who and why. The\n * compare-and-swap on `DEAD` is what makes it \"once\": a second replay of the same row finds it\n * `RECEIVED` and changes nothing. `null` when the row is not `DEAD`.\n */\n async replay(location: InboundDeliveryLocation, dead: InboundDeliveryRow, by: string, justification: string): Promise<InboundDeliveryRow | null> {\n if (dead.status !== InboundDeliveryStatus.DEAD) return null;\n const now = this.clock();\n const replayed = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.DEAD, attemptCount: dead.attemptCount },\n {\n set: {\n status: InboundDeliveryStatus.RECEIVED,\n nextAttemptAt: new Date(notBeforeOf(dead, now)),\n terminalAt: null,\n budgetStartedAt: now,\n budgetBaseAttemptCount: dead.attemptCount,\n updatedAt: now,\n },\n arrayAdditions: [{ path: 'replays', values: [{ by, at: now, justification }], placement: RepositoryArrayAdditionPlacement.TAIL, distinctOnly: false }],\n },\n );\n return replayed ? normalize(replayed) : null;\n }\n\n /**\n * Rows a worker should take now, oldest first, across both variants: queued rows whose next attempt\n * is due, and processing rows whose lease expired. Bounded per query.\n */\n async findDue(limit: number): Promise<{ location: InboundDeliveryLocation; row: InboundDeliveryRow }[]> {\n const now = this.clock();\n const found: { location: InboundDeliveryLocation; row: InboundDeliveryRow }[] = [];\n for (const resourceType of VARIANTS) {\n for (const [filter, field] of [\n [{ status: InboundDeliveryStatus.RECEIVED, nextAttemptAt: { $lte: now } }, 'nextAttemptAt'],\n [{ status: InboundDeliveryStatus.RETRY_SCHEDULED, nextAttemptAt: { $lte: now } }, 'nextAttemptAt'],\n [{ status: InboundDeliveryStatus.PROCESSING, leaseExpiresAt: { $lte: now } }, 'leaseExpiresAt'],\n ] as const) {\n const rows = await this.repositoriesRegistry.findManyForInfrastructure<InboundDeliveryRow>(resourceType, { ...filter }, undefined, undefined, {\n sort: [{ field, order: SortOrder.ASC }, { field: '_id', order: SortOrder.ASC }],\n limit,\n });\n for (const row of rows) found.push({ location: { resourceType, id: String(row._id) }, row: normalize(row) });\n }\n }\n // By DUE time, not receipt: a delivery deferred behind its ordering predecessor is re-dated each time\n // it is deferred, so it cannot hold the page against rows that have been waiting longer.\n const dueAt = (row: InboundDeliveryRow) => (row.status === InboundDeliveryStatus.PROCESSING ? row.leaseExpiresAt : row.nextAttemptAt)?.getTime() ?? 0;\n return found\n .sort((a, b) => dueAt(a.row) - dueAt(b.row) || a.location.id.localeCompare(b.location.id))\n .slice(0, limit);\n }\n\n /**\n * Whether an EARLIER delivery with the same handler and ordering key is still pending (received,\n * processing or scheduled for retry). Asked BEFORE leasing, so a blocked delivery consumes no attempt. A `DEAD` or `UNROUTABLE` predecessor does not block: waiting on\n * a row nothing will move would stall the key forever.\n */\n async hasPendingPredecessor(location: InboundDeliveryLocation, row: InboundDeliveryRow): Promise<boolean> {\n if (row.orderingKey === null) return false;\n const pending = [InboundDeliveryStatus.RECEIVED, InboundDeliveryStatus.PROCESSING, InboundDeliveryStatus.RETRY_SCHEDULED];\n for (const status of pending) {\n const candidates = await this.repositoriesRegistry.findManyForInfrastructure<InboundDeliveryRow>(\n location.resourceType,\n { handlerRef: row.handlerRef, orderingKey: row.orderingKey, status, receivedAt: { $lte: row.receivedAt } },\n undefined,\n undefined,\n { sort: [{ field: 'receivedAt', order: SortOrder.ASC }, { field: '_id', order: SortOrder.ASC }], limit: 2 },\n );\n const earlier = candidates.some((candidate) => String(candidate._id) !== location.id\n && (candidate.receivedAt.getTime() < row.receivedAt.getTime()\n || (candidate.receivedAt.getTime() === row.receivedAt.getTime() && String(candidate._id) < location.id)));\n if (earlier) return true;\n }\n return false;\n }\n\n /**\n * Keep a running attempt's lease alive. `null` when this worker no longer holds it — the row was\n * taken over, or settled by another worker — which the caller logs; it cannot stop a running handler.\n */\n async renewLease(location: InboundDeliveryLocation, leased: InboundDeliveryRow): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const renewed = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount },\n { set: { leaseExpiresAt: new Date(now.getTime() + INBOUND_DELIVERY_LEASE_MS), updatedAt: now } },\n );\n return renewed ? normalize(renewed) : null;\n }\n\n /**\n * A delivery blocked by its ordering predecessor waits WITHOUT scheduling itself: its next attempt\n * moves to `until`, and only the sweep (or the predecessor settling, {@link wakeOrderingSuccessor})\n * brings it back. A self-rescheduling wait multiplied: every sweep started another chain for the same\n * row. Compare-and-swap on the row as read, so a row another worker moved is left alone.\n */\n async deferForOrdering(location: InboundDeliveryLocation, row: InboundDeliveryRow, until: Date): Promise<boolean> {\n if (row.status !== InboundDeliveryStatus.RECEIVED && row.status !== InboundDeliveryStatus.RETRY_SCHEDULED) return false;\n const deferred = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: row.status, attemptCount: row.attemptCount },\n { set: { nextAttemptAt: new Date(notBeforeOf(row, until)), updatedAt: this.clock() } },\n );\n return deferred !== null;\n }\n\n /**\n * The earliest delivery WAITING behind `settled` on its ordering key, made due now, or at its `notBefore` when that is\n * later (#2909 review N1). Returns its location and when it is due, so the caller enqueues it for then; `null` when\n * nothing waits. Only a `RECEIVED` successor is hurried: one scheduled for a retry keeps its backoff.\n */\n async wakeOrderingSuccessor(location: InboundDeliveryLocation, settled: InboundDeliveryRow): Promise<InboundDeliveryWakeup | null> {\n if (settled.orderingKey === null) return null;\n const waiting = await this.repositoriesRegistry.findManyForInfrastructure<InboundDeliveryRow>(\n location.resourceType,\n { handlerRef: settled.handlerRef, orderingKey: settled.orderingKey, status: InboundDeliveryStatus.RECEIVED, receivedAt: { $gte: settled.receivedAt } },\n undefined,\n undefined,\n { sort: [{ field: 'receivedAt', order: SortOrder.ASC }, { field: '_id', order: SortOrder.ASC }], limit: 2 },\n );\n const next = waiting.map(normalize).find((candidate) => String(candidate._id) !== location.id);\n if (!next) return null;\n const now = this.clock();\n const dueAt = new Date(notBeforeOf(next, now));\n const woken = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: String(next._id), status: InboundDeliveryStatus.RECEIVED, attemptCount: next.attemptCount },\n { set: { nextAttemptAt: dueAt, updatedAt: now } },\n );\n return woken ? { resourceType: location.resourceType, id: String(next._id), dueAt } : null;\n }\n\n /**\n * The earliest delivery waiting on `orderingKey`, made due now, or at its `notBefore` when that is later (#2665 S6, plan\n * V8; #2909 review N1). The chat reply dispatcher calls it\n * when a conversation's owed reply is settled: the turn that answered it has ended, so the next message deferred on\n * the conversation can run. Keyed by the ordering key alone: a chat conversation's key is a hash of its organization,\n * connection, vendor conversation and sender (`chatConversationOrderingKeyOf`), so no other handler's deliveries share\n * it. Only a `RECEIVED` delivery is hurried: one scheduled for a retry keeps its backoff. Returns its location, or\n * `null` when nothing waits.\n */\n async wakeEarliestOnOrderingKey(resourceType: InboundDeliveryLocation['resourceType'], orderingKey: string): Promise<InboundDeliveryWakeup | null> {\n const waiting = await this.repositoriesRegistry.findManyForInfrastructure<InboundDeliveryRow>(\n resourceType,\n { orderingKey, status: InboundDeliveryStatus.RECEIVED },\n undefined,\n undefined,\n { sort: [{ field: 'receivedAt', order: SortOrder.ASC }, { field: '_id', order: SortOrder.ASC }], limit: 1 },\n );\n const next = waiting.map(normalize)[0];\n if (!next) return null;\n const now = this.clock();\n const dueAt = new Date(notBeforeOf(next, now));\n const woken = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n resourceType,\n { _id: String(next._id), status: InboundDeliveryStatus.RECEIVED, attemptCount: next.attemptCount },\n { set: { nextAttemptAt: dueAt, updatedAt: now } },\n );\n return woken ? { resourceType, id: String(next._id), dueAt } : null;\n }\n\n /**\n * Whether an organization still confers authority. Read when a delivery RUNS, not only when it\n * arrived: an organization suspended or marked for deletion after acceptance must not keep acting\n * through its retries.\n */\n async organizationStanding(organizationId: string): Promise<InboundScopeOwnerStanding> {\n const organization = await this.repositoriesRegistry.readUnscopedByKey<{ _id: string; status?: OrganizationStatus }>(\n CoreResourceType.ORGANIZATIONS, { _id: organizationId },\n );\n if (!organization) return InboundScopeOwnerStanding.NOT_FOUND;\n return isAuthorityConferringOrganizationStatus(organization.status) ? InboundScopeOwnerStanding.CONFERS_AUTHORITY : InboundScopeOwnerStanding.WITHOUT_AUTHORITY;\n }\n\n /**\n * Whether a person still confers authority over their own data (#1629) — ACTIVE only. Read when a USER-scope\n * delivery RUNS and before a replay, for the reason {@link organizationStanding} is.\n */\n async userStanding(userId: string): Promise<InboundScopeOwnerStanding> {\n const user = await this.repositoriesRegistry.readUnscopedByKey<{ _id: string; status?: UserStatus }>(CoreResourceType.USERS, { _id: userId });\n if (!user) return InboundScopeOwnerStanding.NOT_FOUND;\n return isAuthorityConferringUserStatus(user.status) ? InboundScopeOwnerStanding.CONFERS_AUTHORITY : InboundScopeOwnerStanding.WITHOUT_AUTHORITY;\n }\n\n /**\n * Why the delivery's scope may not run now, or `null` when it may. NOT_FOUND refuses under every policy: there\n * is nothing left to act on. WITHOUT_AUTHORITY refuses unless the handler records regardless of standing.\n */\n async scopeStandingRefusal(row: Pick<InboundDeliveryRow, 'resolvedScope'>, policy: InboundScopeStandingPolicy): Promise<InboundDeliveryUnroutableReason | null> {\n const scope = row.resolvedScope;\n const standing = scope.kind === InboundResolvedScopeKind.ORGANIZATION\n ? await this.organizationStanding(scope.organizationId)\n : scope.kind === InboundResolvedScopeKind.USER\n ? await this.userStanding(scope.userId)\n : InboundScopeOwnerStanding.CONFERS_AUTHORITY;\n if (standing === InboundScopeOwnerStanding.CONFERS_AUTHORITY) return null;\n const isUser = scope.kind === InboundResolvedScopeKind.USER;\n if (standing === InboundScopeOwnerStanding.NOT_FOUND) {\n return isUser ? InboundDeliveryUnroutableReason.USER_NOT_FOUND : InboundDeliveryUnroutableReason.ORGANIZATION_NOT_FOUND;\n }\n if (policy === InboundScopeStandingPolicy.RECORD_REGARDLESS_OF_STANDING) return null;\n return isUser ? InboundDeliveryUnroutableReason.USER_WITHOUT_AUTHORITY : InboundDeliveryUnroutableReason.ORGANIZATION_WITHOUT_AUTHORITY;\n }\n\n private async settle(location: InboundDeliveryLocation, leased: InboundDeliveryRow, mutation: Parameters<RepositoriesRegistryHandlerBackendService['atomicGuardedMutation']>[2]): Promise<InboundDeliveryRow | null> {\n const settled = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount },\n mutation,\n );\n return settled ? normalize(settled) : null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"inbound-delivery-store.backend.service.js","sourceRoot":"","sources":["../../../../src/inbound/services/inbound-delivery-store.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The inbound delivery store (#1596): insert-once, lease, settle, replay — every transition one\n * atomic statement on the infrastructure tier, on MongoDB and PostgreSQL alike.\n *\n * ## I2 — one dedup key, stored at most once, durably\n *\n * What the ledger guarantees is that one event is STORED once, so it never starts a second, independent\n * run. The handler itself runs AT LEAST once: a worker that crashes after `handle()` returned but before\n * the row settled, or a handler that throws after some of its writes, is retried. Handlers must therefore\n * be idempotent per delivery (`ctx.delivery.id` is the natural key). The lease is renewed while a\n * handler runs, so a slow handler is not taken over by a second worker while it is still working.\n *\n * The row's `_id` is DERIVED from `(sourceKey, dedupKey)` ({@link inboundDeliveryIdFor}), so the\n * primary key itself is the collision: a second insert of the same event fails on the key before any\n * handler exists, on both adapters, however many workers race it. The `(sourceKey, dedupKey)`\n * business-key set carries the same identity as a declared unique index, so the ledger's identity is\n * visible in the schema rather than only in this function.\n *\n * The two scope variants are two tables, so neither index spans both. The pipeline resolves scope\n * BEFORE inserting and reads the OTHER variant by the derived id first; an event already stored under\n * either scope is a duplicate. The residual, stated rather than hidden: two copies of one event that\n * arrive in the same instant AND resolve to different scopes (the organization mapping changed between\n * two reads microseconds apart) can each insert into their own table. Concurrent copies of one event\n * resolve identically in every case this repository has — the resolver reads the same payload\n * against the same state — so the window needs a concurrent write to the routing data itself.\n *\n * ## Fencing\n *\n * Every settle is a compare-and-swap on `_id` + `status` + `attemptCount`, and every lease increments\n * `attemptCount` (the billing outbox's discipline). A worker whose lease expired and was taken over\n * cannot settle the row.\n */\nimport { createHash } from 'node:crypto';\nimport { inject, injectable, optional } from 'inversify';\nimport {\n InboundChatInputKind,\n inboundDeliveryCarriesChatInput,\n CoreResourceType,\n ErrorType,\n InboundChannelKind,\n InboundDeliveryAttemptOutcome,\n InboundDeliveryBodyRedaction,\n InboundDeliveryStatus,\n InboundSenderAssurance,\n InboundDeliveryUnroutableReason,\n InboundResolvedScopeKind,\n SortOrder,\n isAuthorityConferringOrganizationStatus,\n isAuthorityConferringUserStatus,\n isWildoBackendError,\n type InboundChatCommandRunResult,\n type InboundDeliveryBase,\n type InboundDeliveryBodyHolder,\n type OrganizationStatus,\n type InboundDeliveryResolvedScope,\n type ResourceType,\n type UserStatus,\n} from '@wildo-ai/saas-models';\n\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport { InboundScopeStandingPolicy } from '~wildo-backend-lib/inbound/models/inbound-engine-handler.backend';\nimport { RepositoryArrayAdditionPlacement } from '~wildo-backend-lib/base-classes/services/repositories/repository-guarded-mutation.backend.types';\nimport { storedBodyFileIdOf, type InboundDeliveryStoredBodyBackendService, type StoredInboundBody } from './inbound-delivery-stored-body.backend.service';\n\n/** A stored delivery as the store returns it: the base row plus its variant's scope FK. */\n/** A delivery a wake made due: where it is, and when it is due, which a trailing re-read holds to its window (#2909). */\nexport interface InboundDeliveryWakeup extends InboundDeliveryLocation {\n readonly dueAt: Date;\n}\n\nexport type InboundDeliveryRow = InboundDeliveryBase & {\n readonly organizationId?: string;\n readonly applicationId?: string;\n};\n\n/** Where a row lives. */\nexport interface InboundDeliveryLocation {\n readonly resourceType: ResourceType;\n readonly id: string;\n}\n\nexport enum InboundDeliveryInsertOutcome {\n INSERTED = 'inserted',\n /** The event is already stored — under this scope or the other. Nothing was written. */\n DUPLICATE = 'duplicate',\n}\n\nexport type InboundDeliveryInsertResult =\n | { readonly outcome: InboundDeliveryInsertOutcome.INSERTED; readonly location: InboundDeliveryLocation; readonly row: InboundDeliveryRow }\n | { readonly outcome: InboundDeliveryInsertOutcome.DUPLICATE; readonly location: InboundDeliveryLocation };\n\n/** What a new row carries; the store fills the lifecycle fields. */\nexport interface NewInboundDelivery {\n readonly sourceKind: InboundDeliveryBase['sourceKind'];\n readonly sourceKey: string;\n readonly handlerRef: string;\n readonly dedupKey: string;\n readonly orderingKey: string | null;\n readonly providerDeliveryId?: string;\n readonly signedAt?: Date;\n readonly receivedAt: Date;\n readonly rawBody: Buffer;\n /**\n * The body as written outside the row (#3395), when it is larger than the row holds: the receiver wrote and linked the\n * file, and the row keeps its id, SHA-256 and length with an empty `rawBody`. Omitted: the body is kept in the row.\n */\n readonly storedBody?: StoredInboundBody;\n readonly headers: Record<string, string>;\n /** The people the payload names, as the handler declared them and the receiver normalized them (#1642). Omitted: none. */\n readonly subjectKeys?: readonly string[];\n readonly resolvedScope: InboundDeliveryResolvedScope;\n /**\n * The channel it arrived on and how much is known about its sender (#1630). Omitted by the endpoint\n * receiver: an endpoint delivery IS a webhook, stored only after its signature verified.\n */\n readonly channel?: InboundChannelKind;\n readonly senderAssurance?: InboundSenderAssurance;\n /** The conversation thread a channel delivery was recorded in. */\n readonly threadId?: string | null;\n /** What a person wrote to the bot that the delivery carries (#2665 S6 V4, #2666 S7): set by the receiver at receipt. */\n readonly chatInput?: InboundChatInputKind;\n /**\n * The delivery may not start before this instant (#2909): a re-read trigger's trailing delivery waits for the next\n * coalescing window. Stored on the row, so nothing that makes the row due later can start it earlier ({@link notBeforeOf}).\n * Omitted, it is due at receipt.\n */\n readonly notBefore?: Date;\n}\n\n/**\n * What emptying a chat message's raw body records (#2665 S6, plans B4, V3): the conversation whose transcript holds it,\n * or nothing, for a message answered without a turn.\n */\nexport interface InboundDeliveryBodyRedactionInput {\n readonly heldByExecutionId?: string;\n /** The record the delivery's handler kept its body as (#3395 received-email rows, #3394 an SMS provider event row). */\n readonly heldBy?: InboundDeliveryBodyHolder;\n}\n\n/**\n * What one redaction writes on a stored row (#3395): the body emptied and why ({@link bodyRedactionFields}), and a body\n * stored outside the row released with it, in the same compare-and-swap. `clear` rather than a `null` in `set`: it is the\n * one spelling both adapters read alike. The store deletes the released file once the swap has won\n * ({@link InboundDeliveryStoreBackendService} `discardStoredBodyOf`).\n */\nfunction bodyRedactionMutation(redaction: InboundDeliveryBodyRedactionInput, now: Date): { readonly set: Record<string, unknown>; readonly clear: readonly string[] } {\n return { set: bodyRedactionFields(redaction, now), clear: ['storedBody', 'storedBodyFile'] };\n}\n\n/** The fields one redaction writes: the body emptied, and why. */\nfunction bodyRedactionFields(redaction: InboundDeliveryBodyRedactionInput, now: Date): Record<string, unknown> {\n return {\n rawBody: '',\n bodyRedactedAt: now,\n bodyRedaction: redaction.heldByExecutionId\n ? InboundDeliveryBodyRedaction.HELD_BY_CONVERSATION\n : redaction.heldBy ?? InboundDeliveryBodyRedaction.NOT_KEPT,\n bodyHeldByExecutionId: redaction.heldByExecutionId ?? null,\n };\n}\n\n/**\n * Whether the owner of the scope a delivery runs in may still act — an organization, or since #1629 a person. The three\n * answers mean the same for both scopes.\n */\nexport enum InboundScopeOwnerStanding {\n CONFERS_AUTHORITY = 'confers_authority',\n WITHOUT_AUTHORITY = 'without_authority',\n NOT_FOUND = 'not_found',\n}\n\n/** How long a worker holds a `PROCESSING` row before the sweep may take it back. Renewed while the handler runs. */\nexport const INBOUND_DELIVERY_LEASE_MS = 30 * 60 * 1000;\n\n/** The derived primary key: 24 hex characters, valid as a MongoDB ObjectId and as PostgreSQL `text`. */\nexport function inboundDeliveryIdFor(sourceKey: string, dedupKey: string): string {\n return createHash('sha256').update(JSON.stringify(['inbound-delivery', sourceKey, dedupKey])).digest('hex').slice(0, 24);\n}\n\n/**\n * The variant a resolved scope stores in. An `UNROUTABLE` delivery belongs to the application that received it,\n * and so does a person's delivery (#1629): no organization owns it, and the application's operators administer it.\n */\nexport function inboundDeliveryResourceTypeFor(scope: InboundDeliveryResolvedScope): ResourceType {\n return scope.kind === InboundResolvedScopeKind.ORGANIZATION\n ? CoreResourceType.ORGANIZATION_INBOUND_DELIVERIES\n : CoreResourceType.APPLICATION_INBOUND_DELIVERIES;\n}\n\n/**\n * The earliest instant `row` may be made due, as epoch milliseconds: `at`, or the row's `notBefore` when that is later\n * (#2909 review N1). Every write that sets a due time goes through it and the lease checks it, so a re-read trigger's\n * trailing delivery is never started before its coalescing window, however it is woken. A row with no `notBefore` is\n * unaffected.\n */\nfunction notBeforeOf(row: Pick<InboundDeliveryRow, 'notBefore'>, at: Date): number {\n const notBefore = row.notBefore ?? null;\n return notBefore === null ? at.getTime() : Math.max(at.getTime(), notBefore.getTime());\n}\n\nconst VARIANTS: readonly ResourceType[] = [CoreResourceType.ORGANIZATION_INBOUND_DELIVERIES, CoreResourceType.APPLICATION_INBOUND_DELIVERIES];\n\n/** Restore absent nullable fields as null: MongoDB may leave a cleared path absent (#1076). */\nfunction normalize(row: InboundDeliveryRow): InboundDeliveryRow {\n return {\n ...row,\n orderingKey: row.orderingKey ?? null,\n nextAttemptAt: row.nextAttemptAt ?? null,\n notBefore: row.notBefore ?? null,\n leaseExpiresAt: row.leaseExpiresAt ?? null,\n terminalAt: row.terminalAt ?? null,\n attempts: row.attempts ?? [],\n replays: row.replays ?? [],\n attemptCount: row.attemptCount ?? 0,\n budgetBaseAttemptCount: row.budgetBaseAttemptCount ?? 0,\n chatInput: row.chatInput ?? null,\n commandRunStartedAt: row.commandRunStartedAt ?? null,\n commandRunResult: row.commandRunResult ?? null,\n commandRunAuditedAt: row.commandRunAuditedAt ?? null,\n bodyRedactedAt: row.bodyRedactedAt ?? null,\n bodyRedaction: row.bodyRedaction ?? null,\n bodyHeldByExecutionId: row.bodyHeldByExecutionId ?? null,\n storedBody: row.storedBody ?? null,\n };\n}\n\n@injectable()\nexport class InboundDeliveryStoreBackendService {\n /** The store's clock. A property rather than a constructor argument so DI never tries to inject it; tests replace it. */\n clock: () => Date = () => new Date();\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)\n private readonly repositoriesRegistry: Pick<RepositoriesRegistryHandlerBackendService, 'readUnscopedByKey' | 'insertDocumentForInfrastructure' | 'atomicGuardedMutation' | 'findManyForInfrastructure'>,\n /**\n * Deletes a body stored outside its row once a redaction released it (#3395). Bound in every backend; optional only for\n * a store that never holds one (a unit test's). What it cannot delete now stays DELETED and the files cleanup removes it.\n */\n @inject(SAAS_SERVICE_TYPES.InboundDeliveryStoredBodyService) @optional()\n private readonly storedBodies?: Pick<InboundDeliveryStoredBodyBackendService, 'discard'>,\n ) {}\n\n /** Read one row where it lives. */\n async read(location: InboundDeliveryLocation): Promise<InboundDeliveryRow | null> {\n const row = await this.repositoriesRegistry.readUnscopedByKey<InboundDeliveryRow>(location.resourceType, { _id: location.id });\n return row ? normalize(row) : null;\n }\n\n /** Find a delivery by id in either variant. */\n async locate(id: string): Promise<{ location: InboundDeliveryLocation; row: InboundDeliveryRow } | null> {\n for (const resourceType of VARIANTS) {\n const row = await this.read({ resourceType, id });\n if (row) return { location: { resourceType, id }, row };\n }\n return null;\n }\n\n /**\n * Insert a verified delivery ONCE (I2). `applicationId` fills the application variant's scope FK;\n * an organization row carries its `organizationId`.\n */\n async insert(delivery: NewInboundDelivery, applicationId: string): Promise<InboundDeliveryInsertResult> {\n const id = inboundDeliveryIdFor(delivery.sourceKey, delivery.dedupKey);\n const resourceType = inboundDeliveryResourceTypeFor(delivery.resolvedScope);\n\n const existing = await this.locate(id);\n if (existing) return { outcome: InboundDeliveryInsertOutcome.DUPLICATE, location: existing.location };\n\n const unroutable = delivery.resolvedScope.kind === InboundResolvedScopeKind.UNROUTABLE;\n const now = this.clock();\n // #2665 S6 review L11: a chat message that reached no organization never runs and cannot be replayed (only a DEAD\n // delivery can), and READ withholds its body. So it is stored without one: nothing would ever read it, and keeping\n // what a person wrote to the bot for the delivery's whole retention period would only be a copy of it. A chat command\n // that reached none is the same (#2666 S7 L1): with no connection to post with, nobody can even answer it.\n const chatMessageNeverRun = unroutable && inboundDeliveryCarriesChatInput(delivery);\n // #3395: a body larger than the row was written and linked by the receiver; the row names it. A chat message that is\n // never run keeps no body at all, so it names none, and the receiver deletes what it wrote.\n const storedBody = chatMessageNeverRun ? undefined : delivery.storedBody;\n const row: Record<string, unknown> = {\n _id: id,\n sourceKind: delivery.sourceKind,\n sourceKey: delivery.sourceKey,\n handlerRef: delivery.handlerRef,\n dedupKey: delivery.dedupKey,\n orderingKey: delivery.orderingKey,\n ...(delivery.providerDeliveryId !== undefined ? { providerDeliveryId: delivery.providerDeliveryId } : {}),\n ...(delivery.signedAt !== undefined ? { signedAt: delivery.signedAt } : {}),\n receivedAt: delivery.receivedAt,\n rawBody: chatMessageNeverRun || storedBody ? '' : delivery.rawBody.toString('base64'),\n ...(storedBody\n ? { storedBody: { sha256: storedBody.sha256, byteLength: storedBody.byteLength }, storedBodyFile: { fileId: storedBody.fileId, updatedAt: now } }\n : { storedBody: null }),\n headers: delivery.headers,\n subjectKeys: [...(delivery.subjectKeys ?? [])],\n resolvedScope: delivery.resolvedScope,\n channel: delivery.channel ?? InboundChannelKind.WEBHOOK,\n senderAssurance: delivery.senderAssurance ?? InboundSenderAssurance.SOURCE_SIGNED,\n threadId: delivery.threadId ?? null,\n chatInput: delivery.chatInput ?? null,\n ...(chatMessageNeverRun ? bodyRedactionFields({}, now) : { bodyRedactedAt: null, bodyRedaction: null, bodyHeldByExecutionId: null }),\n status: unroutable ? InboundDeliveryStatus.UNROUTABLE : InboundDeliveryStatus.RECEIVED,\n attemptCount: 0,\n attempts: [],\n nextAttemptAt: unroutable ? null : (delivery.notBefore ?? delivery.receivedAt),\n notBefore: delivery.notBefore ?? null,\n leaseExpiresAt: null,\n budgetStartedAt: delivery.receivedAt,\n budgetBaseAttemptCount: 0,\n terminalAt: unroutable ? now : null,\n replays: [],\n createdAt: now,\n updatedAt: now,\n ...(delivery.resolvedScope.kind === InboundResolvedScopeKind.ORGANIZATION\n ? { organizationId: delivery.resolvedScope.organizationId }\n : { applicationId }),\n };\n try {\n const inserted = await this.repositoriesRegistry.insertDocumentForInfrastructure<InboundDeliveryRow>(resourceType, row);\n return { outcome: InboundDeliveryInsertOutcome.INSERTED, location: { resourceType, id }, row: normalize(inserted) };\n } catch (error) {\n // A concurrent copy of the same event won the primary key (or the business-key index): that is\n // the ledger doing its job, not a failure.\n if (isWildoBackendError(error) && error.type === ErrorType.CONFLICT) {\n return { outcome: InboundDeliveryInsertOutcome.DUPLICATE, location: { resourceType, id } };\n }\n throw error;\n }\n }\n\n /**\n * Take a due row for one attempt: `RECEIVED` / `RETRY_SCHEDULED` whose next attempt is due, or a\n * `PROCESSING` row whose lease expired. Returns the leased row, or `null` when another worker moved\n * it first or it is not due.\n */\n async lease(location: InboundDeliveryLocation, due: InboundDeliveryRow): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const isDue = due.status === InboundDeliveryStatus.PROCESSING\n ? due.leaseExpiresAt !== null && due.leaseExpiresAt.getTime() <= now.getTime()\n : (due.status === InboundDeliveryStatus.RECEIVED || due.status === InboundDeliveryStatus.RETRY_SCHEDULED)\n && due.nextAttemptAt !== null && due.nextAttemptAt.getTime() <= now.getTime()\n && notBeforeOf(due, now) <= now.getTime();\n if (!isDue) return null;\n const leased = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: due.status, attemptCount: due.attemptCount },\n {\n set: { status: InboundDeliveryStatus.PROCESSING, leaseExpiresAt: new Date(now.getTime() + INBOUND_DELIVERY_LEASE_MS), nextAttemptAt: null, updatedAt: now },\n increment: { attemptCount: 1 },\n },\n );\n return leased ? normalize(leased) : null;\n }\n\n /**\n * The leased attempt completed. `null` when this worker no longer holds the lease.\n *\n * With `redactBody` (a chat-conversation delivery, #2665 S6 plan V3) the raw body is emptied in the SAME compare-and-swap,\n * so a chat message that settled has one copy at most, its conversation's transcript, whatever the handler did. Every\n * other settle keeps the body: a failure or a DEAD delivery keeps it for the replay that is its remedy, except a chat\n * COMMAND that dies ({@link markFailed}).\n */\n async markProcessed(location: InboundDeliveryLocation, leased: InboundDeliveryRow, options: { readonly redactBody?: InboundDeliveryBodyRedactionInput } = {}): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const redaction = options.redactBody ? bodyRedactionMutation(options.redactBody, now) : undefined;\n const processed = await this.settle(location, leased, {\n set: {\n status: InboundDeliveryStatus.PROCESSED, terminalAt: now, leaseExpiresAt: null, nextAttemptAt: null, updatedAt: now,\n ...(redaction?.set ?? {}),\n },\n ...(redaction ? { clear: redaction.clear } : {}),\n arrayAdditions: [{ path: 'attempts', values: [{ at: now, outcome: InboundDeliveryAttemptOutcome.PROCESSED }], placement: RepositoryArrayAdditionPlacement.TAIL, distinctOnly: false }],\n });\n if (processed && redaction) await this.discardStoredBodyOf(leased);\n return processed;\n }\n\n /**\n * Empty a chat message's raw body AT ONCE, while the attempt still runs (#2665 S6, plans B4, V3): the dispatcher's\n * `ctx.chat.converse()` does it when the chat door answers that the conversation's transcript has taken the message (a\n * turn started, or the message was already there), so a handler that throws afterwards leaves no second copy for its\n * retry. Fenced on the lease like every move of a leased row. `null` when this worker no longer holds the lease.\n */\n async redactBody(location: InboundDeliveryLocation, leased: InboundDeliveryRow, redaction: InboundDeliveryBodyRedactionInput): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const mutation = bodyRedactionMutation(redaction, now);\n const redacted = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount },\n { set: { ...mutation.set, updatedAt: now }, clear: mutation.clear },\n );\n if (redacted) await this.discardStoredBodyOf(leased);\n return redacted ? normalize(redacted) : null;\n }\n\n /**\n * A chat command's write starts (#2666 S7, design N1): a compare-and-swap on the lease (PROCESSING, this attempt's\n * count) AND on no start recorded yet. So two attempts, or two `ctx.chat.runCommand()` calls in one, start it once, and a\n * retry that finds the start without an outcome knows the write may have run. Recorded BEFORE the dispatch, after every\n * refusal that can be decided in advance. `null` when the swap lost: the lease is gone, or a start is already recorded.\n */\n async startCommandRun(location: InboundDeliveryLocation, leased: InboundDeliveryRow): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const started = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount, commandRunStartedAt: null },\n { set: { commandRunStartedAt: now, updatedAt: now } },\n );\n return started ? normalize(started) : null;\n }\n\n /**\n * What a chat command did (#2666 S7): recorded under the lease, and only while no outcome is recorded, so the FIRST\n * outcome stands. A retry answers it (a RAN answers as ALREADY_RAN) and never records a second. `null` when the swap\n * lost: the lease is gone, or an outcome is already recorded.\n */\n async recordCommandRunResult(location: InboundDeliveryLocation, leased: InboundDeliveryRow, result: InboundChatCommandRunResult): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const recorded = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount, commandRunResult: null },\n { set: { commandRunResult: result, updatedAt: now } },\n );\n return recorded ? normalize(recorded) : null;\n }\n\n /**\n * The chat command's `CHAT_COMMAND_RUN` row was written (#2666 S7, design N5): recorded under the lease, once. A retry\n * that finds an outcome without this writes the row then, so a crash between the outcome and the row never loses the\n * only evidence of a command, and a retry after the row never writes a second. `null` when the swap lost.\n */\n async markCommandRunAudited(location: InboundDeliveryLocation, leased: InboundDeliveryRow): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const marked = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount, commandRunAuditedAt: null },\n { set: { commandRunAuditedAt: now, updatedAt: now } },\n );\n return marked ? normalize(marked) : null;\n }\n\n /**\n * The leased attempt could not run yet (#2665 S6, plans B5, V5): `PROCESSING` → `RECEIVED`, due at `nextAttemptAt`.\n * The attempt the lease spent is undone by advancing `budgetBaseAttemptCount` by exactly one (the mechanism a replay\n * uses; the attempt count itself never goes down, because the lease's fence IS the count), so waiting on a busy chat\n * conversation spends none of the handler's retries and forgives no earlier failure. No attempt is recorded, nothing\n * is audited and nothing is enqueued: the recheck sweep, or the conversation's settled reply, brings it back. `RECEIVED`,\n * not `RETRY_SCHEDULED`, so `wakeOrderingSuccessor` and `wakeEarliestOnOrderingKey` may hurry it. `null` when this worker\n * no longer holds the lease.\n */\n async releaseNotYet(location: InboundDeliveryLocation, leased: InboundDeliveryRow, nextAttemptAt: Date): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const released = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount },\n {\n set: { status: InboundDeliveryStatus.RECEIVED, nextAttemptAt, leaseExpiresAt: null, updatedAt: now },\n increment: { budgetBaseAttemptCount: 1 },\n },\n );\n return released ? normalize(released) : null;\n }\n\n /**\n * The leased attempt failed. With `retryAt` the row is `RETRY_SCHEDULED`; without it the budget is\n * spent and the row is `DEAD`. `errorCode` is a classification, never an error message.\n *\n * `redactBodyIfDead` empties the raw body in the SAME compare-and-swap when the row dies, never on a retry (#2666 S7\n * slice review F3): a chat COMMAND's text is worth keeping only while it can still run, and a DEAD one can be replayed\n * only inside the command's staleness window, which the person can cover by typing it again.\n */\n async markFailed(\n location: InboundDeliveryLocation,\n leased: InboundDeliveryRow,\n errorCode: string,\n retryAt: Date | null,\n options: { readonly redactBodyIfDead?: InboundDeliveryBodyRedactionInput } = {},\n ): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const redaction = !retryAt && options.redactBodyIfDead ? bodyRedactionMutation(options.redactBodyIfDead, now) : undefined;\n const failed = await this.settle(location, leased, {\n set: retryAt\n ? { status: InboundDeliveryStatus.RETRY_SCHEDULED, nextAttemptAt: retryAt, leaseExpiresAt: null, updatedAt: now }\n : {\n status: InboundDeliveryStatus.DEAD, terminalAt: now, nextAttemptAt: null, leaseExpiresAt: null, updatedAt: now,\n ...(redaction?.set ?? {}),\n },\n ...(redaction ? { clear: redaction.clear } : {}),\n arrayAdditions: [{ path: 'attempts', values: [{ at: now, outcome: InboundDeliveryAttemptOutcome.FAILED, errorCode: errorCode.slice(0, 200) }], placement: RepositoryArrayAdditionPlacement.TAIL, distinctOnly: false }],\n });\n if (failed && redaction) await this.discardStoredBodyOf(leased);\n return failed;\n }\n\n /**\n * Operator replay: `DEAD` → `RECEIVED`, once, with a fresh retry budget, recording who and why. The\n * compare-and-swap on `DEAD` is what makes it \"once\": a second replay of the same row finds it\n * `RECEIVED` and changes nothing. `null` when the row is not `DEAD`.\n */\n async replay(location: InboundDeliveryLocation, dead: InboundDeliveryRow, by: string, justification: string): Promise<InboundDeliveryRow | null> {\n if (dead.status !== InboundDeliveryStatus.DEAD) return null;\n const now = this.clock();\n const replayed = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.DEAD, attemptCount: dead.attemptCount },\n {\n set: {\n status: InboundDeliveryStatus.RECEIVED,\n nextAttemptAt: new Date(notBeforeOf(dead, now)),\n terminalAt: null,\n budgetStartedAt: now,\n budgetBaseAttemptCount: dead.attemptCount,\n updatedAt: now,\n },\n arrayAdditions: [{ path: 'replays', values: [{ by, at: now, justification }], placement: RepositoryArrayAdditionPlacement.TAIL, distinctOnly: false }],\n },\n );\n return replayed ? normalize(replayed) : null;\n }\n\n /**\n * Rows a worker should take now, oldest first, across both variants: queued rows whose next attempt\n * is due, and processing rows whose lease expired. Bounded per query.\n */\n async findDue(limit: number): Promise<{ location: InboundDeliveryLocation; row: InboundDeliveryRow }[]> {\n const now = this.clock();\n const found: { location: InboundDeliveryLocation; row: InboundDeliveryRow }[] = [];\n for (const resourceType of VARIANTS) {\n for (const [filter, field] of [\n [{ status: InboundDeliveryStatus.RECEIVED, nextAttemptAt: { $lte: now } }, 'nextAttemptAt'],\n [{ status: InboundDeliveryStatus.RETRY_SCHEDULED, nextAttemptAt: { $lte: now } }, 'nextAttemptAt'],\n [{ status: InboundDeliveryStatus.PROCESSING, leaseExpiresAt: { $lte: now } }, 'leaseExpiresAt'],\n ] as const) {\n const rows = await this.repositoriesRegistry.findManyForInfrastructure<InboundDeliveryRow>(resourceType, { ...filter }, undefined, undefined, {\n sort: [{ field, order: SortOrder.ASC }, { field: '_id', order: SortOrder.ASC }],\n limit,\n });\n for (const row of rows) found.push({ location: { resourceType, id: String(row._id) }, row: normalize(row) });\n }\n }\n // By DUE time, not receipt: a delivery deferred behind its ordering predecessor is re-dated each time\n // it is deferred, so it cannot hold the page against rows that have been waiting longer.\n const dueAt = (row: InboundDeliveryRow) => (row.status === InboundDeliveryStatus.PROCESSING ? row.leaseExpiresAt : row.nextAttemptAt)?.getTime() ?? 0;\n return found\n .sort((a, b) => dueAt(a.row) - dueAt(b.row) || a.location.id.localeCompare(b.location.id))\n .slice(0, limit);\n }\n\n /**\n * Whether an EARLIER delivery with the same handler and ordering key is still pending (received,\n * processing or scheduled for retry). Asked BEFORE leasing, so a blocked delivery consumes no attempt. A `DEAD` or `UNROUTABLE` predecessor does not block: waiting on\n * a row nothing will move would stall the key forever.\n */\n async hasPendingPredecessor(location: InboundDeliveryLocation, row: InboundDeliveryRow): Promise<boolean> {\n if (row.orderingKey === null) return false;\n const pending = [InboundDeliveryStatus.RECEIVED, InboundDeliveryStatus.PROCESSING, InboundDeliveryStatus.RETRY_SCHEDULED];\n for (const status of pending) {\n const candidates = await this.repositoriesRegistry.findManyForInfrastructure<InboundDeliveryRow>(\n location.resourceType,\n { handlerRef: row.handlerRef, orderingKey: row.orderingKey, status, receivedAt: { $lte: row.receivedAt } },\n undefined,\n undefined,\n { sort: [{ field: 'receivedAt', order: SortOrder.ASC }, { field: '_id', order: SortOrder.ASC }], limit: 2 },\n );\n const earlier = candidates.some((candidate) => String(candidate._id) !== location.id\n && (candidate.receivedAt.getTime() < row.receivedAt.getTime()\n || (candidate.receivedAt.getTime() === row.receivedAt.getTime() && String(candidate._id) < location.id)));\n if (earlier) return true;\n }\n return false;\n }\n\n /**\n * Keep a running attempt's lease alive. `null` when this worker no longer holds it — the row was\n * taken over, or settled by another worker — which the caller logs; it cannot stop a running handler.\n */\n async renewLease(location: InboundDeliveryLocation, leased: InboundDeliveryRow): Promise<InboundDeliveryRow | null> {\n const now = this.clock();\n const renewed = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount },\n { set: { leaseExpiresAt: new Date(now.getTime() + INBOUND_DELIVERY_LEASE_MS), updatedAt: now } },\n );\n return renewed ? normalize(renewed) : null;\n }\n\n /**\n * A delivery blocked by its ordering predecessor waits WITHOUT scheduling itself: its next attempt\n * moves to `until`, and only the sweep (or the predecessor settling, {@link wakeOrderingSuccessor})\n * brings it back. A self-rescheduling wait multiplied: every sweep started another chain for the same\n * row. Compare-and-swap on the row as read, so a row another worker moved is left alone.\n */\n async deferForOrdering(location: InboundDeliveryLocation, row: InboundDeliveryRow, until: Date): Promise<boolean> {\n if (row.status !== InboundDeliveryStatus.RECEIVED && row.status !== InboundDeliveryStatus.RETRY_SCHEDULED) return false;\n const deferred = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: row.status, attemptCount: row.attemptCount },\n { set: { nextAttemptAt: new Date(notBeforeOf(row, until)), updatedAt: this.clock() } },\n );\n return deferred !== null;\n }\n\n /**\n * The earliest delivery WAITING behind `settled` on its ordering key, made due now, or at its `notBefore` when that is\n * later (#2909 review N1). Returns its location and when it is due, so the caller enqueues it for then; `null` when\n * nothing waits. Only a `RECEIVED` successor is hurried: one scheduled for a retry keeps its backoff.\n */\n async wakeOrderingSuccessor(location: InboundDeliveryLocation, settled: InboundDeliveryRow): Promise<InboundDeliveryWakeup | null> {\n if (settled.orderingKey === null) return null;\n const waiting = await this.repositoriesRegistry.findManyForInfrastructure<InboundDeliveryRow>(\n location.resourceType,\n { handlerRef: settled.handlerRef, orderingKey: settled.orderingKey, status: InboundDeliveryStatus.RECEIVED, receivedAt: { $gte: settled.receivedAt } },\n undefined,\n undefined,\n { sort: [{ field: 'receivedAt', order: SortOrder.ASC }, { field: '_id', order: SortOrder.ASC }], limit: 2 },\n );\n const next = waiting.map(normalize).find((candidate) => String(candidate._id) !== location.id);\n if (!next) return null;\n const now = this.clock();\n const dueAt = new Date(notBeforeOf(next, now));\n const woken = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: String(next._id), status: InboundDeliveryStatus.RECEIVED, attemptCount: next.attemptCount },\n { set: { nextAttemptAt: dueAt, updatedAt: now } },\n );\n return woken ? { resourceType: location.resourceType, id: String(next._id), dueAt } : null;\n }\n\n /**\n * The earliest delivery waiting on `orderingKey`, made due now, or at its `notBefore` when that is later (#2665 S6, plan\n * V8; #2909 review N1). The chat reply dispatcher calls it\n * when a conversation's owed reply is settled: the turn that answered it has ended, so the next message deferred on\n * the conversation can run. Keyed by the ordering key alone: a chat conversation's key is a hash of its organization,\n * connection, vendor conversation and sender (`chatConversationOrderingKeyOf`), so no other handler's deliveries share\n * it. Only a `RECEIVED` delivery is hurried: one scheduled for a retry keeps its backoff. Returns its location, or\n * `null` when nothing waits.\n */\n async wakeEarliestOnOrderingKey(resourceType: InboundDeliveryLocation['resourceType'], orderingKey: string): Promise<InboundDeliveryWakeup | null> {\n const waiting = await this.repositoriesRegistry.findManyForInfrastructure<InboundDeliveryRow>(\n resourceType,\n { orderingKey, status: InboundDeliveryStatus.RECEIVED },\n undefined,\n undefined,\n { sort: [{ field: 'receivedAt', order: SortOrder.ASC }, { field: '_id', order: SortOrder.ASC }], limit: 1 },\n );\n const next = waiting.map(normalize)[0];\n if (!next) return null;\n const now = this.clock();\n const dueAt = new Date(notBeforeOf(next, now));\n const woken = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n resourceType,\n { _id: String(next._id), status: InboundDeliveryStatus.RECEIVED, attemptCount: next.attemptCount },\n { set: { nextAttemptAt: dueAt, updatedAt: now } },\n );\n return woken ? { resourceType, id: String(next._id), dueAt } : null;\n }\n\n /**\n * Whether an organization still confers authority. Read when a delivery RUNS, not only when it\n * arrived: an organization suspended or marked for deletion after acceptance must not keep acting\n * through its retries.\n */\n async organizationStanding(organizationId: string): Promise<InboundScopeOwnerStanding> {\n const organization = await this.repositoriesRegistry.readUnscopedByKey<{ _id: string; status?: OrganizationStatus }>(\n CoreResourceType.ORGANIZATIONS, { _id: organizationId },\n );\n if (!organization) return InboundScopeOwnerStanding.NOT_FOUND;\n return isAuthorityConferringOrganizationStatus(organization.status) ? InboundScopeOwnerStanding.CONFERS_AUTHORITY : InboundScopeOwnerStanding.WITHOUT_AUTHORITY;\n }\n\n /**\n * Whether a person still confers authority over their own data (#1629) — ACTIVE only. Read when a USER-scope\n * delivery RUNS and before a replay, for the reason {@link organizationStanding} is.\n */\n async userStanding(userId: string): Promise<InboundScopeOwnerStanding> {\n const user = await this.repositoriesRegistry.readUnscopedByKey<{ _id: string; status?: UserStatus }>(CoreResourceType.USERS, { _id: userId });\n if (!user) return InboundScopeOwnerStanding.NOT_FOUND;\n return isAuthorityConferringUserStatus(user.status) ? InboundScopeOwnerStanding.CONFERS_AUTHORITY : InboundScopeOwnerStanding.WITHOUT_AUTHORITY;\n }\n\n /**\n * Why the delivery's scope may not run now, or `null` when it may. NOT_FOUND refuses under every policy: there\n * is nothing left to act on. WITHOUT_AUTHORITY refuses unless the handler records regardless of standing.\n */\n async scopeStandingRefusal(row: Pick<InboundDeliveryRow, 'resolvedScope'>, policy: InboundScopeStandingPolicy): Promise<InboundDeliveryUnroutableReason | null> {\n const scope = row.resolvedScope;\n const standing = scope.kind === InboundResolvedScopeKind.ORGANIZATION\n ? await this.organizationStanding(scope.organizationId)\n : scope.kind === InboundResolvedScopeKind.USER\n ? await this.userStanding(scope.userId)\n : InboundScopeOwnerStanding.CONFERS_AUTHORITY;\n if (standing === InboundScopeOwnerStanding.CONFERS_AUTHORITY) return null;\n const isUser = scope.kind === InboundResolvedScopeKind.USER;\n if (standing === InboundScopeOwnerStanding.NOT_FOUND) {\n return isUser ? InboundDeliveryUnroutableReason.USER_NOT_FOUND : InboundDeliveryUnroutableReason.ORGANIZATION_NOT_FOUND;\n }\n if (policy === InboundScopeStandingPolicy.RECORD_REGARDLESS_OF_STANDING) return null;\n return isUser ? InboundDeliveryUnroutableReason.USER_WITHOUT_AUTHORITY : InboundDeliveryUnroutableReason.ORGANIZATION_WITHOUT_AUTHORITY;\n }\n\n /**\n * A redaction won its compare-and-swap (#3395): the body the row named outside itself is deleted now, as its in-row copy\n * just was. The row no longer names the file, so whatever this cannot delete is swept by the files cleanup.\n */\n private async discardStoredBodyOf(before: InboundDeliveryRow): Promise<void> {\n const fileId = storedBodyFileIdOf(before);\n if (fileId && this.storedBodies) await this.storedBodies.discard(fileId, 'body_redacted');\n }\n\n private async settle(location: InboundDeliveryLocation, leased: InboundDeliveryRow, mutation: Parameters<RepositoriesRegistryHandlerBackendService['atomicGuardedMutation']>[2]): Promise<InboundDeliveryRow | null> {\n const settled = await this.repositoriesRegistry.atomicGuardedMutation<InboundDeliveryRow>(\n location.resourceType,\n { _id: location.id, status: InboundDeliveryStatus.PROCESSING, attemptCount: leased.attemptCount },\n mutation,\n );\n return settled ? normalize(settled) : null;\n }\n}\n"]}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type InboundDeliveryStoredBody, type ResourceType } from '@wildo-ai/saas-models';
|
|
2
|
+
import type { LoggerService } from '../../monitoring/logger/services/logger.service';
|
|
3
|
+
import type { RepositoriesRegistryHandlerBackendService } from '../../base-classes/services/repositories/repositories-registry-handler.backend.service';
|
|
4
|
+
import type { RepositoryOptions } from '../../base-classes/models/repositories.backend.schemas';
|
|
5
|
+
import type { ResourcesRegistryBackendService } from '../../resources/services/resources-registry.backend.service';
|
|
6
|
+
import type { ExecutionContextCreatorBackendService } from '../../runtime/services/execution-context-creator.backend.service';
|
|
7
|
+
import type { ExecutionContext } from '../../runtime/models/execution-context.backend.schemas';
|
|
8
|
+
import type { FilesBackendService } from '../../files/services/files.backend.service';
|
|
9
|
+
import { type ServerProducedFileWriterDependencies } from '../../files/services/server-produced-file-writer.backend';
|
|
10
|
+
/** A body written outside its row: the file, and the binding the row keeps. */
|
|
11
|
+
export interface StoredInboundBody extends InboundDeliveryStoredBody {
|
|
12
|
+
readonly fileId: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The bytes read back for a delivery are not the bytes it received: the file is gone, or its length or SHA-256 differs
|
|
16
|
+
* from what the row recorded at receipt. Permanent: no retry brings the received message back, so the delivery dies and
|
|
17
|
+
* an operator sees why. A storage outage is NOT this error; it is retried.
|
|
18
|
+
*/
|
|
19
|
+
export declare class InboundStoredBodyIntegrityError extends Error {
|
|
20
|
+
readonly name = "InboundStoredBodyIntegrityError";
|
|
21
|
+
}
|
|
22
|
+
/** The file a row's body is stored as, or undefined for a body kept in the row. */
|
|
23
|
+
export declare function storedBodyFileIdOf(row: {
|
|
24
|
+
readonly storedBodyFile?: unknown;
|
|
25
|
+
}): string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Mark the body files of rows a repository delete removed as DELETED, in the caller's transaction (#3395): a person's
|
|
28
|
+
* erasure deletes deliveries by repository, which releases no file. The files cleanup then removes their bytes, exactly as
|
|
29
|
+
* it does for every file an erasure releases (`FilesBackendService.eraseFile`: a DB rollback must never be mixed with
|
|
30
|
+
* storage side effects). Guarded on the file still being linked to that row and field, so a file another row took is
|
|
31
|
+
* never touched. Returns how many were released.
|
|
32
|
+
*/
|
|
33
|
+
export declare function releaseStoredBodyFilesOfDeletedRows(input: {
|
|
34
|
+
readonly registry: Pick<RepositoriesRegistryHandlerBackendService, 'atomicConditionalSet'>;
|
|
35
|
+
readonly table: ResourceType;
|
|
36
|
+
readonly rows: readonly Readonly<Record<string, unknown>>[];
|
|
37
|
+
readonly executionContext?: ExecutionContext<any>;
|
|
38
|
+
readonly options?: RepositoryOptions;
|
|
39
|
+
}): Promise<number>;
|
|
40
|
+
export declare class InboundDeliveryStoredBodyBackendService {
|
|
41
|
+
private readonly logger;
|
|
42
|
+
private readonly fileWriter;
|
|
43
|
+
private readonly files;
|
|
44
|
+
private readonly repositoriesRegistry;
|
|
45
|
+
private readonly contexts;
|
|
46
|
+
private readonly resources;
|
|
47
|
+
constructor(logger: LoggerService, fileWriter: ServerProducedFileWriterDependencies, files: Pick<FilesBackendService, 'linkFileToResource' | 'hardDeleteFile'>, repositoriesRegistry: Pick<RepositoriesRegistryHandlerBackendService, 'readUnscopedByKey' | 'atomicConditionalSet'>, contexts: Pick<ExecutionContextCreatorBackendService, 'createForInternalOperation'>, resources: Pick<ResourcesRegistryBackendService, 'getServiceOperationPathDefault'>);
|
|
48
|
+
/**
|
|
49
|
+
* Write a verified body for the delivery that will be stored at `resourceType` / `deliveryId`, and link it to that row
|
|
50
|
+
* before the row exists (its id is derived from the event, so it is known). `ownerRow` names the row's owner (its
|
|
51
|
+
* `organizationId`, or its `applicationId`): an internal context carries no organization. A failure after the write
|
|
52
|
+
* releases the file and throws, so the caller answers "retry later" and nothing half-written is kept.
|
|
53
|
+
*/
|
|
54
|
+
write(input: {
|
|
55
|
+
readonly resourceType: ResourceType;
|
|
56
|
+
readonly deliveryId: string;
|
|
57
|
+
readonly bytes: Buffer;
|
|
58
|
+
readonly mimeType: string;
|
|
59
|
+
readonly ownerRow: Readonly<Record<string, unknown>>;
|
|
60
|
+
}): Promise<StoredInboundBody>;
|
|
61
|
+
/**
|
|
62
|
+
* The bytes of a body stored outside its row, checked against the row: never past `byteLength`, exactly `byteLength`,
|
|
63
|
+
* and hashing to `sha256`. A mismatch, or a file that is gone, is {@link InboundStoredBodyIntegrityError}; a provider that
|
|
64
|
+
* does not answer throws its own error and the delivery is retried.
|
|
65
|
+
*/
|
|
66
|
+
read(resourceType: ResourceType, row: {
|
|
67
|
+
readonly _id: unknown;
|
|
68
|
+
readonly storedBody?: InboundDeliveryStoredBody | null;
|
|
69
|
+
readonly storedBodyFile?: unknown;
|
|
70
|
+
}): Promise<Buffer>;
|
|
71
|
+
/**
|
|
72
|
+
* Delete a stored body now: its `files` row is marked DELETED (unlinked), then its bytes and row are removed. Never
|
|
73
|
+
* throws: a body whose bytes could not be removed stays DELETED, and the files cleanup removes it at the FILES period.
|
|
74
|
+
* Used when the row's body is emptied and when a write is abandoned (a duplicate, a failed insert).
|
|
75
|
+
*/
|
|
76
|
+
discard(fileId: string, reason: string): Promise<void>;
|
|
77
|
+
private context;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=inbound-delivery-stored-body.backend.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-delivery-stored-body.backend.service.d.ts","sourceRoot":"","sources":["../../../../src/inbound/services/inbound-delivery-stored-body.backend.service.ts"],"names":[],"mappings":"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"}
|