@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
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type { ApprovalSealStatus, AuthScopeType, CryptoKey_Purpose, CryptoKey_SignatureOutcome, CryptoKey_SignatureRefusal } from '@wildo-ai/saas-models';
|
|
1
|
+
import type { ApprovalSealStatus, AuthScopeType, CryptoKey_Purpose, CryptoKey_SignatureOutcome, CryptoKey_SignatureRefusal, SignatureRequest_State } from '@wildo-ai/saas-models';
|
|
2
|
+
import type { ElectronicSignature_Level } from '@wildo-ai/external-connectors-models';
|
|
3
|
+
import type { SignatureRequestEvidenceFailure, SignatureRequestSendRefusal } from '../../../compliance/electronic-signatures/signature-requests.backend.service';
|
|
4
|
+
import type { SignatureRequestEvidenceLinkOutcome } from '../../../compliance/electronic-signatures/signature-request-evidence-files.backend';
|
|
5
|
+
import type { ElectronicSignatureSendOutcome } from '../../../external-providers/services/electronic-signature.backend.service';
|
|
2
6
|
import type { SubmissionChallengeRefusalReason } from '../../../security/submission-challenge/submission-challenge.backend.service';
|
|
3
7
|
import type { CspViolationDisposition, CspViolationReportDelivery, CspViolationReportedDirective } from '../../../monitoring/csp-violation-reports/csp-violation-reports.backend.utils';
|
|
4
8
|
/**
|
|
@@ -245,6 +249,35 @@ export declare class MetricsService {
|
|
|
245
249
|
private approvalSealOldestUnsealedAgeObserved;
|
|
246
250
|
/** #2903 — the age of the oldest seal a relay run left unsealed (0 when none). Synchronous, never throws. */
|
|
247
251
|
recordApprovalSealOldestUnsealedAge(ageSeconds: number): void;
|
|
252
|
+
/**
|
|
253
|
+
* #2293 — one sending of a deliverable for electronic signature: `sent`, or the `SignatureRequestSendRefusal` that stopped
|
|
254
|
+
* it. Synchronous, never throws.
|
|
255
|
+
*/
|
|
256
|
+
recordSignatureRequestSent(params: {
|
|
257
|
+
outcome: ElectronicSignatureSendOutcome.SENT | SignatureRequestSendRefusal;
|
|
258
|
+
requiredLevel: ElectronicSignature_Level;
|
|
259
|
+
}): void;
|
|
260
|
+
/** #2293 — a signature request a re-read moved, by the state it reached. Synchronous, never throws. */
|
|
261
|
+
recordSignatureRequestMoved(params: {
|
|
262
|
+
providerRef: string;
|
|
263
|
+
to: SignatureRequest_State;
|
|
264
|
+
}): void;
|
|
265
|
+
/**
|
|
266
|
+
* #2293 — a request the vendor reported complete that stayed open, or failed, on its evidence, by
|
|
267
|
+
* `SignatureRequestEvidenceFailure`. Synchronous, never throws.
|
|
268
|
+
*/
|
|
269
|
+
recordSignatureRequestEvidenceRefused(params: {
|
|
270
|
+
providerRef: string;
|
|
271
|
+
failure: SignatureRequestEvidenceFailure;
|
|
272
|
+
}): void;
|
|
273
|
+
/** #2293 — a re-read the vendor did not answer usably. Synchronous, never throws. */
|
|
274
|
+
recordSignatureRequestVendorNotRead(params: {
|
|
275
|
+
providerRef: string;
|
|
276
|
+
}): void;
|
|
277
|
+
/** #2293 — one link of a SIGNED request's evidence file, by `SignatureRequestEvidenceLinkOutcome`. Synchronous, never throws. */
|
|
278
|
+
recordSignatureRequestEvidenceLink(params: {
|
|
279
|
+
outcome: SignatureRequestEvidenceLinkOutcome;
|
|
280
|
+
}): void;
|
|
248
281
|
/** #2891 — a key version found signing past its purpose's cryptoperiod (reported once per version). Synchronous, never throws. */
|
|
249
282
|
recordKeyManagementRotationDue(params: {
|
|
250
283
|
purpose: CryptoKey_Purpose;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.service.d.ts","sourceRoot":"","sources":["../../../../../src/monitoring/observability/services/metrics.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"metrics.service.d.ts","sourceRoot":"","sources":["../../../../../src/monitoring/observability/services/metrics.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -172,6 +172,29 @@ let MetricsService = class MetricsService {
|
|
|
172
172
|
description: 'Age of the oldest approval seal the last relay run left unsealed (0 when none): the relay\'s backlog',
|
|
173
173
|
unit: 's',
|
|
174
174
|
}),
|
|
175
|
+
// #2293 — electronic-signature requests (level 2). The audit rows record each request; these answer "is signing
|
|
176
|
+
// healthy?" without reading them. Alert on:
|
|
177
|
+
// increase(signature_request_sent_total{outcome!~"sent|already_open"}[1h]) > 0 a deliverable not sent
|
|
178
|
+
// increase(signature_request_evidence_refused_total{failure!="rejected"}[1h]) > 0 the engine cannot keep evidence
|
|
179
|
+
// increase(signature_request_evidence_link_total{outcome="lost"}[1h]) > 0 a SIGNED request's evidence lost
|
|
180
|
+
// rate(signature_request_vendor_not_read_total[15m]) > 0, sustained a vendor down
|
|
181
|
+
// A steady `failure="rejected"` is a vendor whose documents do not validate (anchors, revocation, tampering), and
|
|
182
|
+
// `failure="mismatched"` a signer or level that can never be met. Labels: closed enums and the declared provider ref.
|
|
183
|
+
signatureRequestSentTotal: this.meter.createCounter('signature_request_sent_total', {
|
|
184
|
+
description: 'Deliverables sent for electronic signature, by outcome (sent, or the refusal) and required level',
|
|
185
|
+
}),
|
|
186
|
+
signatureRequestMovedTotal: this.meter.createCounter('signature_request_moved_total', {
|
|
187
|
+
description: 'Signature requests moved by a re-read, by provider and the state reached',
|
|
188
|
+
}),
|
|
189
|
+
signatureRequestEvidenceRefusedTotal: this.meter.createCounter('signature_request_evidence_refused_total', {
|
|
190
|
+
description: 'Requests a vendor reported complete whose evidence did not make them SIGNED, by provider and failure',
|
|
191
|
+
}),
|
|
192
|
+
signatureRequestVendorNotReadTotal: this.meter.createCounter('signature_request_vendor_not_read_total', {
|
|
193
|
+
description: 'Re-reads of a signature request its vendor did not answer usably, by provider',
|
|
194
|
+
}),
|
|
195
|
+
signatureRequestEvidenceLinkTotal: this.meter.createCounter('signature_request_evidence_link_total', {
|
|
196
|
+
description: 'Links of a SIGNED request\'s evidence files, by outcome (lost: evidence a request names and nothing keeps)',
|
|
197
|
+
}),
|
|
175
198
|
// #1735 — a public form's submissions refused at their challenge. A sudden rise is a bot wave; a steady
|
|
176
199
|
// `vendor_refused_secret` or `provider_verifier_unavailable` is a DEPLOYMENT fault (every real visitor is being
|
|
177
200
|
// turned away), which is why those two are worth an alert of their own:
|
|
@@ -489,6 +512,32 @@ let MetricsService = class MetricsService {
|
|
|
489
512
|
this.approvalSealOldestUnsealedAgeObserved = true;
|
|
490
513
|
this.metricsDefinitions.approvalSealOldestUnsealedAgeSeconds.addCallback((result) => result.observe(this.approvalSealOldestUnsealedAge));
|
|
491
514
|
}
|
|
515
|
+
/**
|
|
516
|
+
* #2293 — one sending of a deliverable for electronic signature: `sent`, or the `SignatureRequestSendRefusal` that stopped
|
|
517
|
+
* it. Synchronous, never throws.
|
|
518
|
+
*/
|
|
519
|
+
recordSignatureRequestSent(params) {
|
|
520
|
+
this.metricsDefinitions.signatureRequestSentTotal.add(1, { outcome: params.outcome, required_level: params.requiredLevel });
|
|
521
|
+
}
|
|
522
|
+
/** #2293 — a signature request a re-read moved, by the state it reached. Synchronous, never throws. */
|
|
523
|
+
recordSignatureRequestMoved(params) {
|
|
524
|
+
this.metricsDefinitions.signatureRequestMovedTotal.add(1, { provider: params.providerRef, to: params.to });
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* #2293 — a request the vendor reported complete that stayed open, or failed, on its evidence, by
|
|
528
|
+
* `SignatureRequestEvidenceFailure`. Synchronous, never throws.
|
|
529
|
+
*/
|
|
530
|
+
recordSignatureRequestEvidenceRefused(params) {
|
|
531
|
+
this.metricsDefinitions.signatureRequestEvidenceRefusedTotal.add(1, { provider: params.providerRef, failure: params.failure });
|
|
532
|
+
}
|
|
533
|
+
/** #2293 — a re-read the vendor did not answer usably. Synchronous, never throws. */
|
|
534
|
+
recordSignatureRequestVendorNotRead(params) {
|
|
535
|
+
this.metricsDefinitions.signatureRequestVendorNotReadTotal.add(1, { provider: params.providerRef });
|
|
536
|
+
}
|
|
537
|
+
/** #2293 — one link of a SIGNED request's evidence file, by `SignatureRequestEvidenceLinkOutcome`. Synchronous, never throws. */
|
|
538
|
+
recordSignatureRequestEvidenceLink(params) {
|
|
539
|
+
this.metricsDefinitions.signatureRequestEvidenceLinkTotal.add(1, { outcome: params.outcome });
|
|
540
|
+
}
|
|
492
541
|
/** #2891 — a key version found signing past its purpose's cryptoperiod (reported once per version). Synchronous, never throws. */
|
|
493
542
|
recordKeyManagementRotationDue(params) {
|
|
494
543
|
this.metricsDefinitions.keyManagementRotationDueTotal.add(1, { purpose: params.purpose });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.service.js","sourceRoot":"","sources":["../../../../../src/monitoring/observability/services/metrics.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { metrics, Meter } from '@opentelemetry/api';\nimport { injectable } from 'inversify';\nimport type { ApprovalSealStatus, AuthScopeType, CryptoKey_Purpose, CryptoKey_SignatureOutcome, CryptoKey_SignatureRefusal } from '@wildo-ai/saas-models';\nimport type { SubmissionChallengeRefusalReason } from '~wildo-backend-lib/security/submission-challenge/submission-challenge.backend.service';\nimport type {\n CspViolationDisposition,\n CspViolationReportDelivery,\n CspViolationReportedDirective,\n} from '~wildo-backend-lib/monitoring/csp-violation-reports/csp-violation-reports.backend.utils';\nimport { MetricDefinitions } from '~wildo-backend-lib/monitoring/observability/models/observability.backend.schemas';\n\n/**\n * Records the operator-facing metrics that have LIVE producers — the\n * data-seeding counters (dispatcher engines + shared ledger writers) and the\n * M2M outbound-webhook counter (delivery batch worker). All instruments are\n * created on the global meter, which the OTLP preload (`otel-preload.ts`) wires\n * to the OTLP metric exporter; with no preload the global meter is a no-op, so\n * recording is silently inert (never throws). The former HTTP/DB/auth/etc.\n * `record*` helpers were removed in Slice 2 Phase 3 — their only caller was the\n * dead observability middleware, and HTTP metrics now come from the preload's\n * auto-instrumentation (bounded, semconv) instead of unbounded org/user labels.\n */\n@injectable()\nexport class MetricsService {\n private meter: Meter;\n private metricsDefinitions: MetricDefinitions;\n\n constructor() {\n this.meter = metrics.getMeter('wildo-saas-metrics', '1.0.0');\n this.initializeMetrics();\n }\n\n private initializeMetrics(): void {\n this.metricsDefinitions = {\n // ---------------------------------------------------------------------\n // Data Seeding (Phase 6.D / F-17 — Prom-style operator metrics)\n // ---------------------------------------------------------------------\n // The data-seeding dispatcher exposes four observable concerns:\n // - LAZY C1 cache hit-rate (first-access bootstrap short-circuit\n // effectiveness on the hot path),\n // - LAZY thunder-herd bow-outs (concurrent first-access races\n // resolved silently, distinguishing the \"winner already done\"\n // vs \"winner still running\" branches),\n // - DataSeedRun terminal totals (every COMPLETED / PARTIAL / FAILED\n // ledger transition, per seed × mode × trigger origin — the\n // metric covers ALL engines, current and future, because it is\n // fired from the shared lifecycle writers).\n // Counter names follow the Prometheus convention `_total` suffix; the\n // OpenTelemetry meter is the existing `wildo-saas-metrics` meter, so\n // the counters export via the OTLP metric reader configured in the\n // preload without any extra wiring.\n dataSeedingLazyC1CacheHits: this.meter.createCounter('data_seeding_lazy_c1_cache_hits_total', {\n description: 'LAZY engine C1 idempotency-probe cache hits (already-completed scope, skipped without entry resolution)',\n }),\n\n dataSeedingLazyC1CacheMisses: this.meter.createCounter('data_seeding_lazy_c1_cache_misses_total', {\n description: 'LAZY engine C1 idempotency-probe cache misses (cold-start, run-slot acquisition proceeds)',\n }),\n\n dataSeedingThunderHerdBowouts: this.meter.createCounter('data_seeding_thunder_herd_bowouts_total', {\n description: 'LAZY engine concurrent-first-access races where the slot acquisition lost and the caller bowed out silently',\n }),\n\n dataSeedingRunTotal: this.meter.createCounter('data_seeding_run_total', {\n description: 'DataSeedRun terminal-state writes (COMPLETED / PARTIAL / FAILED) across all dispatcher engines',\n }),\n\n dataSeedingAdminListSeedsDuration: this.meter.createHistogram('data_seeding_admin_list_seeds_duration_ms', {\n description: 'Wall-clock duration of GET /internal/admin/data-seeding/seeds (N+1 lastRun lookup) in milliseconds',\n }),\n\n // ─── M2M Outbound Webhook Delivery (Phase 5 / Step 17) ────\n // One counter covering every worker `doHandle` return — the\n // outcome enum maps 1:1 to the five `M2MWebhookDeliveryBatchOutput.outcome`\n // values (`delivered`, `retry_scheduled`, `failed_terminal`,\n // `skipped_missing_row`, `skipped_already_leased`). Operators\n // answer \"is webhook delivery healthy?\" with\n // rate(m2m_webhook_delivery_total{outcome=\"delivered\"}[5m])\n // / rate(m2m_webhook_delivery_total[5m])\n // Cardinality: 2 `scope` × 5 `outcome` = 10 active series.\n m2mWebhookDeliveryTotal: this.meter.createCounter('m2m_webhook_delivery_total', {\n description: 'M2M outbound webhook delivery terminal / intermediate outcomes (one per worker run)',\n }),\n\n // ─── Compliance Audit-Log Sink Failures (Phase 5 / F6) ────\n // A Layer-2 provider audit sink threw while recording an event. The\n // composite (`CompositeAuditLogSink`) isolates the failure so the business\n // op is unaffected, but a silently-failing audit sink (\"we think we're\n // auditing but we aren't\") must not go unnoticed — this counter makes it\n // observable. Operators alert on\n // rate(audit_sink_failure_total[5m]) > 0\n // Cardinality: one series per declared audit `provider` (immudb, SIEM, …).\n auditSinkFailureTotal: this.meter.createCounter('audit_sink_failure_total', {\n description: 'Compliance audit-log provider sink failures (one per sink throw during event fan-out)',\n }),\n\n // ─── Compliance Audit-Log TAMPER detections ────\n // A tamper-evident audit provider (immudb) PROVED, via its cryptographic\n // durable-state consistency proof, that its store was rolled back / tampered\n // between restarts. DISTINCT from `audit_sink_failure_total`: a transient\n // write miss is backfilled by the reconciler and needs no human, whereas a\n // proven rollback of the audit ledger is a compliance incident. Operators\n // page on\n // increase(audit_tamper_detected_total[1h]) > 0\n // Cardinality: one series per declared audit `provider`.\n auditTamperDetectedTotal: this.meter.createCounter('audit_tamper_detected_total', {\n description: 'Compliance audit-log store tamper/rollback detections (durable-state consistency-proof failures)',\n }),\n\n // ─── Compliance Audit-Log assurance DEGRADATIONS ────\n // A tamper-evident audit provider dropped from FULL cross-restart tamper-evidence to a WEAKER\n // assurance level — ephemeral mode (no durable anchor), a corrupt/unreadable anchor, an un-pinned\n // server-identity change, or a per-op proof failure. DISTINCT from `audit_tamper_detected_total`\n // (a PROVEN rollback → page) and `audit_sink_failure_total` (a write hiccup): a degradation means\n // \"we may not detect a future tamper\" — it should be alerted so the guarantee never lapses silently.\n // Operators alert on\n // increase(audit_integrity_assurance_degraded_total{reason=\"ephemeral\"}[1h]) > 0\n // Cardinality: one series per (provider, reason) — `reason` is a small fixed slug set.\n auditIntegrityAssuranceDegradedTotal: this.meter.createCounter('audit_integrity_assurance_degraded_total', {\n description:\n 'Compliance audit-log assurance degradations (ephemeral / corrupt-anchor / identity-change / per-op proof failure)',\n }),\n\n // ─── Compliance Audit-Log LAYER-1 (authoritative DB store) write failures ────\n // The always-on Layer-1 database audit store (`AuditLogsBackendService._createAuditLog`) threw\n // while writing the authoritative row. DISTINCT from `audit_sink_failure_total` (a Layer-2\n // provider sink — immudb/SIEM — hiccup, backfilled by the reconciler): a Layer-1 failure means\n // the PRIMARY, authoritative audit record itself was NOT persisted — the most severe \"we think\n // we're auditing but we aren't\" state. Emission is fire-and-forget (audit must never break the\n // business op), so without this counter the outage is invisible past a swallowed warn line.\n // Operators alert on\n // rate(audit_store_failure_total[5m]) > 0\n // Cardinality: ONE label-free series (the authoritative store has no provider dimension).\n auditStoreFailureTotal: this.meter.createCounter('audit_store_failure_total', {\n description: 'Compliance audit-log Layer-1 authoritative DB store write failures (one per _createAuditLog persist throw)',\n }),\n\n // ─── Security audit observations DROPPED before the pipeline saw them ────\n // A fire-and-forget security observation (an operator tenant crossing, an authorization\n // refusal, a platform-access grant transition) never reached `AuditLogsBackendService` at all:\n // the service was unbound or its `log*` method absent, the call threw synchronously, or the\n // returned promise rejected. DISTINCT from `audit_store_failure_total`, which fires INSIDE\n // `_createAuditLog` and therefore only sees emissions that got that far. The two overlap only where\n // the audit method records with `SURFACE_TO_CALLER` (the system-context read, the pipeline reset's\n // attempt row): a store refusal there rejects the promise, so both count it (as `emission_timed_out`\n // when the caller had already stopped waiting). Every other drop counted here, a late-landing\n // timeout aside, is one it structurally cannot see. Fire-and-forget is deliberate and\n // stays (an observation must never fail the request it observes), so without this counter the\n // loss is completely silent and \"no operator crossings this week\" is indistinguishable from\n // \"the audit service has been unbound since Tuesday\". Operators alert on\n // increase(audit_observation_dropped_total[15m]) > 0\n // Cardinality: `AuditObservationKind` × `AuditObservationLossReason`, both closed enums (count them; do not quote\n // a number here). An `emission_timed_out` drop may still land in the store later: it is a confirmation that\n // did not arrive in time (#2088), so an alert on this counter can fire for a row that then appears.\n auditObservationDroppedTotal: this.meter.createCounter('audit_observation_dropped_total', {\n description:\n 'Security audit observations dropped before reaching the audit pipeline (service unavailable / emission threw / emission rejected / emission timed out, which may still land)',\n }),\n // Key management (#2891): the platform custodian's signing proxy, and an application's copy of its seal keys.\n keyManagementSignatureDurationMs: this.meter.createHistogram('key_management_signature_duration_ms', {\n description: 'Time the signing proxy took to answer a signature request, by purpose and outcome (issued, replayed, refused, error)',\n unit: 'ms',\n }),\n keyManagementSignatureRefusedTotal: this.meter.createCounter('key_management_signature_refused_total', {\n description: 'Signature requests the custodian refused, by purpose and refusal; verify_after_sign_failed is a provider fault to page on',\n }),\n keyManagementVerificationKeysRefreshFailureTotal: this.meter.createCounter('key_management_verification_keys_refresh_failure_total', {\n description: 'Failed refreshes of an application\\'s published verification keys from the custodian (the stored keys are served meanwhile)',\n }),\n keyManagementRotationDueTotal: this.meter.createCounter('key_management_rotation_due_total', {\n description: 'Key versions found signing past their purpose\\'s cryptoperiod, by purpose, once per version: rotate with `wildo keys rotate`',\n }),\n // #2903 — approval seals, by the application's relay. Alert on a DEAD seal (a decision with no verifiable record until\n // an operator re-drives it) and on an unsealed seal growing old (the custodian unreachable). The age is set by each\n // relay run and the gauge keeps the last one, so it does NOT see a relay that stopped running (review F5): that is\n // the `approval-seal-relay` batch's own schedule to watch.\n // increase(approval_seal_settled_total{status=\"dead\"}[15m]) > 0\n // approval_seal_oldest_unsealed_age_seconds > 3600\n approvalSealSettledTotal: this.meter.createCounter('approval_seal_settled_total', {\n description: 'Approval seals the relay settled, by status (sealed, pending: retried after a refusal, dead) and refusal',\n }),\n approvalSealLagSeconds: this.meter.createHistogram('approval_seal_lag_seconds', {\n description: 'Seconds from a person\\'s decision to its seal\\'s signature',\n unit: 's',\n }),\n approvalSealOldestUnsealedAgeSeconds: this.meter.createObservableGauge('approval_seal_oldest_unsealed_age_seconds', {\n description: 'Age of the oldest approval seal the last relay run left unsealed (0 when none): the relay\\'s backlog',\n unit: 's',\n }),\n // #1735 — a public form's submissions refused at their challenge. A sudden rise is a bot wave; a steady\n // `vendor_refused_secret` or `provider_verifier_unavailable` is a DEPLOYMENT fault (every real visitor is being\n // turned away), which is why those two are worth an alert of their own:\n // increase(submission_challenge_refused_total{reason=~\"vendor_refused_secret|provider_verifier_unavailable\"}[15m]) > 0\n submissionChallengeRefusedTotal: this.meter.createCounter('submission_challenge_refused_total', {\n description: 'Public submissions refused at their captcha or proof-of-work challenge, by reason',\n }),\n // #2867 — Content-Security-Policy violations browsers reported, by the directive that refused (or, under a\n // report-only policy, would have refused) and by disposition. A policy that is wrong for the product shows here as\n // a steady rate on one directive; flip a surface from report-only to enforcing only once its `report` series is\n // understood:\n // sum by (effective_directive) (rate(csp_violation_reports_total{disposition=\"report\"}[1h]))\n // Every label is a closed enum (`CspViolationReportedDirective` × `CspViolationDisposition` ×\n // `CspViolationReportDelivery`), so a forged report cannot mint a series.\n cspViolationReportsTotal: this.meter.createCounter('csp_violation_reports_total', {\n description: 'Content-Security-Policy violations reported by browsers, by effective directive, disposition and delivery',\n }),\n };\n }\n\n // ---------------------------------------------------------------------------\n // Data Seeding metrics (Phase 6.D / F-17)\n // ---------------------------------------------------------------------------\n // Typed wrappers around the four data-seeding counters so the dispatcher\n // never reaches into the raw OpenTelemetry meter and so all label keys\n // stay consistent (snake_case to match Prometheus convention; the\n // dispatcher passes already-stringified enum values).\n // ---------------------------------------------------------------------------\n\n /**\n * LAZY engine — C1 idempotency-probe cache hit. Fired once per\n * (seed × scope) when `runLazy` short-circuits because a prior\n * COMPLETED `DataSeedRun` row already covers the scope.\n */\n public recordDataSeedingLazyCacheHit(params: { seedKey: string; scopeKind: string }): void {\n this.metricsDefinitions.dataSeedingLazyC1CacheHits.add(1, {\n seed_key: params.seedKey,\n scope_kind: params.scopeKind,\n });\n }\n\n /**\n * LAZY engine — C1 idempotency-probe cache miss. Fired once per\n * (seed × scope) when `runLazy` proceeds past the C1 probe and\n * attempts to acquire a run-slot.\n */\n public recordDataSeedingLazyCacheMiss(params: { seedKey: string; scopeKind: string }): void {\n this.metricsDefinitions.dataSeedingLazyC1CacheMisses.add(1, {\n seed_key: params.seedKey,\n scope_kind: params.scopeKind,\n });\n }\n\n /**\n * LAZY engine — concurrent first-access race resolved by silent\n * bow-out. `reason` mirrors the dispatcher's\n * `acquireLazyRunSlotWithRaceGuard` outcome:\n * - `concurrent-completed` — a winning concurrent caller already\n * wrote a COMPLETED row (data is there);\n * - `concurrent-running` — a winning concurrent caller currently\n * owns the RUNNING slot (data is being written).\n */\n public recordDataSeedingThunderHerdBowout(params: {\n seedKey: string;\n scopeKind: string;\n reason: 'concurrent-completed' | 'concurrent-running';\n }): void {\n this.metricsDefinitions.dataSeedingThunderHerdBowouts.add(1, {\n seed_key: params.seedKey,\n scope_kind: params.scopeKind,\n reason: params.reason,\n });\n }\n\n /**\n * Terminal `DataSeedRun` write — fired exactly once per row\n * transition into COMPLETED / PARTIAL / FAILED. The metric is\n * emitted from the shared lifecycle writers\n * (`completeDataSeedRun` / `failDataSeedRun` /\n * `writeFreshFailedDataSeedRun`) so every dispatcher engine —\n * Level-A application lifecycle, Level-B resource lifecycle, LAZY\n * first-access, MANUAL re-runs, and the deferred Phase-7 cron —\n * contributes uniformly without per-engine wiring.\n *\n * `mode`, `status`, `triggerOrigin`, and `scopeKind` are passed as\n * raw enum string values (the dispatcher does the `.toString()`) so\n * this service stays decoupled from the data-seeding domain enums.\n *\n * Phase 5/6 audit H-2 — `scope_kind` was added to align with the\n * sibling LAZY-engine counters (hit / miss / bow-out) which all\n * carry it. Without `scope_kind`, operators cannot answer\n * \"are my org-scoped seeds healthier than my user-scoped seeds?\",\n * and the deferred Phase-7 cron-scheduler dashboard cannot slice\n * terminal-run health by scope at all (terminal counts are the\n * only signal SYNC / ADDITIVE / UPGRADE seeds emit). Cardinality\n * stays bounded: 5 `DataSeedScopeKind` values × ~200 seeds × 4\n * modes × 4 statuses × ~6 trigger origins ≈ 96K series upper\n * bound; in practice <1K active series.\n */\n public recordDataSeedingRun(params: {\n seedKey: string;\n mode: string;\n status: string;\n triggerOrigin: string;\n scopeKind: string;\n }): void {\n this.metricsDefinitions.dataSeedingRunTotal.add(1, {\n seed_key: params.seedKey,\n mode: params.mode,\n status: params.status,\n trigger_origin: params.triggerOrigin,\n scope_kind: params.scopeKind,\n });\n }\n\n /**\n * Wall-clock duration of the admin `GET /internal/admin/data-seeding/seeds`\n * endpoint in milliseconds. Recorded in the controller around the full\n * registry walk (which fans out N `lastRun` lookups, one per seed).\n *\n * Phase 5/6 audit L-4 — needed because the endpoint is N+1 by design\n * (single registry-wide aggregate would couple the surface to the\n * adapter's grammar; see the controller's `lookupLastRunSummary` JSDoc).\n * The histogram lets operators spot when the seed registry crosses the\n * \"switch to bulk aggregation\" threshold and surface it as a Phase-7\n * dashboard SLO alert.\n *\n * `seedCount` is bucketed coarsely (0, 1-10, 11-50, 51-200, 201+) so\n * label cardinality stays bounded across deployments with widely\n * different seed counts.\n */\n public recordDataSeedingAdminListSeedsDuration(params: {\n durationMs: number;\n seedCount: number;\n }): void {\n const bucket = (() => {\n if (params.seedCount <= 0) return '0';\n if (params.seedCount <= 10) return '1-10';\n if (params.seedCount <= 50) return '11-50';\n if (params.seedCount <= 200) return '51-200';\n return '201+';\n })();\n this.metricsDefinitions.dataSeedingAdminListSeedsDuration.record(params.durationMs, {\n seed_count_bucket: bucket,\n });\n }\n\n // ---------------------------------------------------------------------------\n // M2M Outbound Webhook Delivery metrics\n // ---------------------------------------------------------------------------\n // Typed wrapper around the single `m2m_webhook_delivery_total` counter so\n // worker call sites never reach into the raw OpenTelemetry meter and so\n // label keys (`scope` / `outcome`) stay consistent. The `scope` parameter\n // is locked to the `AuthScopeType` enum (`'organization' | 'application'`)\n // — passing a typo or a stale string fails type-check rather than silently\n // creating a parallel time series — and `outcome` maps 1:1 to\n // `M2MWebhookDeliveryBatchOutput.outcome`.\n //\n // Firing contract:\n // - Exactly ONCE per worker invocation, at each terminal / intermediate\n // return-point in `m2mWebhookDeliveryBatchService.doHandle`.\n // - NOT fired from the dispatcher's skip paths (feature off / config\n // off / no endpoints) — those never create a delivery row and never\n // emit outbound HTTP, so they are not webhook deliveries by\n // definition.\n // ---------------------------------------------------------------------------\n\n /**\n * M2M Outbound Webhook Delivery outcome counter.\n *\n * @param params.scope - `AuthScopeType.ORGANIZATION` (`'organization'`)\n * or `AuthScopeType.APPLICATION` (`'application'`). Locked to the\n * shared `AuthScopeType` enum so a typo or stale literal fails\n * type-check rather than silently creating a parallel time series\n * under a divergent label.\n * @param params.outcome - One of the five\n * `M2MWebhookDeliveryBatchOutput.outcome` values. `delivered` and\n * `failed_terminal` are terminal; `retry_scheduled` is the\n * intermediate retry branch; `skipped_missing_row` /\n * `skipped_already_leased` cover the two skip branches that still\n * consumed a worker slot.\n */\n public recordM2MWebhookDeliveryOutcome(params: {\n scope: AuthScopeType;\n outcome:\n | 'delivered'\n | 'retry_scheduled'\n | 'failed_terminal'\n | 'skipped_missing_row'\n | 'skipped_already_leased';\n }): void {\n this.metricsDefinitions.m2mWebhookDeliveryTotal.add(1, {\n scope: params.scope,\n outcome: params.outcome,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Compliance Audit-Log Sink failures (Phase 5 / F6)\n // ---------------------------------------------------------------------------\n\n /**\n * F6 (audit Phase 5) — a Layer-2 provider audit sink threw while recording an\n * event. Fired by `CompositeAuditLogSink` in its per-sink catch, so an\n * otherwise-swallowed sink failure is OBSERVABLE (→ alert). Synchronous, never\n * throws (the global meter is a no-op without the OTLP preload).\n *\n * @param params.providerRef - The declared audit provider whose sink failed\n * (immudb, a SIEM webhook, …) — the stable, low-cardinality series label.\n */\n public recordAuditSinkFailure(params: { providerRef: string }): void {\n this.metricsDefinitions.auditSinkFailureTotal.add(1, {\n provider: params.providerRef,\n });\n }\n\n /**\n * A tamper-evident audit provider PROVED its store was rolled back / tampered between restarts\n * (its durable-state cryptographic consistency proof failed). Fired by `CompositeAuditLogSink`\n * via the `onIntegrityViolation` hook it threads into the provider sink factory (the sink cannot\n * import this service across the dependency wall). DISTINCT from {@link recordAuditSinkFailure}:\n * this is a compliance incident (page a human), not a backfillable transient miss. Synchronous,\n * never throws (the global meter is a no-op without the OTLP preload).\n *\n * @param params.providerRef - The audit provider whose store proved tampered (immudb, …).\n */\n public recordAuditTamperDetected(params: { providerRef: string }): void {\n this.metricsDefinitions.auditTamperDetectedTotal.add(1, {\n provider: params.providerRef,\n });\n }\n\n /**\n * A tamper-evident audit provider DEGRADED from full cross-restart tamper-evidence to a weaker\n * assurance level (ephemeral mode, a corrupt anchor, an un-pinned server-identity change, or a per-op\n * proof failure). Fired by `CompositeAuditLogSink` via the `onAssuranceDegraded` hook it threads into\n * the provider sink factory. DISTINCT from {@link recordAuditTamperDetected}: a degradation is not a\n * proven tamper, but it means a future tamper may go UNDETECTED — alertable so the guarantee never\n * lapses silently. Non-latching. Synchronous, never throws.\n *\n * @param params.providerRef - The audit provider that degraded (immudb, …).\n * @param params.reason - Stable snake_case slug (`ephemeral`, `anchor_corrupt`, `anchor_identity_change`, `proof_failure_transient`).\n */\n public recordAuditIntegrityAssuranceDegraded(params: { providerRef: string; reason: string }): void {\n this.metricsDefinitions.auditIntegrityAssuranceDegradedTotal.add(1, {\n provider: params.providerRef,\n reason: params.reason,\n });\n }\n\n /**\n * The Layer-1 authoritative DB audit store threw while persisting an event. Fired by\n * `AuditLogsBackendService._createAuditLog` in its Layer-1 catch, so the \"the primary audit record\n * itself did not persist\" outage is OBSERVABLE (→ alert) rather than a swallowed warn line on a\n * fire-and-forget path. DISTINCT from {@link recordAuditSinkFailure}: that is a Layer-2 provider sink\n * (immudb/SIEM) hiccup the reconciler backfills; THIS is the authoritative store failing. Synchronous,\n * never throws (the global meter is a no-op without the OTLP preload). Label-free — the authoritative\n * store has no provider dimension. Alert on `rate(audit_store_failure_total[5m]) > 0`.\n */\n public recordAuditStoreFailure(): void {\n this.metricsDefinitions.auditStoreFailureTotal.add(1);\n }\n\n /**\n * A fire-and-forget security audit observation was DROPPED before it reached the audit pipeline.\n * Fired by the shared emission seam (`audit-observation-emission.backend.ts`), which every such\n * observation routes through, so a new observation is counted the day it lands.\n *\n * DISTINCT from {@link recordAuditStoreFailure}, and the distinction is the reason this counter\n * exists: that one fires INSIDE `_createAuditLog`, so it only ever sees an emission that reached\n * the audit service. The shapes counted here — an unbound service or absent `log*` method, a synchronous\n * throw, a rejected promise — were previously invisible. A rejected promise is also a store refusal\n * when the audit method records with `SURFACE_TO_CALLER` (the system-context read, the pipeline reset's\n * `attempted` row, #2088): BOTH counters see that one. The fourth shape, an awaited emission its caller\n * stopped waiting for (`emission_timed_out`), may still land.\n * Merging them into one counter would let a total wiring outage hide behind a store hiccup.\n *\n * Synchronous, never throws (the global meter is a no-op without the OTLP preload — which is why\n * the seam ALSO logs, at a throttled `error`).\n *\n * @param params.observation - `AuditObservationKind` member — WHICH security event was lost.\n * @param params.reason - `AuditObservationLossReason` member — WHICH loss shape.\n */\n public recordAuditObservationDropped(params: { observation: string; reason: string }): void {\n this.metricsDefinitions.auditObservationDroppedTotal.add(1, {\n observation: params.observation,\n reason: params.reason,\n });\n }\n\n /**\n * #1735 — one public submission refused at its challenge. Synchronous, never throws.\n *\n * @param params.reason - why it was refused; the enum keeps the metric's label set bounded.\n */\n public recordSubmissionChallengeRefused(params: { reason: SubmissionChallengeRefusalReason }): void {\n this.metricsDefinitions.submissionChallengeRefusedTotal.add(1, { reason: params.reason });\n }\n\n /**\n * #2867 — one Content-Security-Policy violation a browser reported. Synchronous, never throws.\n *\n * @param params.effectiveDirective - the directive that refused, mapped onto a closed vocabulary.\n * @param params.disposition - `enforce` (blocked) or `report` (a report-only policy).\n * @param params.delivery - `report_uri` or `report_to`, which tells an operator what the visitors' browsers implement.\n */\n public recordCspViolationReport(params: {\n effectiveDirective: CspViolationReportedDirective;\n disposition: CspViolationDisposition;\n delivery: CspViolationReportDelivery;\n }): void {\n this.metricsDefinitions.cspViolationReportsTotal.add(1, {\n effective_directive: params.effectiveDirective,\n disposition: params.disposition,\n delivery: params.delivery,\n });\n }\n\n /**\n * #2891 — one signature request the custodian answered, how long it took and how it ended. Synchronous, never throws.\n *\n * @param params.outcome - issued, replayed (the stored signature returned for a retry), refused, or error (a failure that is not a refusal).\n */\n public recordKeyManagementSignature(params: { purpose: CryptoKey_Purpose | null; outcome: CryptoKey_SignatureOutcome; durationMs: number }): void {\n this.metricsDefinitions.keyManagementSignatureDurationMs.record(params.durationMs, { purpose: params.purpose ?? 'unreadable', outcome: params.outcome });\n }\n\n /**\n * #2891 — a refused signature request, by its `CryptoKey_SignatureRefusal`. `verify_after_sign_failed` means a provider\n * returned a signature that does not verify under the key it was asked to use: alert on it. Synchronous, never throws.\n */\n public recordKeyManagementSignatureRefused(params: { purpose: CryptoKey_Purpose | null; refusal: CryptoKey_SignatureRefusal }): void {\n // A request refused before its body could be read has no purpose: its label says so rather than inventing one.\n this.metricsDefinitions.keyManagementSignatureRefusedTotal.add(1, { purpose: params.purpose ?? 'unreadable', refusal: params.refusal });\n }\n\n /** #2891 — an application failed to refresh its published verification keys from the custodian. Synchronous, never throws. */\n public recordKeyManagementVerificationKeysRefreshFailure(): void {\n this.metricsDefinitions.keyManagementVerificationKeysRefreshFailureTotal.add(1);\n }\n\n /** #2903 — an approval seal the relay settled: sealed (with its lag), retried after a refusal, or dead. Synchronous, never throws. */\n public recordApprovalSealSettled(params: { status: ApprovalSealStatus; refusal?: CryptoKey_SignatureRefusal; lagSeconds?: number }): void {\n this.metricsDefinitions.approvalSealSettledTotal.add(1, { status: params.status, refusal: params.refusal ?? 'none' });\n if (params.lagSeconds !== undefined) this.metricsDefinitions.approvalSealLagSeconds.record(params.lagSeconds);\n }\n\n /** The age the last relay run left its oldest unsealed seal at, observed by the gauge on every collection. */\n private approvalSealOldestUnsealedAge = 0;\n private approvalSealOldestUnsealedAgeObserved = false;\n\n /** #2903 — the age of the oldest seal a relay run left unsealed (0 when none). Synchronous, never throws. */\n public recordApprovalSealOldestUnsealedAge(ageSeconds: number): void {\n this.approvalSealOldestUnsealedAge = ageSeconds;\n if (this.approvalSealOldestUnsealedAgeObserved) return;\n this.approvalSealOldestUnsealedAgeObserved = true;\n this.metricsDefinitions.approvalSealOldestUnsealedAgeSeconds.addCallback((result: { observe: (value: number) => void }) => result.observe(this.approvalSealOldestUnsealedAge));\n }\n\n /** #2891 — a key version found signing past its purpose's cryptoperiod (reported once per version). Synchronous, never throws. */\n public recordKeyManagementRotationDue(params: { purpose: CryptoKey_Purpose }): void {\n this.metricsDefinitions.keyManagementRotationDueTotal.add(1, { purpose: params.purpose });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"metrics.service.js","sourceRoot":"","sources":["../../../../../src/monitoring/observability/services/metrics.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { metrics, Meter } from '@opentelemetry/api';\nimport { injectable } from 'inversify';\nimport type { ApprovalSealStatus, AuthScopeType, CryptoKey_Purpose, CryptoKey_SignatureOutcome, CryptoKey_SignatureRefusal, SignatureRequest_State } from '@wildo-ai/saas-models';\nimport type { ElectronicSignature_Level } from '@wildo-ai/external-connectors-models';\nimport type { SignatureRequestEvidenceFailure, SignatureRequestSendRefusal } from '~wildo-backend-lib/compliance/electronic-signatures/signature-requests.backend.service';\nimport type { SignatureRequestEvidenceLinkOutcome } from '~wildo-backend-lib/compliance/electronic-signatures/signature-request-evidence-files.backend';\nimport type { ElectronicSignatureSendOutcome } from '~wildo-backend-lib/external-providers/services/electronic-signature.backend.service';\nimport type { SubmissionChallengeRefusalReason } from '~wildo-backend-lib/security/submission-challenge/submission-challenge.backend.service';\nimport type {\n CspViolationDisposition,\n CspViolationReportDelivery,\n CspViolationReportedDirective,\n} from '~wildo-backend-lib/monitoring/csp-violation-reports/csp-violation-reports.backend.utils';\nimport { MetricDefinitions } from '~wildo-backend-lib/monitoring/observability/models/observability.backend.schemas';\n\n/**\n * Records the operator-facing metrics that have LIVE producers — the\n * data-seeding counters (dispatcher engines + shared ledger writers) and the\n * M2M outbound-webhook counter (delivery batch worker). All instruments are\n * created on the global meter, which the OTLP preload (`otel-preload.ts`) wires\n * to the OTLP metric exporter; with no preload the global meter is a no-op, so\n * recording is silently inert (never throws). The former HTTP/DB/auth/etc.\n * `record*` helpers were removed in Slice 2 Phase 3 — their only caller was the\n * dead observability middleware, and HTTP metrics now come from the preload's\n * auto-instrumentation (bounded, semconv) instead of unbounded org/user labels.\n */\n@injectable()\nexport class MetricsService {\n private meter: Meter;\n private metricsDefinitions: MetricDefinitions;\n\n constructor() {\n this.meter = metrics.getMeter('wildo-saas-metrics', '1.0.0');\n this.initializeMetrics();\n }\n\n private initializeMetrics(): void {\n this.metricsDefinitions = {\n // ---------------------------------------------------------------------\n // Data Seeding (Phase 6.D / F-17 — Prom-style operator metrics)\n // ---------------------------------------------------------------------\n // The data-seeding dispatcher exposes four observable concerns:\n // - LAZY C1 cache hit-rate (first-access bootstrap short-circuit\n // effectiveness on the hot path),\n // - LAZY thunder-herd bow-outs (concurrent first-access races\n // resolved silently, distinguishing the \"winner already done\"\n // vs \"winner still running\" branches),\n // - DataSeedRun terminal totals (every COMPLETED / PARTIAL / FAILED\n // ledger transition, per seed × mode × trigger origin — the\n // metric covers ALL engines, current and future, because it is\n // fired from the shared lifecycle writers).\n // Counter names follow the Prometheus convention `_total` suffix; the\n // OpenTelemetry meter is the existing `wildo-saas-metrics` meter, so\n // the counters export via the OTLP metric reader configured in the\n // preload without any extra wiring.\n dataSeedingLazyC1CacheHits: this.meter.createCounter('data_seeding_lazy_c1_cache_hits_total', {\n description: 'LAZY engine C1 idempotency-probe cache hits (already-completed scope, skipped without entry resolution)',\n }),\n\n dataSeedingLazyC1CacheMisses: this.meter.createCounter('data_seeding_lazy_c1_cache_misses_total', {\n description: 'LAZY engine C1 idempotency-probe cache misses (cold-start, run-slot acquisition proceeds)',\n }),\n\n dataSeedingThunderHerdBowouts: this.meter.createCounter('data_seeding_thunder_herd_bowouts_total', {\n description: 'LAZY engine concurrent-first-access races where the slot acquisition lost and the caller bowed out silently',\n }),\n\n dataSeedingRunTotal: this.meter.createCounter('data_seeding_run_total', {\n description: 'DataSeedRun terminal-state writes (COMPLETED / PARTIAL / FAILED) across all dispatcher engines',\n }),\n\n dataSeedingAdminListSeedsDuration: this.meter.createHistogram('data_seeding_admin_list_seeds_duration_ms', {\n description: 'Wall-clock duration of GET /internal/admin/data-seeding/seeds (N+1 lastRun lookup) in milliseconds',\n }),\n\n // ─── M2M Outbound Webhook Delivery (Phase 5 / Step 17) ────\n // One counter covering every worker `doHandle` return — the\n // outcome enum maps 1:1 to the five `M2MWebhookDeliveryBatchOutput.outcome`\n // values (`delivered`, `retry_scheduled`, `failed_terminal`,\n // `skipped_missing_row`, `skipped_already_leased`). Operators\n // answer \"is webhook delivery healthy?\" with\n // rate(m2m_webhook_delivery_total{outcome=\"delivered\"}[5m])\n // / rate(m2m_webhook_delivery_total[5m])\n // Cardinality: 2 `scope` × 5 `outcome` = 10 active series.\n m2mWebhookDeliveryTotal: this.meter.createCounter('m2m_webhook_delivery_total', {\n description: 'M2M outbound webhook delivery terminal / intermediate outcomes (one per worker run)',\n }),\n\n // ─── Compliance Audit-Log Sink Failures (Phase 5 / F6) ────\n // A Layer-2 provider audit sink threw while recording an event. The\n // composite (`CompositeAuditLogSink`) isolates the failure so the business\n // op is unaffected, but a silently-failing audit sink (\"we think we're\n // auditing but we aren't\") must not go unnoticed — this counter makes it\n // observable. Operators alert on\n // rate(audit_sink_failure_total[5m]) > 0\n // Cardinality: one series per declared audit `provider` (immudb, SIEM, …).\n auditSinkFailureTotal: this.meter.createCounter('audit_sink_failure_total', {\n description: 'Compliance audit-log provider sink failures (one per sink throw during event fan-out)',\n }),\n\n // ─── Compliance Audit-Log TAMPER detections ────\n // A tamper-evident audit provider (immudb) PROVED, via its cryptographic\n // durable-state consistency proof, that its store was rolled back / tampered\n // between restarts. DISTINCT from `audit_sink_failure_total`: a transient\n // write miss is backfilled by the reconciler and needs no human, whereas a\n // proven rollback of the audit ledger is a compliance incident. Operators\n // page on\n // increase(audit_tamper_detected_total[1h]) > 0\n // Cardinality: one series per declared audit `provider`.\n auditTamperDetectedTotal: this.meter.createCounter('audit_tamper_detected_total', {\n description: 'Compliance audit-log store tamper/rollback detections (durable-state consistency-proof failures)',\n }),\n\n // ─── Compliance Audit-Log assurance DEGRADATIONS ────\n // A tamper-evident audit provider dropped from FULL cross-restart tamper-evidence to a WEAKER\n // assurance level — ephemeral mode (no durable anchor), a corrupt/unreadable anchor, an un-pinned\n // server-identity change, or a per-op proof failure. DISTINCT from `audit_tamper_detected_total`\n // (a PROVEN rollback → page) and `audit_sink_failure_total` (a write hiccup): a degradation means\n // \"we may not detect a future tamper\" — it should be alerted so the guarantee never lapses silently.\n // Operators alert on\n // increase(audit_integrity_assurance_degraded_total{reason=\"ephemeral\"}[1h]) > 0\n // Cardinality: one series per (provider, reason) — `reason` is a small fixed slug set.\n auditIntegrityAssuranceDegradedTotal: this.meter.createCounter('audit_integrity_assurance_degraded_total', {\n description:\n 'Compliance audit-log assurance degradations (ephemeral / corrupt-anchor / identity-change / per-op proof failure)',\n }),\n\n // ─── Compliance Audit-Log LAYER-1 (authoritative DB store) write failures ────\n // The always-on Layer-1 database audit store (`AuditLogsBackendService._createAuditLog`) threw\n // while writing the authoritative row. DISTINCT from `audit_sink_failure_total` (a Layer-2\n // provider sink — immudb/SIEM — hiccup, backfilled by the reconciler): a Layer-1 failure means\n // the PRIMARY, authoritative audit record itself was NOT persisted — the most severe \"we think\n // we're auditing but we aren't\" state. Emission is fire-and-forget (audit must never break the\n // business op), so without this counter the outage is invisible past a swallowed warn line.\n // Operators alert on\n // rate(audit_store_failure_total[5m]) > 0\n // Cardinality: ONE label-free series (the authoritative store has no provider dimension).\n auditStoreFailureTotal: this.meter.createCounter('audit_store_failure_total', {\n description: 'Compliance audit-log Layer-1 authoritative DB store write failures (one per _createAuditLog persist throw)',\n }),\n\n // ─── Security audit observations DROPPED before the pipeline saw them ────\n // A fire-and-forget security observation (an operator tenant crossing, an authorization\n // refusal, a platform-access grant transition) never reached `AuditLogsBackendService` at all:\n // the service was unbound or its `log*` method absent, the call threw synchronously, or the\n // returned promise rejected. DISTINCT from `audit_store_failure_total`, which fires INSIDE\n // `_createAuditLog` and therefore only sees emissions that got that far. The two overlap only where\n // the audit method records with `SURFACE_TO_CALLER` (the system-context read, the pipeline reset's\n // attempt row): a store refusal there rejects the promise, so both count it (as `emission_timed_out`\n // when the caller had already stopped waiting). Every other drop counted here, a late-landing\n // timeout aside, is one it structurally cannot see. Fire-and-forget is deliberate and\n // stays (an observation must never fail the request it observes), so without this counter the\n // loss is completely silent and \"no operator crossings this week\" is indistinguishable from\n // \"the audit service has been unbound since Tuesday\". Operators alert on\n // increase(audit_observation_dropped_total[15m]) > 0\n // Cardinality: `AuditObservationKind` × `AuditObservationLossReason`, both closed enums (count them; do not quote\n // a number here). An `emission_timed_out` drop may still land in the store later: it is a confirmation that\n // did not arrive in time (#2088), so an alert on this counter can fire for a row that then appears.\n auditObservationDroppedTotal: this.meter.createCounter('audit_observation_dropped_total', {\n description:\n 'Security audit observations dropped before reaching the audit pipeline (service unavailable / emission threw / emission rejected / emission timed out, which may still land)',\n }),\n // Key management (#2891): the platform custodian's signing proxy, and an application's copy of its seal keys.\n keyManagementSignatureDurationMs: this.meter.createHistogram('key_management_signature_duration_ms', {\n description: 'Time the signing proxy took to answer a signature request, by purpose and outcome (issued, replayed, refused, error)',\n unit: 'ms',\n }),\n keyManagementSignatureRefusedTotal: this.meter.createCounter('key_management_signature_refused_total', {\n description: 'Signature requests the custodian refused, by purpose and refusal; verify_after_sign_failed is a provider fault to page on',\n }),\n keyManagementVerificationKeysRefreshFailureTotal: this.meter.createCounter('key_management_verification_keys_refresh_failure_total', {\n description: 'Failed refreshes of an application\\'s published verification keys from the custodian (the stored keys are served meanwhile)',\n }),\n keyManagementRotationDueTotal: this.meter.createCounter('key_management_rotation_due_total', {\n description: 'Key versions found signing past their purpose\\'s cryptoperiod, by purpose, once per version: rotate with `wildo keys rotate`',\n }),\n // #2903 — approval seals, by the application's relay. Alert on a DEAD seal (a decision with no verifiable record until\n // an operator re-drives it) and on an unsealed seal growing old (the custodian unreachable). The age is set by each\n // relay run and the gauge keeps the last one, so it does NOT see a relay that stopped running (review F5): that is\n // the `approval-seal-relay` batch's own schedule to watch.\n // increase(approval_seal_settled_total{status=\"dead\"}[15m]) > 0\n // approval_seal_oldest_unsealed_age_seconds > 3600\n approvalSealSettledTotal: this.meter.createCounter('approval_seal_settled_total', {\n description: 'Approval seals the relay settled, by status (sealed, pending: retried after a refusal, dead) and refusal',\n }),\n approvalSealLagSeconds: this.meter.createHistogram('approval_seal_lag_seconds', {\n description: 'Seconds from a person\\'s decision to its seal\\'s signature',\n unit: 's',\n }),\n approvalSealOldestUnsealedAgeSeconds: this.meter.createObservableGauge('approval_seal_oldest_unsealed_age_seconds', {\n description: 'Age of the oldest approval seal the last relay run left unsealed (0 when none): the relay\\'s backlog',\n unit: 's',\n }),\n // #2293 — electronic-signature requests (level 2). The audit rows record each request; these answer \"is signing\n // healthy?\" without reading them. Alert on:\n // increase(signature_request_sent_total{outcome!~\"sent|already_open\"}[1h]) > 0 a deliverable not sent\n // increase(signature_request_evidence_refused_total{failure!=\"rejected\"}[1h]) > 0 the engine cannot keep evidence\n // increase(signature_request_evidence_link_total{outcome=\"lost\"}[1h]) > 0 a SIGNED request's evidence lost\n // rate(signature_request_vendor_not_read_total[15m]) > 0, sustained a vendor down\n // A steady `failure=\"rejected\"` is a vendor whose documents do not validate (anchors, revocation, tampering), and\n // `failure=\"mismatched\"` a signer or level that can never be met. Labels: closed enums and the declared provider ref.\n signatureRequestSentTotal: this.meter.createCounter('signature_request_sent_total', {\n description: 'Deliverables sent for electronic signature, by outcome (sent, or the refusal) and required level',\n }),\n signatureRequestMovedTotal: this.meter.createCounter('signature_request_moved_total', {\n description: 'Signature requests moved by a re-read, by provider and the state reached',\n }),\n signatureRequestEvidenceRefusedTotal: this.meter.createCounter('signature_request_evidence_refused_total', {\n description: 'Requests a vendor reported complete whose evidence did not make them SIGNED, by provider and failure',\n }),\n signatureRequestVendorNotReadTotal: this.meter.createCounter('signature_request_vendor_not_read_total', {\n description: 'Re-reads of a signature request its vendor did not answer usably, by provider',\n }),\n signatureRequestEvidenceLinkTotal: this.meter.createCounter('signature_request_evidence_link_total', {\n description: 'Links of a SIGNED request\\'s evidence files, by outcome (lost: evidence a request names and nothing keeps)',\n }),\n // #1735 — a public form's submissions refused at their challenge. A sudden rise is a bot wave; a steady\n // `vendor_refused_secret` or `provider_verifier_unavailable` is a DEPLOYMENT fault (every real visitor is being\n // turned away), which is why those two are worth an alert of their own:\n // increase(submission_challenge_refused_total{reason=~\"vendor_refused_secret|provider_verifier_unavailable\"}[15m]) > 0\n submissionChallengeRefusedTotal: this.meter.createCounter('submission_challenge_refused_total', {\n description: 'Public submissions refused at their captcha or proof-of-work challenge, by reason',\n }),\n // #2867 — Content-Security-Policy violations browsers reported, by the directive that refused (or, under a\n // report-only policy, would have refused) and by disposition. A policy that is wrong for the product shows here as\n // a steady rate on one directive; flip a surface from report-only to enforcing only once its `report` series is\n // understood:\n // sum by (effective_directive) (rate(csp_violation_reports_total{disposition=\"report\"}[1h]))\n // Every label is a closed enum (`CspViolationReportedDirective` × `CspViolationDisposition` ×\n // `CspViolationReportDelivery`), so a forged report cannot mint a series.\n cspViolationReportsTotal: this.meter.createCounter('csp_violation_reports_total', {\n description: 'Content-Security-Policy violations reported by browsers, by effective directive, disposition and delivery',\n }),\n };\n }\n\n // ---------------------------------------------------------------------------\n // Data Seeding metrics (Phase 6.D / F-17)\n // ---------------------------------------------------------------------------\n // Typed wrappers around the four data-seeding counters so the dispatcher\n // never reaches into the raw OpenTelemetry meter and so all label keys\n // stay consistent (snake_case to match Prometheus convention; the\n // dispatcher passes already-stringified enum values).\n // ---------------------------------------------------------------------------\n\n /**\n * LAZY engine — C1 idempotency-probe cache hit. Fired once per\n * (seed × scope) when `runLazy` short-circuits because a prior\n * COMPLETED `DataSeedRun` row already covers the scope.\n */\n public recordDataSeedingLazyCacheHit(params: { seedKey: string; scopeKind: string }): void {\n this.metricsDefinitions.dataSeedingLazyC1CacheHits.add(1, {\n seed_key: params.seedKey,\n scope_kind: params.scopeKind,\n });\n }\n\n /**\n * LAZY engine — C1 idempotency-probe cache miss. Fired once per\n * (seed × scope) when `runLazy` proceeds past the C1 probe and\n * attempts to acquire a run-slot.\n */\n public recordDataSeedingLazyCacheMiss(params: { seedKey: string; scopeKind: string }): void {\n this.metricsDefinitions.dataSeedingLazyC1CacheMisses.add(1, {\n seed_key: params.seedKey,\n scope_kind: params.scopeKind,\n });\n }\n\n /**\n * LAZY engine — concurrent first-access race resolved by silent\n * bow-out. `reason` mirrors the dispatcher's\n * `acquireLazyRunSlotWithRaceGuard` outcome:\n * - `concurrent-completed` — a winning concurrent caller already\n * wrote a COMPLETED row (data is there);\n * - `concurrent-running` — a winning concurrent caller currently\n * owns the RUNNING slot (data is being written).\n */\n public recordDataSeedingThunderHerdBowout(params: {\n seedKey: string;\n scopeKind: string;\n reason: 'concurrent-completed' | 'concurrent-running';\n }): void {\n this.metricsDefinitions.dataSeedingThunderHerdBowouts.add(1, {\n seed_key: params.seedKey,\n scope_kind: params.scopeKind,\n reason: params.reason,\n });\n }\n\n /**\n * Terminal `DataSeedRun` write — fired exactly once per row\n * transition into COMPLETED / PARTIAL / FAILED. The metric is\n * emitted from the shared lifecycle writers\n * (`completeDataSeedRun` / `failDataSeedRun` /\n * `writeFreshFailedDataSeedRun`) so every dispatcher engine —\n * Level-A application lifecycle, Level-B resource lifecycle, LAZY\n * first-access, MANUAL re-runs, and the deferred Phase-7 cron —\n * contributes uniformly without per-engine wiring.\n *\n * `mode`, `status`, `triggerOrigin`, and `scopeKind` are passed as\n * raw enum string values (the dispatcher does the `.toString()`) so\n * this service stays decoupled from the data-seeding domain enums.\n *\n * Phase 5/6 audit H-2 — `scope_kind` was added to align with the\n * sibling LAZY-engine counters (hit / miss / bow-out) which all\n * carry it. Without `scope_kind`, operators cannot answer\n * \"are my org-scoped seeds healthier than my user-scoped seeds?\",\n * and the deferred Phase-7 cron-scheduler dashboard cannot slice\n * terminal-run health by scope at all (terminal counts are the\n * only signal SYNC / ADDITIVE / UPGRADE seeds emit). Cardinality\n * stays bounded: 5 `DataSeedScopeKind` values × ~200 seeds × 4\n * modes × 4 statuses × ~6 trigger origins ≈ 96K series upper\n * bound; in practice <1K active series.\n */\n public recordDataSeedingRun(params: {\n seedKey: string;\n mode: string;\n status: string;\n triggerOrigin: string;\n scopeKind: string;\n }): void {\n this.metricsDefinitions.dataSeedingRunTotal.add(1, {\n seed_key: params.seedKey,\n mode: params.mode,\n status: params.status,\n trigger_origin: params.triggerOrigin,\n scope_kind: params.scopeKind,\n });\n }\n\n /**\n * Wall-clock duration of the admin `GET /internal/admin/data-seeding/seeds`\n * endpoint in milliseconds. Recorded in the controller around the full\n * registry walk (which fans out N `lastRun` lookups, one per seed).\n *\n * Phase 5/6 audit L-4 — needed because the endpoint is N+1 by design\n * (single registry-wide aggregate would couple the surface to the\n * adapter's grammar; see the controller's `lookupLastRunSummary` JSDoc).\n * The histogram lets operators spot when the seed registry crosses the\n * \"switch to bulk aggregation\" threshold and surface it as a Phase-7\n * dashboard SLO alert.\n *\n * `seedCount` is bucketed coarsely (0, 1-10, 11-50, 51-200, 201+) so\n * label cardinality stays bounded across deployments with widely\n * different seed counts.\n */\n public recordDataSeedingAdminListSeedsDuration(params: {\n durationMs: number;\n seedCount: number;\n }): void {\n const bucket = (() => {\n if (params.seedCount <= 0) return '0';\n if (params.seedCount <= 10) return '1-10';\n if (params.seedCount <= 50) return '11-50';\n if (params.seedCount <= 200) return '51-200';\n return '201+';\n })();\n this.metricsDefinitions.dataSeedingAdminListSeedsDuration.record(params.durationMs, {\n seed_count_bucket: bucket,\n });\n }\n\n // ---------------------------------------------------------------------------\n // M2M Outbound Webhook Delivery metrics\n // ---------------------------------------------------------------------------\n // Typed wrapper around the single `m2m_webhook_delivery_total` counter so\n // worker call sites never reach into the raw OpenTelemetry meter and so\n // label keys (`scope` / `outcome`) stay consistent. The `scope` parameter\n // is locked to the `AuthScopeType` enum (`'organization' | 'application'`)\n // — passing a typo or a stale string fails type-check rather than silently\n // creating a parallel time series — and `outcome` maps 1:1 to\n // `M2MWebhookDeliveryBatchOutput.outcome`.\n //\n // Firing contract:\n // - Exactly ONCE per worker invocation, at each terminal / intermediate\n // return-point in `m2mWebhookDeliveryBatchService.doHandle`.\n // - NOT fired from the dispatcher's skip paths (feature off / config\n // off / no endpoints) — those never create a delivery row and never\n // emit outbound HTTP, so they are not webhook deliveries by\n // definition.\n // ---------------------------------------------------------------------------\n\n /**\n * M2M Outbound Webhook Delivery outcome counter.\n *\n * @param params.scope - `AuthScopeType.ORGANIZATION` (`'organization'`)\n * or `AuthScopeType.APPLICATION` (`'application'`). Locked to the\n * shared `AuthScopeType` enum so a typo or stale literal fails\n * type-check rather than silently creating a parallel time series\n * under a divergent label.\n * @param params.outcome - One of the five\n * `M2MWebhookDeliveryBatchOutput.outcome` values. `delivered` and\n * `failed_terminal` are terminal; `retry_scheduled` is the\n * intermediate retry branch; `skipped_missing_row` /\n * `skipped_already_leased` cover the two skip branches that still\n * consumed a worker slot.\n */\n public recordM2MWebhookDeliveryOutcome(params: {\n scope: AuthScopeType;\n outcome:\n | 'delivered'\n | 'retry_scheduled'\n | 'failed_terminal'\n | 'skipped_missing_row'\n | 'skipped_already_leased';\n }): void {\n this.metricsDefinitions.m2mWebhookDeliveryTotal.add(1, {\n scope: params.scope,\n outcome: params.outcome,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Compliance Audit-Log Sink failures (Phase 5 / F6)\n // ---------------------------------------------------------------------------\n\n /**\n * F6 (audit Phase 5) — a Layer-2 provider audit sink threw while recording an\n * event. Fired by `CompositeAuditLogSink` in its per-sink catch, so an\n * otherwise-swallowed sink failure is OBSERVABLE (→ alert). Synchronous, never\n * throws (the global meter is a no-op without the OTLP preload).\n *\n * @param params.providerRef - The declared audit provider whose sink failed\n * (immudb, a SIEM webhook, …) — the stable, low-cardinality series label.\n */\n public recordAuditSinkFailure(params: { providerRef: string }): void {\n this.metricsDefinitions.auditSinkFailureTotal.add(1, {\n provider: params.providerRef,\n });\n }\n\n /**\n * A tamper-evident audit provider PROVED its store was rolled back / tampered between restarts\n * (its durable-state cryptographic consistency proof failed). Fired by `CompositeAuditLogSink`\n * via the `onIntegrityViolation` hook it threads into the provider sink factory (the sink cannot\n * import this service across the dependency wall). DISTINCT from {@link recordAuditSinkFailure}:\n * this is a compliance incident (page a human), not a backfillable transient miss. Synchronous,\n * never throws (the global meter is a no-op without the OTLP preload).\n *\n * @param params.providerRef - The audit provider whose store proved tampered (immudb, …).\n */\n public recordAuditTamperDetected(params: { providerRef: string }): void {\n this.metricsDefinitions.auditTamperDetectedTotal.add(1, {\n provider: params.providerRef,\n });\n }\n\n /**\n * A tamper-evident audit provider DEGRADED from full cross-restart tamper-evidence to a weaker\n * assurance level (ephemeral mode, a corrupt anchor, an un-pinned server-identity change, or a per-op\n * proof failure). Fired by `CompositeAuditLogSink` via the `onAssuranceDegraded` hook it threads into\n * the provider sink factory. DISTINCT from {@link recordAuditTamperDetected}: a degradation is not a\n * proven tamper, but it means a future tamper may go UNDETECTED — alertable so the guarantee never\n * lapses silently. Non-latching. Synchronous, never throws.\n *\n * @param params.providerRef - The audit provider that degraded (immudb, …).\n * @param params.reason - Stable snake_case slug (`ephemeral`, `anchor_corrupt`, `anchor_identity_change`, `proof_failure_transient`).\n */\n public recordAuditIntegrityAssuranceDegraded(params: { providerRef: string; reason: string }): void {\n this.metricsDefinitions.auditIntegrityAssuranceDegradedTotal.add(1, {\n provider: params.providerRef,\n reason: params.reason,\n });\n }\n\n /**\n * The Layer-1 authoritative DB audit store threw while persisting an event. Fired by\n * `AuditLogsBackendService._createAuditLog` in its Layer-1 catch, so the \"the primary audit record\n * itself did not persist\" outage is OBSERVABLE (→ alert) rather than a swallowed warn line on a\n * fire-and-forget path. DISTINCT from {@link recordAuditSinkFailure}: that is a Layer-2 provider sink\n * (immudb/SIEM) hiccup the reconciler backfills; THIS is the authoritative store failing. Synchronous,\n * never throws (the global meter is a no-op without the OTLP preload). Label-free — the authoritative\n * store has no provider dimension. Alert on `rate(audit_store_failure_total[5m]) > 0`.\n */\n public recordAuditStoreFailure(): void {\n this.metricsDefinitions.auditStoreFailureTotal.add(1);\n }\n\n /**\n * A fire-and-forget security audit observation was DROPPED before it reached the audit pipeline.\n * Fired by the shared emission seam (`audit-observation-emission.backend.ts`), which every such\n * observation routes through, so a new observation is counted the day it lands.\n *\n * DISTINCT from {@link recordAuditStoreFailure}, and the distinction is the reason this counter\n * exists: that one fires INSIDE `_createAuditLog`, so it only ever sees an emission that reached\n * the audit service. The shapes counted here — an unbound service or absent `log*` method, a synchronous\n * throw, a rejected promise — were previously invisible. A rejected promise is also a store refusal\n * when the audit method records with `SURFACE_TO_CALLER` (the system-context read, the pipeline reset's\n * `attempted` row, #2088): BOTH counters see that one. The fourth shape, an awaited emission its caller\n * stopped waiting for (`emission_timed_out`), may still land.\n * Merging them into one counter would let a total wiring outage hide behind a store hiccup.\n *\n * Synchronous, never throws (the global meter is a no-op without the OTLP preload — which is why\n * the seam ALSO logs, at a throttled `error`).\n *\n * @param params.observation - `AuditObservationKind` member — WHICH security event was lost.\n * @param params.reason - `AuditObservationLossReason` member — WHICH loss shape.\n */\n public recordAuditObservationDropped(params: { observation: string; reason: string }): void {\n this.metricsDefinitions.auditObservationDroppedTotal.add(1, {\n observation: params.observation,\n reason: params.reason,\n });\n }\n\n /**\n * #1735 — one public submission refused at its challenge. Synchronous, never throws.\n *\n * @param params.reason - why it was refused; the enum keeps the metric's label set bounded.\n */\n public recordSubmissionChallengeRefused(params: { reason: SubmissionChallengeRefusalReason }): void {\n this.metricsDefinitions.submissionChallengeRefusedTotal.add(1, { reason: params.reason });\n }\n\n /**\n * #2867 — one Content-Security-Policy violation a browser reported. Synchronous, never throws.\n *\n * @param params.effectiveDirective - the directive that refused, mapped onto a closed vocabulary.\n * @param params.disposition - `enforce` (blocked) or `report` (a report-only policy).\n * @param params.delivery - `report_uri` or `report_to`, which tells an operator what the visitors' browsers implement.\n */\n public recordCspViolationReport(params: {\n effectiveDirective: CspViolationReportedDirective;\n disposition: CspViolationDisposition;\n delivery: CspViolationReportDelivery;\n }): void {\n this.metricsDefinitions.cspViolationReportsTotal.add(1, {\n effective_directive: params.effectiveDirective,\n disposition: params.disposition,\n delivery: params.delivery,\n });\n }\n\n /**\n * #2891 — one signature request the custodian answered, how long it took and how it ended. Synchronous, never throws.\n *\n * @param params.outcome - issued, replayed (the stored signature returned for a retry), refused, or error (a failure that is not a refusal).\n */\n public recordKeyManagementSignature(params: { purpose: CryptoKey_Purpose | null; outcome: CryptoKey_SignatureOutcome; durationMs: number }): void {\n this.metricsDefinitions.keyManagementSignatureDurationMs.record(params.durationMs, { purpose: params.purpose ?? 'unreadable', outcome: params.outcome });\n }\n\n /**\n * #2891 — a refused signature request, by its `CryptoKey_SignatureRefusal`. `verify_after_sign_failed` means a provider\n * returned a signature that does not verify under the key it was asked to use: alert on it. Synchronous, never throws.\n */\n public recordKeyManagementSignatureRefused(params: { purpose: CryptoKey_Purpose | null; refusal: CryptoKey_SignatureRefusal }): void {\n // A request refused before its body could be read has no purpose: its label says so rather than inventing one.\n this.metricsDefinitions.keyManagementSignatureRefusedTotal.add(1, { purpose: params.purpose ?? 'unreadable', refusal: params.refusal });\n }\n\n /** #2891 — an application failed to refresh its published verification keys from the custodian. Synchronous, never throws. */\n public recordKeyManagementVerificationKeysRefreshFailure(): void {\n this.metricsDefinitions.keyManagementVerificationKeysRefreshFailureTotal.add(1);\n }\n\n /** #2903 — an approval seal the relay settled: sealed (with its lag), retried after a refusal, or dead. Synchronous, never throws. */\n public recordApprovalSealSettled(params: { status: ApprovalSealStatus; refusal?: CryptoKey_SignatureRefusal; lagSeconds?: number }): void {\n this.metricsDefinitions.approvalSealSettledTotal.add(1, { status: params.status, refusal: params.refusal ?? 'none' });\n if (params.lagSeconds !== undefined) this.metricsDefinitions.approvalSealLagSeconds.record(params.lagSeconds);\n }\n\n /** The age the last relay run left its oldest unsealed seal at, observed by the gauge on every collection. */\n private approvalSealOldestUnsealedAge = 0;\n private approvalSealOldestUnsealedAgeObserved = false;\n\n /** #2903 — the age of the oldest seal a relay run left unsealed (0 when none). Synchronous, never throws. */\n public recordApprovalSealOldestUnsealedAge(ageSeconds: number): void {\n this.approvalSealOldestUnsealedAge = ageSeconds;\n if (this.approvalSealOldestUnsealedAgeObserved) return;\n this.approvalSealOldestUnsealedAgeObserved = true;\n this.metricsDefinitions.approvalSealOldestUnsealedAgeSeconds.addCallback((result: { observe: (value: number) => void }) => result.observe(this.approvalSealOldestUnsealedAge));\n }\n\n /**\n * #2293 — one sending of a deliverable for electronic signature: `sent`, or the `SignatureRequestSendRefusal` that stopped\n * it. Synchronous, never throws.\n */\n public recordSignatureRequestSent(params: { outcome: ElectronicSignatureSendOutcome.SENT | SignatureRequestSendRefusal; requiredLevel: ElectronicSignature_Level }): void {\n this.metricsDefinitions.signatureRequestSentTotal.add(1, { outcome: params.outcome, required_level: params.requiredLevel });\n }\n\n /** #2293 — a signature request a re-read moved, by the state it reached. Synchronous, never throws. */\n public recordSignatureRequestMoved(params: { providerRef: string; to: SignatureRequest_State }): void {\n this.metricsDefinitions.signatureRequestMovedTotal.add(1, { provider: params.providerRef, to: params.to });\n }\n\n /**\n * #2293 — a request the vendor reported complete that stayed open, or failed, on its evidence, by\n * `SignatureRequestEvidenceFailure`. Synchronous, never throws.\n */\n public recordSignatureRequestEvidenceRefused(params: { providerRef: string; failure: SignatureRequestEvidenceFailure }): void {\n this.metricsDefinitions.signatureRequestEvidenceRefusedTotal.add(1, { provider: params.providerRef, failure: params.failure });\n }\n\n /** #2293 — a re-read the vendor did not answer usably. Synchronous, never throws. */\n public recordSignatureRequestVendorNotRead(params: { providerRef: string }): void {\n this.metricsDefinitions.signatureRequestVendorNotReadTotal.add(1, { provider: params.providerRef });\n }\n\n /** #2293 — one link of a SIGNED request's evidence file, by `SignatureRequestEvidenceLinkOutcome`. Synchronous, never throws. */\n public recordSignatureRequestEvidenceLink(params: { outcome: SignatureRequestEvidenceLinkOutcome }): void {\n this.metricsDefinitions.signatureRequestEvidenceLinkTotal.add(1, { outcome: params.outcome });\n }\n\n /** #2891 — a key version found signing past its purpose's cryptoperiod (reported once per version). Synchronous, never throws. */\n public recordKeyManagementRotationDue(params: { purpose: CryptoKey_Purpose }): void {\n this.metricsDefinitions.keyManagementRotationDueTotal.add(1, { purpose: params.purpose });\n }\n}\n"]}
|
package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { AbstractControllerBackendService } from '../../../base-classes/services
|
|
|
25
25
|
import type { WebhookHandlerBackendService } from '../../../notifications/webhooks/services/webhook-handler.backend.service';
|
|
26
26
|
import type { InboundHandlerRegistryBackendService } from '../../../inbound/services/inbound-handler-registry.backend.service';
|
|
27
27
|
import type { InboundDeliveryReceiverBackendService, InboundReceiveAnswer } from '../../../inbound/services/inbound-delivery-receiver.backend.service';
|
|
28
|
+
import type { InboundLargeBodyRoutesBackendService } from '../../../runtime/services/utils/inbound-endpoint-raw-body.backend.utils';
|
|
28
29
|
/**
|
|
29
30
|
* Why a declared webhook endpoint did NOT get an Express route.
|
|
30
31
|
*
|
|
@@ -177,6 +178,8 @@ export declare function describeCapabilityWiringCause(wiring: WebhookCapabilityW
|
|
|
177
178
|
export declare class WebhookAutoControllerBackendService extends AbstractControllerBackendService {
|
|
178
179
|
private readonly backendProviderRegistry;
|
|
179
180
|
private readonly externalProvidersRegistry;
|
|
181
|
+
/** #3395: where a provider endpoint reading more than the global parsers do is declared, for the body parser to read. */
|
|
182
|
+
private readonly largeBodyRoutes?;
|
|
180
183
|
/** Capability handlers keyed by capability string (e.g., 'billing') */
|
|
181
184
|
private capabilityHandlers;
|
|
182
185
|
/** What each capability's owning startup step recorded (#3255), keyed by capability. Read when a route is withheld. */
|
|
@@ -206,7 +209,9 @@ export declare class WebhookAutoControllerBackendService extends AbstractControl
|
|
|
206
209
|
* {@link registerCapabilityHandler}, which refuses to let that be silent.
|
|
207
210
|
*/
|
|
208
211
|
private routesRegistered;
|
|
209
|
-
constructor(logger: LoggerService, errorBuilder: ErrorBuilderBackendService, errorHandler: ErrorHandlerService, backendProviderRegistry: BackendProviderRegistryBackendService, externalProvidersRegistry: ExternalProvidersRegistryBackendService
|
|
212
|
+
constructor(logger: LoggerService, errorBuilder: ErrorBuilderBackendService, errorHandler: ErrorHandlerService, backendProviderRegistry: BackendProviderRegistryBackendService, externalProvidersRegistry: ExternalProvidersRegistryBackendService,
|
|
213
|
+
/** #3395: where a provider endpoint reading more than the global parsers do is declared, for the body parser to read. */
|
|
214
|
+
largeBodyRoutes?: Pick<InboundLargeBodyRoutesBackendService, 'declare'>);
|
|
210
215
|
/**
|
|
211
216
|
* Initialize with required dependencies, pre-load endpoint configs, AND
|
|
212
217
|
* register the webhook routes.
|
package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-auto-controller.backend.service.d.ts","sourceRoot":"","sources":["../../../../../src/notifications/webhooks/controllers/webhook-auto-controller.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAW,QAAQ,EAAgB,MAAM,SAAS,CAAC;AAC/D,OAAO,EAQL,KAAK,wBAAwB,EAC9B,MAAM,sCAAsC,CAAC;AAI9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAC;AAClG,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kEAAkE,CAAC;AACnH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kEAAkE,CAAC;AAC5G,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,0FAA0F,CAAC;AACtJ,OAAO,KAAK,EAAE,uCAAuC,EAAE,MAAM,4FAA4F,CAAC;AAC1J,OAAO,EAAE,gCAAgC,EAAE,MAAM,0FAA0F,CAAC;AAC5I,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oFAAoF,CAAC;AAGvI,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,8EAA8E,CAAC;AACzI,OAAO,KAAK,EAAE,qCAAqC,EAAqB,oBAAoB,EAAE,MAAM,+EAA+E,CAAC;
|
|
1
|
+
{"version":3,"file":"webhook-auto-controller.backend.service.d.ts","sourceRoot":"","sources":["../../../../../src/notifications/webhooks/controllers/webhook-auto-controller.backend.service.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js
CHANGED
|
@@ -26,7 +26,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
26
26
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
27
27
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
28
28
|
};
|
|
29
|
-
import { injectable, inject } from 'inversify';
|
|
29
|
+
import { injectable, inject, optional } from 'inversify';
|
|
30
30
|
import express from 'express';
|
|
31
31
|
import { ExternalProvider_ExchangeProtocol_Kind, Hook_AcknowledgementEncoding, ProviderProtocolRuntimeKind, hookSignatureDeclarationIsComplete, isReReadTriggerEndpoint, reReadTriggerLimitsAreSound, } from '@wildo-ai/external-connectors-models';
|
|
32
32
|
import { ErrorType, isWildoBackendError } from '@wildo-ai/saas-models';
|
|
@@ -34,7 +34,7 @@ import { SAAS_SERVICE_TYPES } from '../../../inject/models/service-types.js';
|
|
|
34
34
|
import { AbstractControllerBackendService } from '../../../base-classes/services/controllers/abstract-controller.backend.service.js';
|
|
35
35
|
import { engineSchemeSignsDeliveryId, isEngineVerifiedWebhookEndpoint } from '../../../notifications/webhooks/services/webhook-handler.backend.service.js';
|
|
36
36
|
import { projectCaughtErrorLogFields } from '../../../errors/utils/error-log-level-classification.backend.utils.js';
|
|
37
|
-
import { deriveInboundEndpointSecretEnvVarName, INBOUND_APPLICATION_ENDPOINT_PROVIDER_REF, inboundEndpointRoutePath } from '@wildo-ai/saas-models';
|
|
37
|
+
import { deriveInboundEndpointSecretEnvVarName, INBOUND_APPLICATION_ENDPOINT_PROVIDER_REF, INBOUND_DELIVERY_MAX_BODY_BYTES, INBOUND_DELIVERY_MAX_STORED_BODY_BYTES, inboundEndpointRoutePath, MAIN_API_BASE_PATH } from '@wildo-ai/saas-models';
|
|
38
38
|
/**
|
|
39
39
|
* Why a declared webhook endpoint did NOT get an Express route.
|
|
40
40
|
*
|
|
@@ -197,6 +197,7 @@ function describeRegistrationKeys(keys) {
|
|
|
197
197
|
let WebhookAutoControllerBackendService = class WebhookAutoControllerBackendService extends AbstractControllerBackendService {
|
|
198
198
|
backendProviderRegistry;
|
|
199
199
|
externalProvidersRegistry;
|
|
200
|
+
largeBodyRoutes;
|
|
200
201
|
/** Capability handlers keyed by capability string (e.g., 'billing') */
|
|
201
202
|
capabilityHandlers = new Map();
|
|
202
203
|
/** What each capability's owning startup step recorded (#3255), keyed by capability. Read when a route is withheld. */
|
|
@@ -226,10 +227,11 @@ let WebhookAutoControllerBackendService = class WebhookAutoControllerBackendServ
|
|
|
226
227
|
* {@link registerCapabilityHandler}, which refuses to let that be silent.
|
|
227
228
|
*/
|
|
228
229
|
routesRegistered = false;
|
|
229
|
-
constructor(logger, errorBuilder, errorHandler, backendProviderRegistry, externalProvidersRegistry) {
|
|
230
|
+
constructor(logger, errorBuilder, errorHandler, backendProviderRegistry, externalProvidersRegistry, largeBodyRoutes) {
|
|
230
231
|
super(logger, errorBuilder, errorHandler, 'WebhookAutoController');
|
|
231
232
|
this.backendProviderRegistry = backendProviderRegistry;
|
|
232
233
|
this.externalProvidersRegistry = externalProvidersRegistry;
|
|
234
|
+
this.largeBodyRoutes = largeBodyRoutes;
|
|
233
235
|
}
|
|
234
236
|
// ════════════════════════════════════════════════════════════
|
|
235
237
|
// Initialization
|
|
@@ -599,6 +601,13 @@ let WebhookAutoControllerBackendService = class WebhookAutoControllerBackendServ
|
|
|
599
601
|
});
|
|
600
602
|
continue;
|
|
601
603
|
}
|
|
604
|
+
// #3395: an endpoint an inbound handler takes, declaring a body larger than a delivery row (a pushed email), is read
|
|
605
|
+
// raw up to its own limit by the parser mounted before the global ones, whose 10 MB would refuse it. Never past the
|
|
606
|
+
// most any delivery may hold, which the receiver also enforces.
|
|
607
|
+
if (endpoint.maxBodyBytes !== undefined && endpoint.maxBodyBytes > INBOUND_DELIVERY_MAX_STORED_BODY_BYTES
|
|
608
|
+
&& this.inbound?.registry.getProviderEndpointHandler(providerRef, endpoint.key)) {
|
|
609
|
+
this.largeBodyRoutes?.declare(`${MAIN_API_BASE_PATH}${routePath}`, Math.min(endpoint.maxBodyBytes, INBOUND_DELIVERY_MAX_BODY_BYTES));
|
|
610
|
+
}
|
|
602
611
|
this.router.post(routePath,
|
|
603
612
|
// Defense-in-depth for a future streaming mount. If this controller is
|
|
604
613
|
// ever assigned the RAW_REQUEST_STREAM mount phase, this express.raw()
|
|
@@ -816,7 +825,9 @@ WebhookAutoControllerBackendService = __decorate([
|
|
|
816
825
|
__param(2, inject(SAAS_SERVICE_TYPES.ErrorHandlerService)),
|
|
817
826
|
__param(3, inject(SAAS_SERVICE_TYPES.BackendProviderRegistryService)),
|
|
818
827
|
__param(4, inject(SAAS_SERVICE_TYPES.ExternalProvidersRegistryService)),
|
|
819
|
-
|
|
828
|
+
__param(5, inject(SAAS_SERVICE_TYPES.InboundLargeBodyRoutes)),
|
|
829
|
+
__param(5, optional()),
|
|
830
|
+
__metadata("design:paramtypes", [Function, Function, Function, Function, Function, Object])
|
|
820
831
|
], WebhookAutoControllerBackendService);
|
|
821
832
|
export { WebhookAutoControllerBackendService };
|
|
822
833
|
//# sourceMappingURL=webhook-auto-controller.backend.service.js.map
|