@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.
Files changed (226) hide show
  1. package/dist/esm/base-classes/models/manual-controllers.backend.definition.d.ts.map +1 -1
  2. package/dist/esm/base-classes/models/manual-controllers.backend.definition.js +2 -0
  3. package/dist/esm/base-classes/models/manual-controllers.backend.definition.js.map +1 -1
  4. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts +4 -0
  5. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts.map +1 -1
  6. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js +20 -5
  7. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js.map +1 -1
  8. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts +3 -0
  9. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts.map +1 -1
  10. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js +10 -1
  11. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js.map +1 -1
  12. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts +22 -0
  13. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts.map +1 -1
  14. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js +25 -1
  15. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js.map +1 -1
  16. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts +38 -3
  17. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts.map +1 -1
  18. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js +68 -5
  19. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js.map +1 -1
  20. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts +2 -2
  21. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts.map +1 -1
  22. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js +6 -3
  23. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js.map +1 -1
  24. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts +83 -0
  25. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts.map +1 -1
  26. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js +217 -14
  27. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js.map +1 -1
  28. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts +32 -0
  29. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts.map +1 -0
  30. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js +36 -0
  31. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js.map +1 -0
  32. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts +38 -0
  33. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts.map +1 -0
  34. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js +83 -0
  35. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js.map +1 -0
  36. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts +36 -0
  37. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts.map +1 -0
  38. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js +51 -0
  39. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js.map +1 -0
  40. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts +46 -0
  41. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts.map +1 -1
  42. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js +68 -0
  43. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js.map +1 -1
  44. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts +27 -0
  45. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts.map +1 -1
  46. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js +42 -3
  47. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js.map +1 -1
  48. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts +26 -1
  49. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts.map +1 -1
  50. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js +10 -0
  51. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js.map +1 -1
  52. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts +10 -1
  53. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts.map +1 -1
  54. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js +60 -28
  55. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js.map +1 -1
  56. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts +90 -0
  57. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts.map +1 -0
  58. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js +373 -0
  59. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js.map +1 -0
  60. package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts +29 -2
  61. package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts.map +1 -1
  62. package/dist/esm/compliance/approval-seals/decision-presentation.backend.js +40 -3
  63. package/dist/esm/compliance/approval-seals/decision-presentation.backend.js.map +1 -1
  64. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.d.ts.map +1 -1
  65. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js +34 -6
  66. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js.map +1 -1
  67. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts +30 -6
  68. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts.map +1 -1
  69. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js +67 -22
  70. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js.map +1 -1
  71. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.d.ts.map +1 -1
  72. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js +18 -1
  73. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js.map +1 -1
  74. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts +66 -1
  75. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts.map +1 -1
  76. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js +161 -14
  77. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js.map +1 -1
  78. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts +47 -0
  79. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts.map +1 -1
  80. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.js.map +1 -1
  81. package/dist/esm/external-providers/services/content-safety.backend.service.d.ts +27 -2
  82. package/dist/esm/external-providers/services/content-safety.backend.service.d.ts.map +1 -1
  83. package/dist/esm/external-providers/services/content-safety.backend.service.js +46 -1
  84. package/dist/esm/external-providers/services/content-safety.backend.service.js.map +1 -1
  85. package/dist/esm/external-providers/services/embeddings.backend.service.d.ts.map +1 -1
  86. package/dist/esm/external-providers/services/embeddings.backend.service.js +2 -0
  87. package/dist/esm/external-providers/services/embeddings.backend.service.js.map +1 -1
  88. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +11 -0
  89. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -1
  90. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +23 -0
  91. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
  92. package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts +19 -1
  93. package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts.map +1 -1
  94. package/dist/esm/external-providers/services/provider-service-account-token.backend.js +41 -1
  95. package/dist/esm/external-providers/services/provider-service-account-token.backend.js.map +1 -1
  96. package/dist/esm/files/utils/file-parent-read-context.backend.d.ts +27 -2
  97. package/dist/esm/files/utils/file-parent-read-context.backend.d.ts.map +1 -1
  98. package/dist/esm/files/utils/file-parent-read-context.backend.js +23 -4
  99. package/dist/esm/files/utils/file-parent-read-context.backend.js.map +1 -1
  100. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts +26 -0
  101. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts.map +1 -1
  102. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js +100 -8
  103. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js.map +1 -1
  104. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts +3 -1
  105. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts.map +1 -1
  106. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js +8 -2
  107. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js.map +1 -1
  108. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts +43 -0
  109. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts.map +1 -1
  110. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js +37 -0
  111. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js.map +1 -1
  112. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts +7 -0
  113. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts.map +1 -1
  114. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js +8 -3
  115. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js.map +1 -1
  116. package/dist/esm/flows-actors/services/agents.backend.service.d.ts +31 -6
  117. package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
  118. package/dist/esm/flows-actors/services/agents.backend.service.js +78 -30
  119. package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
  120. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.d.ts.map +1 -1
  121. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js +4 -0
  122. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js.map +1 -1
  123. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts +28 -2
  124. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts.map +1 -1
  125. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js +132 -22
  126. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js.map +1 -1
  127. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.d.ts.map +1 -1
  128. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js +12 -8
  129. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js.map +1 -1
  130. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts +5 -0
  131. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts.map +1 -1
  132. package/dist/esm/flows-actors/services/flows-actors-registry.service.js +18 -2
  133. package/dist/esm/flows-actors/services/flows-actors-registry.service.js.map +1 -1
  134. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts +33 -0
  135. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts.map +1 -1
  136. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js +58 -0
  137. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
  138. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts +12 -1
  139. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts.map +1 -1
  140. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js +23 -4
  141. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js.map +1 -1
  142. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts +12 -1
  143. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts.map +1 -1
  144. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js +55 -17
  145. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js.map +1 -1
  146. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts +22 -1
  147. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts.map +1 -1
  148. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js +52 -9
  149. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js.map +1 -1
  150. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts +79 -0
  151. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts.map +1 -0
  152. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js +211 -0
  153. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js.map +1 -0
  154. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts +2 -2
  155. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts.map +1 -1
  156. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js +9 -1
  157. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js.map +1 -1
  158. package/dist/esm/index.d.ts +1 -0
  159. package/dist/esm/index.d.ts.map +1 -1
  160. package/dist/esm/index.js +1 -0
  161. package/dist/esm/index.js.map +1 -1
  162. package/dist/esm/inject/models/container.d.ts.map +1 -1
  163. package/dist/esm/inject/models/container.js +6 -0
  164. package/dist/esm/inject/models/container.js.map +1 -1
  165. package/dist/esm/inject/models/service-types.d.ts +5 -0
  166. package/dist/esm/inject/models/service-types.d.ts.map +1 -1
  167. package/dist/esm/inject/models/service-types.js +3 -0
  168. package/dist/esm/inject/models/service-types.js.map +1 -1
  169. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts +5 -0
  170. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts.map +1 -1
  171. package/dist/esm/monitoring/observability/models/observability.backend.schemas.js.map +1 -1
  172. package/dist/esm/monitoring/observability/services/metrics.service.d.ts +34 -1
  173. package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -1
  174. package/dist/esm/monitoring/observability/services/metrics.service.js +49 -0
  175. package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -1
  176. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts +6 -1
  177. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts.map +1 -1
  178. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js +15 -4
  179. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js.map +1 -1
  180. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.d.ts.map +1 -1
  181. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js +3 -1
  182. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js.map +1 -1
  183. package/dist/esm/runtime/services/http-server.backend.service.d.ts +3 -1
  184. package/dist/esm/runtime/services/http-server.backend.service.d.ts.map +1 -1
  185. package/dist/esm/runtime/services/http-server.backend.service.js +11 -3
  186. package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -1
  187. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts +22 -0
  188. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts.map +1 -1
  189. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js +54 -0
  190. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js.map +1 -1
  191. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts +51 -0
  192. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts.map +1 -1
  193. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js +87 -15
  194. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js.map +1 -1
  195. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.d.ts.map +1 -1
  196. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js +5 -2
  197. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js.map +1 -1
  198. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts.map +1 -1
  199. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js +65 -24
  200. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js.map +1 -1
  201. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts +64 -1
  202. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts.map +1 -1
  203. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js +84 -2
  204. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js.map +1 -1
  205. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts +14 -0
  206. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts.map +1 -1
  207. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js +13 -5
  208. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js.map +1 -1
  209. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.d.ts.map +1 -1
  210. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js +6 -2
  211. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js.map +1 -1
  212. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts +7 -0
  213. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts.map +1 -1
  214. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js +65 -20
  215. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js.map +1 -1
  216. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.d.ts.map +1 -1
  217. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js +11 -4
  218. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js.map +1 -1
  219. package/dist/esm/users/services/user-self-custom-implementations.backend.d.ts.map +1 -1
  220. package/dist/esm/users/services/user-self-custom-implementations.backend.js +4 -2
  221. package/dist/esm/users/services/user-self-custom-implementations.backend.js.map +1 -1
  222. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.d.ts.map +1 -1
  223. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js +16 -0
  224. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js.map +1 -1
  225. package/dist/tsconfig.build.tsbuildinfo +1 -1
  226. package/package.json +10 -10
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-auto-controller.backend.service.js","sourceRoot":"","sources":["../../../../../src/notifications/webhooks/controllers/webhook-auto-controller.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Webhook Auto-Controller Backend Service\n *\n * Auto-registers webhook routes from provider registry definitions.\n * At startup, iterates all providers with WEBHOOK_ORIGINATOR protocol,\n * then iterates each provider's endpoints, and registers:\n * POST /webhooks/{providerRef}/{endpointKey}\n *\n * One provider declares the protocol today, and it declares one endpoint:\n * POST /webhooks/stripe/billing\n *\n * A second provider registers here the moment it declares `WEBHOOK_ORIGINATOR` with its own\n * `endpoints`; no edit to this controller is needed.\n *\n * This replaces manual per-provider webhook controllers.\n */\n\nimport { injectable, inject } from 'inversify';\nimport express from 'express';\nimport type { Request, Response, NextFunction } from 'express';\nimport {\n ExternalProvider_ExchangeProtocol_Kind,\n Hook_AcknowledgementEncoding,\n ProviderProtocolRuntimeKind,\n hookSignatureDeclarationIsComplete,\n isReReadTriggerEndpoint,\n reReadTriggerLimitsAreSound,\n type Hook_Endpoint,\n type WebhookCapabilityHandler,\n} from '@wildo-ai/external-connectors-models';\nimport { ErrorType, HttpMethod, isWildoBackendError } from '@wildo-ai/saas-models';\n\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport type { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';\nimport type { ErrorHandlerService } from '~wildo-backend-lib/errors/services/error-handler.backend.service';\nimport type { BackendProviderRegistryBackendService } from '~wildo-backend-lib/external-providers/services/backend-provider-registry.backend.service';\nimport type { ExternalProvidersRegistryBackendService } from '~wildo-backend-lib/external-providers/services/external-providers-registry.backend.service';\nimport { AbstractControllerBackendService } from '~wildo-backend-lib/base-classes/services/controllers/abstract-controller.backend.service';\nimport type { WebhookHandlerBackendService } from '~wildo-backend-lib/notifications/webhooks/services/webhook-handler.backend.service';\nimport { engineSchemeSignsDeliveryId, isEngineVerifiedWebhookEndpoint } from '~wildo-backend-lib/notifications/webhooks/services/webhook-handler.backend.service';\nimport { projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport type { InboundHandlerRegistryBackendService } from '~wildo-backend-lib/inbound/services/inbound-handler-registry.backend.service';\nimport type { InboundDeliveryReceiverBackendService, InboundRawRequest, InboundReceiveAnswer } from '~wildo-backend-lib/inbound/services/inbound-delivery-receiver.backend.service';\nimport { deriveInboundEndpointSecretEnvVarName, INBOUND_APPLICATION_ENDPOINT_PROVIDER_REF, inboundEndpointRoutePath } from '@wildo-ai/saas-models';\n\n/**\n * Why a declared webhook endpoint did NOT get an Express route.\n *\n * A closed vocabulary rather than a free string: each member names a DIFFERENT\n * missing registration, with a different remedy, and an operator reading the\n * startup log has to be able to tell them apart. The two are independent — an\n * endpoint can be missing either, or both.\n */\nexport enum WebhookRouteWithholdingReason {\n /**\n * No {@link WebhookCapabilityHandler} is registered for the endpoint's\n * `capability`. The route would reach `handleWebhookRequest`, complete\n * signature verification and idempotency claiming, then fail at dispatch.\n */\n NO_CAPABILITY_HANDLER = 'NO_CAPABILITY_HANDLER',\n /**\n * No `WebhookCapabilityAdapter` is registered for `providerRef:endpointKey`\n * on {@link WebhookHandlerBackendService}. The route would fail at the very\n * top of `processWebhook`, before signature verification.\n */\n NO_ENDPOINT_ADAPTER = 'NO_ENDPOINT_ADAPTER',\n /**\n * An APPLICATION inbound endpoint (#1596) whose verification secret — the variable\n * `deriveInboundEndpointSecretEnvVarName(endpointKey)` names — is unset at mount. An endpoint that\n * cannot verify must not exist: mounting it would answer 401 to every delivery forever, which tells\n * the sender nothing an operator can act on. The request-time refusal stays as well, because a\n * secret can disappear after mount.\n */\n NO_VERIFICATION_SECRET = 'NO_VERIFICATION_SECRET',\n /**\n * An ENGINE-verified provider endpoint (Svix, Slack v0, the Bot Framework token, Ed25519) that no inbound handler takes\n * (#2659). Engine schemes are served only on the durable inbound path; the capability path needs a provider\n * adapter such an endpoint cannot have, so the route would answer 500 on every delivery.\n */\n ENGINE_VERIFIED_WITHOUT_INBOUND_HANDLER = 'ENGINE_VERIFIED_WITHOUT_INBOUND_HANDLER',\n /**\n * An engine-verified provider endpoint whose scheme signs no delivery id (Slack v0, the Bot Framework token, Ed25519) and\n * which declares no `identifyEvent` (#2659). Nothing would name its events, so none could be stored.\n */\n NO_EVENT_IDENTIFIER = 'NO_EVENT_IDENTIFIER',\n /**\n * An engine-verified provider endpoint whose `signatureConfig` omits something its scheme reads (#3393): an `ED25519`\n * endpoint without its signature header, timestamp header or signed-content separator. The engine does not guess a\n * vendor's construction, so every delivery would be refused. A provider package defect.\n */\n SIGNATURE_DECLARATION_INCOMPLETE = 'SIGNATURE_DECLARATION_INCOMPLETE',\n /**\n * A re-read trigger endpoint (`Hook_TriggerStrategy.WEBHOOK_TRIGGERS_POLL`, #2909) that no inbound handler takes. Its\n * notifications only cause a re-read, which a handler performs; with none, nothing could act on them.\n */\n REREAD_TRIGGER_WITHOUT_INBOUND_HANDLER = 'REREAD_TRIGGER_WITHOUT_INBOUND_HANDLER',\n /**\n * The endpoint's declaration contradicts its trigger strategy (#2909): a re-read trigger endpoint that carries a\n * `signatureConfig` (nothing would verify it, so it would only look like a control) or no `reReadTrigger`, or any other\n * endpoint with no `signatureConfig` or with a `reReadTrigger`. A provider package defect.\n */\n DECLARATION_CONTRADICTS_TRIGGER_STRATEGY = 'DECLARATION_CONTRADICTS_TRIGGER_STRATEGY',\n /**\n * A re-read trigger endpoint whose `coalescingWindowSeconds` or `rateLimit` is not a positive integer (#2909 review\n * F6): a window of 0 would fail every request, and a negative or fractional one would coalesce nothing as declared.\n */\n REREAD_TRIGGER_LIMITS_INVALID = 'REREAD_TRIGGER_LIMITS_INVALID',\n /**\n * A re-read trigger endpoint whose provider declares no vendor rate budget (#2909 review F5): no `rateBudgets` on its\n * connection and no `maxRequestsPerMinute` of its own. The re-reads an unverified notification causes spend only a\n * share of the vendor's budget so polling keeps the rest; with none declared there is nothing to reserve, and a flood\n * would spend the vendor's real (undeclared) limit before polling could. Decided: refuse rather than reserve nothing.\n */\n REREAD_TRIGGER_WITHOUT_RATE_BUDGET = 'REREAD_TRIGGER_WITHOUT_RATE_BUDGET',\n}\n\n/**\n * Write an inbound answer (#2659): the endpoint's acknowledgement when it declared one, the engine's JSON otherwise.\n * An acknowledgement is always a 200: it answers a request the engine accepted.\n */\nexport function writeInboundAnswer(res: Response, answer: InboundReceiveAnswer): void {\n const acknowledgement = answer.acknowledgement;\n if (!acknowledgement) {\n res.status(answer.status).json(answer.body);\n return;\n }\n switch (acknowledgement.encoding) {\n case Hook_AcknowledgementEncoding.EMPTY:\n res.status(200).end();\n return;\n case Hook_AcknowledgementEncoding.JSON:\n res.status(200).json(acknowledgement.body);\n return;\n case Hook_AcknowledgementEncoding.TEXT:\n res.status(200).type('text/plain; charset=utf-8').send(acknowledgement.body);\n return;\n default: {\n const unhandled: never = acknowledgement;\n throw new Error(`Unknown acknowledgement encoding: ${JSON.stringify(unhandled)}`);\n }\n }\n}\n\n/** One declared endpoint whose route was deliberately not mounted, and why. */\nexport interface WebhookRouteWithholding {\n providerRef: string;\n endpointKey: string;\n capability: string;\n routePath: string;\n reasons: WebhookRouteWithholdingReason[];\n /**\n * What the startup step owning the endpoint's capability recorded about it, when one did (#3255). Present only\n * when it explains the withholding: it is the CAUSE, where {@link reasons} is the missing registration.\n */\n capabilityWiring?: WebhookCapabilityWiring;\n}\n\n/**\n * What the startup step that OWNS a webhook capability did with it (#3255) — billing's initializer, for `BILLING`.\n *\n * {@link WebhookRouteWithholdingReason} says which registration is missing; this says WHY the module that registers it\n * did not. The two are separate questions because the controller can measure the first and cannot know the second:\n * on app-creation-test-007 the line read `NO_CAPABILITY_HANDLER, NO_ENDPOINT_ADAPTER` with \"check whether billing\n * initialization was skipped or failed\", and the reader guessed \"no local Stripe credentials\", which is the one cause\n * that cannot produce it (billing enabled with no secret fails startup before any route is assessed). Recorded by the\n * capability's owner, read here, so the withholding line names the cause instead of listing the possibilities.\n */\nexport enum WebhookCapabilityWiringState {\n /**\n * The application does not enable the capability, so its module never ran — while a provider still declares an\n * endpoint for it (its `WEBHOOK_ORIGINATOR` protocol is enabled). A coherent configuration, said plainly: enable the\n * capability, or disable the provider's protocol.\n */\n NOT_ENABLED = 'NOT_ENABLED',\n /** The module ran and failed non-fatally before it wired the endpoint; the failure is carried. */\n INITIALIZATION_FAILED = 'INITIALIZATION_FAILED',\n /**\n * The module wired the capability, to the endpoint named — or to none, when its provider declares no enabled endpoint\n * for it. A withheld endpoint of a WIRED capability is a different provider's (or key's) endpoint nothing owns.\n */\n WIRED = 'WIRED',\n}\n\n/** One capability's wiring record (see {@link WebhookCapabilityWiringState}). */\nexport type WebhookCapabilityWiring =\n | {\n readonly capability: string;\n readonly state: WebhookCapabilityWiringState.NOT_ENABLED;\n /** The setting that enables it, named as the application author writes it (`billing.enabled`). */\n readonly enablingSetting: string;\n /** Where that setting is authored, relative to the application root. */\n readonly settingLocation: string;\n /**\n * What turning it on also needs, in the owner's words — billing needs a provider ref and that provider's secret, and\n * turning the switch on without them fails startup instead (`PROVIDER_REF_UNSET`, `SECRET_MISSING`).\n */\n readonly enablingRequires: string;\n /** The value found: `false`, or `null` when the setting (or its section) is absent. */\n readonly declaredValue: boolean | null;\n }\n | {\n readonly capability: string;\n readonly state: WebhookCapabilityWiringState.INITIALIZATION_FAILED;\n readonly providerRef: string | null;\n /** The failure as `describeCaughtError` renders it — the message of the error logged earlier at startup. */\n readonly failure: string;\n /** The startup log line that carries the full failure, so the reader can find it. */\n readonly failureLogLine: string;\n }\n | {\n readonly capability: string;\n readonly state: WebhookCapabilityWiringState.WIRED;\n readonly providerRef: string;\n /** The endpoint key the capability serves, or `null` when its provider declares no enabled endpoint for it. */\n readonly endpointKey: string | null;\n };\n\n/**\n * The CAUSE sentence of a withheld endpoint's line, from its capability's wiring record — or `null` when the record\n * explains nothing about THIS endpoint (a capability wired to this very endpoint is withheld for another reason, which\n * the per-reason remedies already name).\n */\nexport function describeCapabilityWiringCause(wiring: WebhookCapabilityWiring, providerRef: string, endpointKey: string): string | null {\n switch (wiring.state) {\n case WebhookCapabilityWiringState.NOT_ENABLED:\n return `'${wiring.capability}' is not enabled: \\`${wiring.enablingSetting}\\` is `\n + `${wiring.declaredValue === null ? 'not set' : String(wiring.declaredValue)} in ${wiring.settingLocation}, so its module never ran, `\n + `while provider '${providerRef}' still declares this endpoint (its WEBHOOK_ORIGINATOR protocol is enabled). `\n + `To serve it, set \\`${wiring.enablingSetting}: true\\` (${wiring.enablingRequires}); `\n + `or disable that protocol for '${providerRef}' if '${wiring.capability}' is not meant to run.`;\n case WebhookCapabilityWiringState.INITIALIZATION_FAILED:\n return `'${wiring.capability}' initialization failed earlier in startup${wiring.providerRef === null ? '' : ` (provider '${wiring.providerRef}')`}, `\n + `before it wired this endpoint: ${wiring.failure.replace(/[.\\s]+$/u, '')}. The full error is the '${wiring.failureLogLine}' line above; fix that failure and restart.`;\n case WebhookCapabilityWiringState.WIRED:\n if (wiring.providerRef === providerRef && wiring.endpointKey === endpointKey) return null;\n return wiring.endpointKey === null\n ? `'${wiring.capability}' is served by provider '${wiring.providerRef}', which declares no enabled endpoint for it; nothing owns '${providerRef}:${endpointKey}'.`\n : `'${wiring.capability}' is served by '${wiring.providerRef}:${wiring.endpointKey}', not by '${providerRef}:${endpointKey}'; `\n + `disable the WEBHOOK_ORIGINATOR protocol for '${providerRef}', or make it the capability's provider.`;\n default: {\n const unhandled: never = wiring;\n throw new Error(`Unknown webhook capability wiring ${JSON.stringify(unhandled)}`);\n }\n }\n}\n\n/**\n * Render a registration-key list for an operator. `(none)` rather than an empty string, because an\n * absent list and a list that happens to be empty are the two readings this log exists to separate.\n */\nfunction describeRegistrationKeys(keys: readonly string[]): string {\n return keys.length > 0 ? keys.map((key) => `'${key}'`).join(', ') : '(none)';\n}\n\n@injectable()\nexport class WebhookAutoControllerBackendService extends AbstractControllerBackendService {\n\n /** Capability handlers keyed by capability string (e.g., 'billing') */\n private capabilityHandlers = new Map<string, WebhookCapabilityHandler>();\n\n /** What each capability's owning startup step recorded (#3255), keyed by capability. Read when a route is withheld. */\n private capabilityWirings = new Map<string, WebhookCapabilityWiring>();\n\n private webhookHandler: WebhookHandlerBackendService | null = null;\n\n /** The durable inbound pipeline (#1596), when the application declares handlers. */\n private inbound: { registry: InboundHandlerRegistryBackendService; receiver: InboundDeliveryReceiverBackendService } | null = null;\n private applicationEndpointsMounted = false;\n\n /**\n * Pre-loaded endpoint configurations per provider.\n * Populated during initialize() from first-class provider runtime contracts.\n * setupRoutes() reads from this cache (sync) to register routes.\n */\n private loadedEndpoints = new Map<string, Hook_Endpoint[]>();\n\n /** Route paths recorded only after Express accepted their registration. */\n private registeredRoutePaths: string[] = [];\n\n /**\n * Declared endpoints whose route was WITHHELD because the capability could\n * not be dispatched. Kept so the decision is inspectable after startup rather\n * than only visible in a log line that has already scrolled past.\n */\n private withheldRoutes: WebhookRouteWithholding[] = [];\n\n /**\n * Set once {@link registerWebhookRoutes} has run. The mount decision is taken\n * ONCE, from the registration state at that instant, so anything registered\n * afterwards cannot change which routes exist — see\n * {@link registerCapabilityHandler}, which refuses to let that be silent.\n */\n private routesRegistered = false;\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.ErrorBuilderService) errorBuilder: ErrorBuilderBackendService,\n @inject(SAAS_SERVICE_TYPES.ErrorHandlerService) errorHandler: ErrorHandlerService,\n @inject(SAAS_SERVICE_TYPES.BackendProviderRegistryService) private readonly backendProviderRegistry: BackendProviderRegistryBackendService,\n @inject(SAAS_SERVICE_TYPES.ExternalProvidersRegistryService) private readonly externalProvidersRegistry: ExternalProvidersRegistryBackendService,\n ) {\n super(logger, errorBuilder, errorHandler, 'WebhookAutoController');\n }\n\n // ════════════════════════════════════════════════════════════\n // Initialization\n // ════════════════════════════════════════════════════════════\n\n /**\n * Initialize with required dependencies, pre-load endpoint configs, AND\n * register the webhook routes.\n *\n * ── Why routes are registered HERE, not in `setupRoutes()` ──────────────\n *\n * `AbstractControllerBackendService` calls the abstract `setupRoutes()` hook\n * synchronously from *inside its own constructor* (`super(...)`). At that\n * point this controller has NOTHING to register:\n *\n * 1. The webhook handler is not injected via the constructor — it is\n * supplied to `initialize()` by `start-application` after the billing /\n * provider layers are wired.\n * 2. The route SET is data-dependent (one route per provider webhook\n * endpoint), and those endpoint contracts are only knowable after the\n * provider registries have been initialized (which happens later in the\n * startup sequence than DI construction).\n *\n * So `setupRoutes()` is a deliberate no-op (see its JSDoc) and the real,\n * data-dependent route registration runs here — the same lifecycle shape\n * `ControllerResourceBackendService` uses for its per-resource routes.\n *\n * `start-application` calls this BEFORE the controllers registry mounts the\n * router (via `getRouter()`), so the routes added here are present when the\n * master router mounts this controller's router by reference. Errors thrown\n * from webhook handlers propagate to the app-level error middleware\n * (`HttpServerBackendService`), so no router-scoped error handler is needed\n * after these routes.\n */\n /**\n * Mount the application inbound endpoints ON THEIR OWN (#1596, L4). Startup calls this in a FATAL step\n * before {@link initialize}, whose provider pre-loading runs inside a non-fatal catch: an application\n * endpoint left unmounted by an unrelated provider failure would answer 404 while the process looked\n * healthy. Idempotent — {@link initialize} mounts them only if this did not.\n */\n public mountApplicationEndpoints(inbound: { registry: InboundHandlerRegistryBackendService; receiver: InboundDeliveryReceiverBackendService }): void {\n this.inbound = inbound;\n if (this.applicationEndpointsMounted) return;\n this.applicationEndpointsMounted = true;\n this.registerApplicationEndpointRoutes();\n }\n\n public async initialize(\n webhookHandler: WebhookHandlerBackendService,\n inbound?: { registry: InboundHandlerRegistryBackendService; receiver: InboundDeliveryReceiverBackendService },\n ): Promise<void> {\n this.webhookHandler = webhookHandler;\n if (inbound) this.inbound = inbound;\n\n for (const provider of this.backendProviderRegistry.getProvidersWithProtocol(ExternalProvider_ExchangeProtocol_Kind.WEBHOOK_ORIGINATOR)) {\n const providerRef = provider.metadata.ref;\n try {\n if (\n !this.externalProvidersRegistry.isProviderEnabled(\n providerRef,\n ExternalProvider_ExchangeProtocol_Kind.WEBHOOK_ORIGINATOR,\n )\n ) {\n continue;\n }\n\n const config = this.externalProvidersRegistry.getProviderConfiguration(\n providerRef,\n ExternalProvider_ExchangeProtocol_Kind.WEBHOOK_ORIGINATOR,\n );\n // `config.endpoints` is `ReadonlyArray<Hook_Endpoint>` post the\n // 2026-05-06 webhook endpoint reshape: `Hook_Endpoint.displayName`\n // is now optional (matches the runtime emission) and the dead\n // extras (`providerRef` / `path` / `secretBinding`) were dropped\n // from `buildWebhookEndpoints`. The local cache is a\n // `Map<string, Hook_Endpoint[]>`, so we materialize a mutable\n // copy here — the cache was historically `Hook_Endpoint[]`\n // (mutable); preserving that semantics avoids touching every\n // downstream signature.\n const endpoints: Hook_Endpoint[] = [...(config?.endpoints ?? [])];\n if (endpoints.length > 0) {\n this.loadedEndpoints.set(providerRef, endpoints);\n this.logDebug(`Pre-loaded ${endpoints.length} webhook endpoint(s) for ${providerRef}`);\n } else {\n // Genuine contract fault (not the expected \"no webhook providers\"\n // case): the provider is ENABLED for WEBHOOK_ORIGINATOR yet exposes\n // zero endpoints, so it will silently never receive inbound webhooks\n // (e.g. Stripe would 404 on /webhooks/stripe/billing). Surface it\n // once, clearly — this is a mis-sequence, not steady-state noise.\n this.logger.warn(\n `WebhookAutoController: provider '${providerRef}' is enabled for WEBHOOK_ORIGINATOR but exposes no endpoints — no routes will be registered for it`,\n );\n }\n } catch (error) {\n this.logger.warn(`Failed to pre-load webhook protocol for ${providerRef}`, {\n error: (error as Error).message,\n });\n }\n }\n\n this.logDebug(`Webhook auto-controller initialized with ${this.loadedEndpoints.size} provider(s)`);\n\n // Register the routes now that the handler + endpoint contracts are known.\n this.registerWebhookRoutes();\n if (this.inbound) this.mountApplicationEndpoints(this.inbound);\n }\n\n /** Whether a capability handler owns `capability` — asked by the startup step that refuses two owners for one source. */\n public hasCapabilityHandler(capability: string): boolean {\n return this.capabilityHandlers.has(capability);\n }\n\n /**\n * Mount `POST /webhooks/app/{endpointKey}` for each application inbound endpoint (#1596) — EXCEPT one\n * whose verification secret is unset (I1 at mount: `NO_VERIFICATION_SECRET`).\n */\n private registerApplicationEndpointRoutes(): void {\n if (!this.inbound) return;\n const { registry, receiver } = this.inbound;\n for (const endpoint of registry.getApplicationEndpoints()) {\n const routePath = inboundEndpointRoutePath(INBOUND_APPLICATION_ENDPOINT_PROVIDER_REF, endpoint.endpointKey);\n // assurance-control: WILDO.SECURITY.FAIL_CLOSED — an endpoint that cannot verify is not mounted (I1).\n const secretEnvVar = deriveInboundEndpointSecretEnvVarName(endpoint.endpointKey);\n if (!process.env[secretEnvVar]) {\n this.withheldRoutes.push({\n providerRef: INBOUND_APPLICATION_ENDPOINT_PROVIDER_REF,\n endpointKey: endpoint.endpointKey,\n capability: 'inbound',\n routePath,\n reasons: [WebhookRouteWithholdingReason.NO_VERIFICATION_SECRET],\n });\n this.logger.error(\n `WebhookAutoController: NOT registering POST ${routePath} — its verification secret '${secretEnvVar}' is not set. `\n + 'An endpoint that cannot verify a signature must not exist; the sender gets a 404 until the secret is configured and the backend restarts.',\n { endpointKey: endpoint.endpointKey, secretEnvVar, reasons: [WebhookRouteWithholdingReason.NO_VERIFICATION_SECRET] },\n );\n continue;\n }\n this.router.post(routePath, this.asyncHandler(async (req: Request, res: Response) => {\n writeInboundAnswer(res, await receiver.receiveApplicationEndpoint(endpoint, this.rawRequestOf(req)));\n }));\n this.registeredRoutePaths.push(routePath);\n this.logger.info(`Inbound application endpoint registered: POST ${routePath}`);\n }\n }\n\n /**\n * The exact bytes, the headers, and the path and query the request arrived on (a scheme that signs the URL reads\n * them, #3394). Never a re-serialization: a JSON.stringify of `req.body` is not what was signed.\n */\n private rawRequestOf(req: Request): InboundRawRequest {\n const rawBody = Buffer.isBuffer(req.rawBody) ? req.rawBody : Buffer.isBuffer(req.body) ? req.body : undefined;\n return {\n rawBody,\n headers: req.headers,\n ...(req.inboundBodyTooLarge ? { bodyTooLarge: true } : {}),\n ...(typeof req.originalUrl === 'string' ? { requestTarget: req.originalUrl } : {}),\n };\n }\n\n /**\n * Register a capability handler for dispatching processed events.\n * Called at startup by capability modules (e.g., billing module).\n *\n * MUST be called before {@link initialize}. `start-application` satisfies this\n * ordering today — step 4.5 initializes capability modules (which register\n * here) and step 4.6 initializes this controller — and the guard below exists\n * so a future step inserted the other way round is LOUD instead of silent.\n *\n * The failure it catches is genuinely confusing without it: a late-registered\n * handler works perfectly at request time (the map is read per request), but\n * the route it would serve was already withheld at mount time, so the endpoint\n * answers 404 while a handler for it demonstrably exists.\n */\n registerCapabilityHandler(handler: WebhookCapabilityHandler): void {\n this.capabilityHandlers.set(handler.capability, handler);\n\n if (this.routesRegistered) {\n this.logger.error(\n `WebhookAutoController: capability handler for '${handler.capability}' was registered AFTER webhook routes were mounted. `\n + 'Route mounting is decided once, from the registrations present at that moment, so this handler cannot bring back any route '\n + 'that was withheld for a missing handler — those endpoints will keep answering 404. '\n + 'Register capability handlers before WebhookAutoControllerBackendService.initialize() runs.',\n {\n capability: handler.capability,\n withheldRoutes: this.withheldRoutes.map((withholding) => withholding.routePath),\n },\n );\n return;\n }\n\n this.logDebug(`Registered webhook capability handler for ${handler.capability}`);\n }\n\n /**\n * Record what the startup step owning a capability did with it (#3255), so a withheld endpoint of that capability\n * names its cause. Same ordering contract as {@link registerCapabilityHandler}: the mount decision and its log line\n * are taken once, at {@link initialize}, so a record arriving afterwards could explain nothing and says so.\n */\n recordCapabilityWiring(wiring: WebhookCapabilityWiring): void {\n this.capabilityWirings.set(wiring.capability, wiring);\n if (this.routesRegistered) {\n this.logger.error(\n `WebhookAutoController: the wiring of capability '${wiring.capability}' (${wiring.state}) was recorded AFTER webhook routes were mounted, `\n + 'so no withheld route could name it as its cause. Record it before WebhookAutoControllerBackendService.initialize() runs.',\n { capability: wiring.capability, state: wiring.state },\n );\n }\n }\n\n /**\n * Return the sanitized inbound-provider routes that this controller actually\n * registered. Provider configuration, signature material, endpoint payloads,\n * and handler metadata are intentionally absent.\n */\n public getRegisteredWebhookRoutePaths(): ReadonlyArray<string> {\n return [...this.registeredRoutePaths];\n }\n\n /**\n * Return the declared endpoints whose route was deliberately NOT mounted,\n * with the reason. Carries no provider configuration or signature material —\n * only the route identity, which registration was missing, and (#3255) the\n * cause its capability's owner recorded, which may carry a caught error's message.\n */\n public getWithheldWebhookRoutes(): ReadonlyArray<WebhookRouteWithholding> {\n return this.withheldRoutes.map((withholding) => ({\n ...withholding,\n reasons: [...withholding.reasons],\n ...(withholding.capabilityWiring === undefined ? {} : { capabilityWiring: { ...withholding.capabilityWiring } }),\n }));\n }\n\n // ════════════════════════════════════════════════════════════\n // Routes\n // ════════════════════════════════════════════════════════════\n\n /**\n * Required by `AbstractControllerBackendService`, which invokes this hook\n * synchronously from its constructor (`super(...)`). This controller\n * intentionally registers NOTHING here: its route set is data-dependent\n * (one route per provider webhook endpoint) and neither the webhook handler\n * nor the provider endpoint contracts exist at construction time. The real\n * registration happens in `initialize()` / `registerWebhookRoutes()` once\n * that data is available — see `initialize()`'s JSDoc for the full rationale.\n */\n protected setupRoutes(): void {\n // No-op by design — see JSDoc above and `registerWebhookRoutes()`.\n }\n\n /**\n * Register one Express route per pre-loaded provider webhook endpoint —\n * EXCEPT those whose capability cannot actually be dispatched.\n *\n * Invoked from `initialize()` after `webhookHandler` and `loadedEndpoints`\n * have been populated. Idempotent-safe against an empty cache; guards on the\n * handler so a mis-sequenced call fails visibly rather than registering dead\n * routes.\n *\n * ── Why an undispatchable endpoint is WITHHELD rather than mounted ────────\n *\n * A declared endpoint needs two registrations that this controller does not\n * own and cannot create: a `WebhookCapabilityAdapter` (verify + parse, on\n * `WebhookHandlerBackendService`) and a `WebhookCapabilityHandler` (dispatch,\n * here). Both are supplied by the capability module — for `billing`, inside\n * `start-application.initializeBillingServices`, which is deliberately\n * NON-FATAL: if it throws part-way, or if `billing.enabled` is false while the\n * provider is still enabled for `WEBHOOK_ORIGINATOR`, the application boots\n * with the provider's endpoint declared and neither registration present.\n *\n * Mounting a route in that state produces a 500 on every inbound delivery\n * (`No webhook adapter registered for ...`, or `No capability handler for ...`\n * below), and a 500 is precisely the answer that tells a vendor to RETRY — an\n * instruction that can never be satisfied, because no retry supplies a missing\n * startup registration. The endpoint therefore absorbs the vendor's full retry\n * schedule and eventually gets disabled on the vendor's side, while the only\n * local signal is a repeating error log.\n *\n * Not mounting says the true thing instead: this endpoint does not exist. The\n * vendor gets a 404 rather than a retry instruction, and the operator gets one\n * loud, remedy-naming error at startup — the moment the misconfiguration was\n * actually introduced.\n *\n * REJECTED — refusing at BOOT (throwing from here). It is the shape the rest of\n * the registry uses, and it is wrong at this site for three reasons. (1) It\n * would not even be loud: `start-application.initializeWebhookAutoController`\n * wraps `initialize()` in a non-fatal catch that downgrades a throw to a warn,\n * so the net effect would be a quieter log AND the loss of every OTHER\n * provider's working route. (2) It inverts a decision the engine already took\n * explicitly — billing initialization failure is documented as survivable\n * (\"the app can still run without billing\"); a failed optional subsystem must\n * not become a refusal to start. (3) `billing.enabled: false` beside a\n * registered Stripe provider is a COHERENT configuration, and refusing to boot\n * over it would be a false alarm. The check is per-endpoint, so a capability\n * that is wired keeps its route regardless of a sibling that is not.\n */\n private registerWebhookRoutes(): void {\n this.routesRegistered = true;\n\n if (!this.webhookHandler) {\n this.logger.warn('WebhookAutoController: initialize() ran without a webhook handler — no routes registered');\n return;\n }\n\n if (this.loadedEndpoints.size === 0) {\n this.logDebug('No webhook endpoints pre-loaded — no routes registered');\n return;\n }\n\n for (const [providerRef, endpoints] of this.loadedEndpoints) {\n for (const endpoint of endpoints) {\n const routePath = inboundEndpointRoutePath(providerRef, endpoint.key);\n\n const withholding = this.assessRouteDispatchability(providerRef, endpoint, routePath);\n if (withholding) {\n /*\n * The CAUSE, when the capability's owner recorded one (#3255). It explains the two registrations that owner\n * makes — the handler and the adapter — and nothing else, so it is read only when one of those is missing.\n * When it is known it REPLACES their generic remedies below: \"check whether billing initialization was\n * skipped or failed\" sent the test-007 reader to guess at credentials when the answer was one setting.\n */\n const wiring = this.capabilityWirings.get(endpoint.capability);\n const ownerRegistrationMissing = withholding.reasons.includes(WebhookRouteWithholdingReason.NO_CAPABILITY_HANDLER)\n || withholding.reasons.includes(WebhookRouteWithholdingReason.NO_ENDPOINT_ADAPTER);\n const cause = wiring !== undefined && ownerRegistrationMissing ? describeCapabilityWiringCause(wiring, providerRef, endpoint.key) : null;\n if (cause !== null && wiring !== undefined) withholding.capabilityWiring = wiring;\n this.withheldRoutes.push(withholding);\n /*\n * `registeredCapabilities` is what tells a MISSING registration apart from a\n * MISSPELLED one, and it is not decoration.\n *\n * Both sides of this join are typed `string`, so a capability declared\n * `'billing'` and registered `'BILLING'` produces exactly the same\n * NO_CAPABILITY_HANDLER as a module that never initialized. That happened\n * (#620): the remedy sentence that stood here sent the operator to \"billing\n * initialization was skipped or failed\", billing had initialized perfectly,\n * and the endpoint was withheld on every boot for months. Printing the keys\n * that ARE registered makes the two readings distinguishable in the one line\n * an operator sees, without them having to know either module.\n */\n const registeredCapabilities = [...this.capabilityHandlers.keys()];\n const registeredAdapterKeys = this.webhookHandler?.registeredAdapterKeys() ?? [];\n /*\n * The remedy is written PER REASON, because the two are different joins with different\n * remedies and printing both invites the operator to fix the wrong one. An earlier\n * version printed the capability-handler list unconditionally, so a route withheld\n * purely for a missing ADAPTER read \"register the capability module that owns 'BILLING'\n * … registered: 'BILLING'\" — self-contradictory, and pointing away from the join that\n * actually failed.\n */\n const remedies: string[] = [];\n if (cause === null && withholding.reasons.includes(WebhookRouteWithholdingReason.NO_CAPABILITY_HANDLER)) {\n remedies.push(\n `No capability handler owns '${endpoint.capability}'. Registered capability handlers at this moment: `\n + `${describeRegistrationKeys(registeredCapabilities)}. If one of those is the same capability under a `\n + 'different spelling, the declaration and the handler disagree and BOTH must come from the named '\n + 'capability vocabulary (BUILTIN_PROVIDER_CAPABILITY). No startup step recorded why the module owning '\n + `'${endpoint.capability}' did not register it.`,\n );\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.ENGINE_VERIFIED_WITHOUT_INBOUND_HANDLER)) {\n remedies.push(\n `'${providerRef}:${endpoint.key}' is verified by the engine (${endpoint.signatureConfig.algorithm}), which serves it only through an `\n + 'inbound handler: declare one whose source is this provider endpoint.',\n );\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.NO_EVENT_IDENTIFIER)) {\n remedies.push(\n `'${providerRef}:${endpoint.key}' uses ${endpoint.signatureConfig.algorithm}, which signs no delivery id: the provider module must `\n + 'declare `identifyEvent` on the endpoint so its events can be named and deduplicated.',\n );\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.REREAD_TRIGGER_WITHOUT_INBOUND_HANDLER)) {\n remedies.push(\n `'${providerRef}:${endpoint.key}' only triggers re-reads, which an inbound handler performs: declare one whose source is this `\n + 'provider endpoint, and whose scope resolver finds the record the notification names.',\n );\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.DECLARATION_CONTRADICTS_TRIGGER_STRATEGY)) {\n remedies.push(\n `'${providerRef}:${endpoint.key}' (${endpoint.triggerStrategy}) contradicts its strategy: a re-read trigger endpoint declares `\n + '`reReadTrigger` and no `signatureConfig`; every other endpoint declares a `signatureConfig` and no `reReadTrigger`. '\n + 'Fix the provider package.',\n );\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.REREAD_TRIGGER_LIMITS_INVALID)) {\n remedies.push(`'${providerRef}:${endpoint.key}' declares a coalescing window or rate limit that is not a positive integer. Fix the provider package.`);\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.REREAD_TRIGGER_WITHOUT_RATE_BUDGET)) {\n remedies.push(\n `'${providerRef}' declares no vendor rate budget, so the re-reads its unverified notifications cause cannot be held to a `\n + 'share that leaves polling the rest: declare `rateBudgets` on its connection (or `remoteCallSemantics.maxRequestsPerMinute`).',\n );\n }\n if (cause === null && withholding.reasons.includes(WebhookRouteWithholdingReason.NO_ENDPOINT_ADAPTER)) {\n remedies.push(\n `No adapter is registered for '${providerRef}:${endpoint.key}'. Registered adapter keys at this moment: `\n + `${describeRegistrationKeys(registeredAdapterKeys)}. Note this join is keyed on the endpoint KEY (the URL `\n + 'segment), not on its capability.',\n );\n }\n this.logger.error(\n `WebhookAutoController: NOT registering POST ${routePath} — the endpoint is declared but cannot be dispatched `\n + `(${withholding.reasons.join(', ')})${cause === null ? '.' : `, because ${cause}`} A route mounted in this state can only ever answer 500, which instructs the `\n + 'vendor to retry an inbound event that no retry can make processable. Withholding the route so the vendor gets a '\n + '404 instead.'\n // A known cause carries its own remedy; the generic one below is for a registration nothing explained.\n + (remedies.length === 0 ? '' : ` Remedy: ${remedies.join(' ')} Every registration must happen before `\n + `WebhookAutoControllerBackendService.initialize() runs; otherwise, disable the WEBHOOK_ORIGINATOR protocol for `\n + `provider '${providerRef}'.`),\n {\n providerRef,\n endpointKey: endpoint.key,\n capability: endpoint.capability,\n registeredCapabilities,\n registeredAdapterKeys,\n routePath,\n reasons: withholding.reasons,\n ...(withholding.capabilityWiring === undefined ? {} : { capabilityWiring: withholding.capabilityWiring }),\n },\n );\n continue;\n }\n\n this.router.post(\n routePath,\n // Defense-in-depth for a future streaming mount. If this controller is\n // ever assigned the RAW_REQUEST_STREAM mount phase, this express.raw()\n // makes req.body the raw Buffer. Under the\n // current master-router mount it is an inert no-op: the global\n // express.json (HttpServerBackendService.setupBodyParsing) parses the\n // body first and sets req._body, so the signature-faithful bytes come\n // from req.rawBody — captured by that same express.json `verify` hook.\n // handleWebhookRequest reads rawBody first, then falls back to a Buffer\n // req.body for the streaming case.\n express.raw({ type: 'application/json' }),\n this.asyncHandler(async (req: Request, res: Response, _next: NextFunction) => {\n const inboundHandler = this.inbound?.registry.getProviderEndpointHandler(providerRef, endpoint.key);\n if (inboundHandler && this.inbound) {\n writeInboundAnswer(res, await this.inbound.receiver.receiveProviderEndpoint(providerRef, endpoint, inboundHandler, this.rawRequestOf(req)));\n return;\n }\n // A re-read trigger is never verified, so it never reaches the signed path (#2909 review F8): the mount gate\n // requires its handler, and one removed after mount is answered as every such request is, and logged.\n if (isReReadTriggerEndpoint(endpoint)) {\n this.logger.error('A re-read trigger notification arrived for an endpoint whose inbound handler is gone; dropped', { providerRef, endpointKey: endpoint.key });\n res.status(202).json({ received: true });\n return;\n }\n // Over the body parser's limit (#3395): no body was read, so there is nothing to verify or dispatch.\n if (req.inboundBodyTooLarge) {\n res.status(413).json({ error: 'Payload too large' });\n return;\n }\n await this.handleWebhookRequest(providerRef, endpoint, req, res);\n }),\n );\n\n this.registeredRoutePaths.push(routePath);\n this.logger.info(`Webhook endpoint registered: POST ${routePath}`);\n }\n }\n }\n\n /**\n * Whether `providerRef`'s re-reads spend a declared vendor budget (#2909): its own `maxRequestsPerMinute`, or\n * `rateBudgets` on the connection its grant belongs to. The same two sources `ConnectionRateBudgetBackendService` builds\n * the budgets from, so a \"yes\" here is a budget the triggered share is cut from.\n */\n private declaresVendorRateBudget(providerRef: string): boolean {\n const registry = this.externalProvidersRegistry;\n const own = registry.getProviderRuntimeContract(providerRef, ExternalProvider_ExchangeProtocol_Kind.REST_API);\n if (own?.kind === ProviderProtocolRuntimeKind.REST && own.remoteCallSemantics?.maxRequestsPerMinute !== undefined) return true;\n const connectionRef = registry.resolveCredentialConnectionRef(providerRef) ?? providerRef;\n const connection = registry.getProviderRuntimeContract(connectionRef, ExternalProvider_ExchangeProtocol_Kind.REST_API);\n return connection?.kind === ProviderProtocolRuntimeKind.REST && (connection.rateBudgets?.length ?? 0) > 0;\n }\n\n /**\n * Decide whether a declared endpoint can actually be served, and if not, say\n * which registration is missing.\n *\n * Returns `null` when the route is dispatchable. Both prerequisites are\n * evaluated (rather than short-circuiting on the first) so an operator gets\n * the WHOLE remedy in one log line instead of fixing one registration and\n * meeting the next on the following restart.\n */\n private assessRouteDispatchability(\n providerRef: string,\n endpoint: Hook_Endpoint,\n routePath: string,\n ): WebhookRouteWithholding | null {\n const reasons: WebhookRouteWithholdingReason[] = [];\n\n // A provider endpoint bound to an inbound handler (#1596) is dispatched by that handler, so it needs\n // no capability handler — only the provider's adapter, which still verifies it.\n const boundToInboundHandler = Boolean(this.inbound?.registry.getProviderEndpointHandler(providerRef, endpoint.key));\n\n // A re-read trigger (#2909) is handled by the engine and served only by an inbound handler: no capability handler,\n // no adapter, no signature.\n const reReadTrigger = isReReadTriggerEndpoint(endpoint);\n if (reReadTrigger !== (endpoint.reReadTrigger !== undefined) || reReadTrigger === (endpoint.signatureConfig !== undefined)) {\n reasons.push(WebhookRouteWithholdingReason.DECLARATION_CONTRADICTS_TRIGGER_STRATEGY);\n }\n if (reReadTrigger) {\n if (!boundToInboundHandler) reasons.push(WebhookRouteWithholdingReason.REREAD_TRIGGER_WITHOUT_INBOUND_HANDLER);\n if (endpoint.reReadTrigger && !reReadTriggerLimitsAreSound(endpoint.reReadTrigger)) reasons.push(WebhookRouteWithholdingReason.REREAD_TRIGGER_LIMITS_INVALID);\n if (!this.declaresVendorRateBudget(providerRef)) reasons.push(WebhookRouteWithholdingReason.REREAD_TRIGGER_WITHOUT_RATE_BUDGET);\n return reasons.length === 0 ? null : { providerRef, endpointKey: endpoint.key, capability: endpoint.capability, routePath, reasons };\n }\n if (!boundToInboundHandler && !this.capabilityHandlers.has(endpoint.capability)) {\n reasons.push(WebhookRouteWithholdingReason.NO_CAPABILITY_HANDLER);\n }\n // An engine-verified endpoint (Svix #1600, Slack v0 and the Bot Framework token #2659) is verified by engine code\n // and takes no adapter — and so is served only by an inbound handler, never by the capability path.\n if (isEngineVerifiedWebhookEndpoint(endpoint)) {\n if (!boundToInboundHandler) reasons.push(WebhookRouteWithholdingReason.ENGINE_VERIFIED_WITHOUT_INBOUND_HANDLER);\n if (!engineSchemeSignsDeliveryId(endpoint) && !endpoint.identifyEvent) reasons.push(WebhookRouteWithholdingReason.NO_EVENT_IDENTIFIER);\n if (!hookSignatureDeclarationIsComplete(endpoint.signatureConfig)) reasons.push(WebhookRouteWithholdingReason.SIGNATURE_DECLARATION_INCOMPLETE);\n } else if (!this.webhookHandler?.hasAdapter(providerRef, endpoint.key)) {\n reasons.push(WebhookRouteWithholdingReason.NO_ENDPOINT_ADAPTER);\n }\n\n if (reasons.length === 0) {\n return null;\n }\n return { providerRef, endpointKey: endpoint.key, capability: endpoint.capability, routePath, reasons };\n }\n\n // ════════════════════════════════════════════════════════════\n // Handler\n // ════════════════════════════════════════════════════════════\n\n private async handleWebhookRequest(\n providerRef: string,\n endpoint: Hook_Endpoint,\n req: Request,\n res: Response,\n ): Promise<void> {\n if (!this.webhookHandler) {\n res.status(503).json({ error: 'Webhook handler not initialized' });\n return;\n }\n\n // Raw request bytes for signature verification. Order matters:\n // 1. req.rawBody — captured by the global express.json `verify` hook\n // (HttpServerBackendService.setupBodyParsing). This is the provider's\n // EXACT original payload and the ONLY byte-faithful source under the\n // current master-router mount, where global express.json parses the\n // body before this route runs (making the per-route express.raw() a\n // no-op, so req.body is a parsed object here).\n // 2. Buffer req.body — only populated if this controller is ever\n // streaming-mounted before body parsing (per-route express.raw() fires).\n // 3. string / JSON.stringify — last-resort fallbacks; JSON.stringify will\n // NOT byte-match the provider (key ordering / whitespace), so it exists\n // only to avoid a crash, never as a correctness path for signatures.\n const rawBody = Buffer.isBuffer(req.rawBody)\n ? req.rawBody.toString('utf-8')\n : Buffer.isBuffer(req.body)\n ? req.body.toString('utf-8')\n : typeof req.body === 'string'\n ? req.body\n : JSON.stringify(req.body);\n\n let result: Awaited<ReturnType<WebhookHandlerBackendService['processWebhook']>> | null = null;\n try {\n result = await this.webhookHandler.processWebhook({\n providerRef,\n endpointKey: endpoint.key,\n endpoint,\n rawBody,\n headers: req.headers as Record<string, string>,\n });\n\n // null = idempotent duplicate or unparseable event — already acknowledged\n if (!result) {\n res.status(200).json({ received: true });\n return;\n }\n\n // Dispatch to capability handler.\n //\n // Defence in depth only: `registerWebhookRoutes` refuses to MOUNT a route\n // whose capability has no handler, so this branch is unreachable while that\n // gate holds — reaching it means the handler map was mutated after mounting\n // (which `registerCapabilityHandler` refuses to do silently). The throw is\n // kept rather than removed because the alternative — dispatching to\n // `undefined` — would 500 anyway, with no explanation.\n const handler = this.capabilityHandlers.get(endpoint.capability);\n if (handler) {\n await handler.handleEvent(result.executionContext, result.parsedEvent);\n } else {\n throw new Error(`No capability handler for ${endpoint.capability} on ${providerRef}/${endpoint.key}`);\n }\n\n await this.webhookHandler.markWebhookProcessed(result.idempotencyKey);\n res.status(200).json({ received: true });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : undefined;\n\n /*\n * `isWildoBackendError` + `.type`, never `(error as any).errorType`.\n *\n * `ErrorBuilderBackendService.buildError` stamps the field **`type`**; nothing in the engine\n * throws an object carrying `errorType`. So this predicate was `undefined === 'AUTHORIZATION'`\n * — permanently false — and every signature failure fell into the 500 branch below, which\n * tells the vendor to RETRY a delivery no retry can make valid. On Stripe that absorbs the\n * full retry schedule and can get the endpoint disabled vendor-side.\n *\n * It went unnoticed because until 2026-09-10 this route was WITHHELD at startup (#620), so\n * the whole handler was unreachable. Fixing the mount is what made this live.\n */\n if (isWildoBackendError(error) && error.type === ErrorType.AUTHORIZATION) {\n this.logDebug('Webhook signature verification failed', { providerRef, endpointKey: endpoint.key });\n res.status(401).json({ error: 'Invalid signature' });\n return;\n }\n\n /*\n * All other errors → 500 (trigger provider retry).\n *\n * Projected through `projectCaughtErrorLogFields` rather than reported as\n * `(error as Error).message`, because a `WildoError_Backend` IS NOT an `Error`: it has no\n * `message` property, so that read yields `undefined` and the `?? 'Unknown error'` fallback\n * fires. This line published the literal string **\"Unknown error\"** for the entire class of\n * error the engine actually raises — the classified ones, carrying the type, the custom\n * message reference and the context naming what failed.\n *\n * Measured 2026-09-10 while executing #544: a forwarded Stripe `checkout.session.completed`\n * failed, and this LOG LINE carried `\"error\":\"Unknown error\"` and nothing else, so the\n * delivery failure was unreadable and the provider retried against a fault nobody could name.\n * (The wire response is the unconditional `{ error: 'Processing failed' }` below and never\n * carried that string — naming the right surface matters, because the next reader will go\n * looking where this comment points.) `errorMessage` is still passed for a plain `Error`: a\n * `TypeError` from a bad read has a real message and no classified fields.\n */\n this.logger.error('Webhook processing failed', {\n providerRef,\n endpointKey: endpoint.key,\n // Only for a plain `Error` (a TypeError from a bad read has a real message and no classified\n // fields). Omitted rather than defaulted to the string \"Unknown error\": that literal is what\n // this line used to publish for every classified error, and leaving it in place would keep\n // it findable by an alert grep that should now be finding the projected cause instead.\n ...(errorMessage === undefined ? {} : { error: errorMessage }),\n ...projectCaughtErrorLogFields(error),\n });\n await this.webhookHandler.releaseWebhookClaim(result?.idempotencyKey);\n res.status(500).json({ error: 'Processing failed' });\n }\n }\n}\n"]}
1
+ {"version":3,"file":"webhook-auto-controller.backend.service.js","sourceRoot":"","sources":["../../../../../src/notifications/webhooks/controllers/webhook-auto-controller.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Webhook Auto-Controller Backend Service\n *\n * Auto-registers webhook routes from provider registry definitions.\n * At startup, iterates all providers with WEBHOOK_ORIGINATOR protocol,\n * then iterates each provider's endpoints, and registers:\n * POST /webhooks/{providerRef}/{endpointKey}\n *\n * One provider declares the protocol today, and it declares one endpoint:\n * POST /webhooks/stripe/billing\n *\n * A second provider registers here the moment it declares `WEBHOOK_ORIGINATOR` with its own\n * `endpoints`; no edit to this controller is needed.\n *\n * This replaces manual per-provider webhook controllers.\n */\n\nimport { injectable, inject, optional } from 'inversify';\nimport express from 'express';\nimport type { Request, Response, NextFunction } from 'express';\nimport {\n ExternalProvider_ExchangeProtocol_Kind,\n Hook_AcknowledgementEncoding,\n ProviderProtocolRuntimeKind,\n hookSignatureDeclarationIsComplete,\n isReReadTriggerEndpoint,\n reReadTriggerLimitsAreSound,\n type Hook_Endpoint,\n type WebhookCapabilityHandler,\n} from '@wildo-ai/external-connectors-models';\nimport { ErrorType, HttpMethod, isWildoBackendError } from '@wildo-ai/saas-models';\n\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport type { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';\nimport type { ErrorHandlerService } from '~wildo-backend-lib/errors/services/error-handler.backend.service';\nimport type { BackendProviderRegistryBackendService } from '~wildo-backend-lib/external-providers/services/backend-provider-registry.backend.service';\nimport type { ExternalProvidersRegistryBackendService } from '~wildo-backend-lib/external-providers/services/external-providers-registry.backend.service';\nimport { AbstractControllerBackendService } from '~wildo-backend-lib/base-classes/services/controllers/abstract-controller.backend.service';\nimport type { WebhookHandlerBackendService } from '~wildo-backend-lib/notifications/webhooks/services/webhook-handler.backend.service';\nimport { engineSchemeSignsDeliveryId, isEngineVerifiedWebhookEndpoint } from '~wildo-backend-lib/notifications/webhooks/services/webhook-handler.backend.service';\nimport { projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport type { InboundHandlerRegistryBackendService } from '~wildo-backend-lib/inbound/services/inbound-handler-registry.backend.service';\nimport type { InboundDeliveryReceiverBackendService, InboundRawRequest, InboundReceiveAnswer } from '~wildo-backend-lib/inbound/services/inbound-delivery-receiver.backend.service';\nimport { 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';\nimport type { InboundLargeBodyRoutesBackendService } from '~wildo-backend-lib/runtime/services/utils/inbound-endpoint-raw-body.backend.utils';\n\n/**\n * Why a declared webhook endpoint did NOT get an Express route.\n *\n * A closed vocabulary rather than a free string: each member names a DIFFERENT\n * missing registration, with a different remedy, and an operator reading the\n * startup log has to be able to tell them apart. The two are independent — an\n * endpoint can be missing either, or both.\n */\nexport enum WebhookRouteWithholdingReason {\n /**\n * No {@link WebhookCapabilityHandler} is registered for the endpoint's\n * `capability`. The route would reach `handleWebhookRequest`, complete\n * signature verification and idempotency claiming, then fail at dispatch.\n */\n NO_CAPABILITY_HANDLER = 'NO_CAPABILITY_HANDLER',\n /**\n * No `WebhookCapabilityAdapter` is registered for `providerRef:endpointKey`\n * on {@link WebhookHandlerBackendService}. The route would fail at the very\n * top of `processWebhook`, before signature verification.\n */\n NO_ENDPOINT_ADAPTER = 'NO_ENDPOINT_ADAPTER',\n /**\n * An APPLICATION inbound endpoint (#1596) whose verification secret — the variable\n * `deriveInboundEndpointSecretEnvVarName(endpointKey)` names — is unset at mount. An endpoint that\n * cannot verify must not exist: mounting it would answer 401 to every delivery forever, which tells\n * the sender nothing an operator can act on. The request-time refusal stays as well, because a\n * secret can disappear after mount.\n */\n NO_VERIFICATION_SECRET = 'NO_VERIFICATION_SECRET',\n /**\n * An ENGINE-verified provider endpoint (Svix, Slack v0, the Bot Framework token, Ed25519) that no inbound handler takes\n * (#2659). Engine schemes are served only on the durable inbound path; the capability path needs a provider\n * adapter such an endpoint cannot have, so the route would answer 500 on every delivery.\n */\n ENGINE_VERIFIED_WITHOUT_INBOUND_HANDLER = 'ENGINE_VERIFIED_WITHOUT_INBOUND_HANDLER',\n /**\n * An engine-verified provider endpoint whose scheme signs no delivery id (Slack v0, the Bot Framework token, Ed25519) and\n * which declares no `identifyEvent` (#2659). Nothing would name its events, so none could be stored.\n */\n NO_EVENT_IDENTIFIER = 'NO_EVENT_IDENTIFIER',\n /**\n * An engine-verified provider endpoint whose `signatureConfig` omits something its scheme reads (#3393): an `ED25519`\n * endpoint without its signature header, timestamp header or signed-content separator. The engine does not guess a\n * vendor's construction, so every delivery would be refused. A provider package defect.\n */\n SIGNATURE_DECLARATION_INCOMPLETE = 'SIGNATURE_DECLARATION_INCOMPLETE',\n /**\n * A re-read trigger endpoint (`Hook_TriggerStrategy.WEBHOOK_TRIGGERS_POLL`, #2909) that no inbound handler takes. Its\n * notifications only cause a re-read, which a handler performs; with none, nothing could act on them.\n */\n REREAD_TRIGGER_WITHOUT_INBOUND_HANDLER = 'REREAD_TRIGGER_WITHOUT_INBOUND_HANDLER',\n /**\n * The endpoint's declaration contradicts its trigger strategy (#2909): a re-read trigger endpoint that carries a\n * `signatureConfig` (nothing would verify it, so it would only look like a control) or no `reReadTrigger`, or any other\n * endpoint with no `signatureConfig` or with a `reReadTrigger`. A provider package defect.\n */\n DECLARATION_CONTRADICTS_TRIGGER_STRATEGY = 'DECLARATION_CONTRADICTS_TRIGGER_STRATEGY',\n /**\n * A re-read trigger endpoint whose `coalescingWindowSeconds` or `rateLimit` is not a positive integer (#2909 review\n * F6): a window of 0 would fail every request, and a negative or fractional one would coalesce nothing as declared.\n */\n REREAD_TRIGGER_LIMITS_INVALID = 'REREAD_TRIGGER_LIMITS_INVALID',\n /**\n * A re-read trigger endpoint whose provider declares no vendor rate budget (#2909 review F5): no `rateBudgets` on its\n * connection and no `maxRequestsPerMinute` of its own. The re-reads an unverified notification causes spend only a\n * share of the vendor's budget so polling keeps the rest; with none declared there is nothing to reserve, and a flood\n * would spend the vendor's real (undeclared) limit before polling could. Decided: refuse rather than reserve nothing.\n */\n REREAD_TRIGGER_WITHOUT_RATE_BUDGET = 'REREAD_TRIGGER_WITHOUT_RATE_BUDGET',\n}\n\n/**\n * Write an inbound answer (#2659): the endpoint's acknowledgement when it declared one, the engine's JSON otherwise.\n * An acknowledgement is always a 200: it answers a request the engine accepted.\n */\nexport function writeInboundAnswer(res: Response, answer: InboundReceiveAnswer): void {\n const acknowledgement = answer.acknowledgement;\n if (!acknowledgement) {\n res.status(answer.status).json(answer.body);\n return;\n }\n switch (acknowledgement.encoding) {\n case Hook_AcknowledgementEncoding.EMPTY:\n res.status(200).end();\n return;\n case Hook_AcknowledgementEncoding.JSON:\n res.status(200).json(acknowledgement.body);\n return;\n case Hook_AcknowledgementEncoding.TEXT:\n res.status(200).type('text/plain; charset=utf-8').send(acknowledgement.body);\n return;\n default: {\n const unhandled: never = acknowledgement;\n throw new Error(`Unknown acknowledgement encoding: ${JSON.stringify(unhandled)}`);\n }\n }\n}\n\n/** One declared endpoint whose route was deliberately not mounted, and why. */\nexport interface WebhookRouteWithholding {\n providerRef: string;\n endpointKey: string;\n capability: string;\n routePath: string;\n reasons: WebhookRouteWithholdingReason[];\n /**\n * What the startup step owning the endpoint's capability recorded about it, when one did (#3255). Present only\n * when it explains the withholding: it is the CAUSE, where {@link reasons} is the missing registration.\n */\n capabilityWiring?: WebhookCapabilityWiring;\n}\n\n/**\n * What the startup step that OWNS a webhook capability did with it (#3255) — billing's initializer, for `BILLING`.\n *\n * {@link WebhookRouteWithholdingReason} says which registration is missing; this says WHY the module that registers it\n * did not. The two are separate questions because the controller can measure the first and cannot know the second:\n * on app-creation-test-007 the line read `NO_CAPABILITY_HANDLER, NO_ENDPOINT_ADAPTER` with \"check whether billing\n * initialization was skipped or failed\", and the reader guessed \"no local Stripe credentials\", which is the one cause\n * that cannot produce it (billing enabled with no secret fails startup before any route is assessed). Recorded by the\n * capability's owner, read here, so the withholding line names the cause instead of listing the possibilities.\n */\nexport enum WebhookCapabilityWiringState {\n /**\n * The application does not enable the capability, so its module never ran — while a provider still declares an\n * endpoint for it (its `WEBHOOK_ORIGINATOR` protocol is enabled). A coherent configuration, said plainly: enable the\n * capability, or disable the provider's protocol.\n */\n NOT_ENABLED = 'NOT_ENABLED',\n /** The module ran and failed non-fatally before it wired the endpoint; the failure is carried. */\n INITIALIZATION_FAILED = 'INITIALIZATION_FAILED',\n /**\n * The module wired the capability, to the endpoint named — or to none, when its provider declares no enabled endpoint\n * for it. A withheld endpoint of a WIRED capability is a different provider's (or key's) endpoint nothing owns.\n */\n WIRED = 'WIRED',\n}\n\n/** One capability's wiring record (see {@link WebhookCapabilityWiringState}). */\nexport type WebhookCapabilityWiring =\n | {\n readonly capability: string;\n readonly state: WebhookCapabilityWiringState.NOT_ENABLED;\n /** The setting that enables it, named as the application author writes it (`billing.enabled`). */\n readonly enablingSetting: string;\n /** Where that setting is authored, relative to the application root. */\n readonly settingLocation: string;\n /**\n * What turning it on also needs, in the owner's words — billing needs a provider ref and that provider's secret, and\n * turning the switch on without them fails startup instead (`PROVIDER_REF_UNSET`, `SECRET_MISSING`).\n */\n readonly enablingRequires: string;\n /** The value found: `false`, or `null` when the setting (or its section) is absent. */\n readonly declaredValue: boolean | null;\n }\n | {\n readonly capability: string;\n readonly state: WebhookCapabilityWiringState.INITIALIZATION_FAILED;\n readonly providerRef: string | null;\n /** The failure as `describeCaughtError` renders it — the message of the error logged earlier at startup. */\n readonly failure: string;\n /** The startup log line that carries the full failure, so the reader can find it. */\n readonly failureLogLine: string;\n }\n | {\n readonly capability: string;\n readonly state: WebhookCapabilityWiringState.WIRED;\n readonly providerRef: string;\n /** The endpoint key the capability serves, or `null` when its provider declares no enabled endpoint for it. */\n readonly endpointKey: string | null;\n };\n\n/**\n * The CAUSE sentence of a withheld endpoint's line, from its capability's wiring record — or `null` when the record\n * explains nothing about THIS endpoint (a capability wired to this very endpoint is withheld for another reason, which\n * the per-reason remedies already name).\n */\nexport function describeCapabilityWiringCause(wiring: WebhookCapabilityWiring, providerRef: string, endpointKey: string): string | null {\n switch (wiring.state) {\n case WebhookCapabilityWiringState.NOT_ENABLED:\n return `'${wiring.capability}' is not enabled: \\`${wiring.enablingSetting}\\` is `\n + `${wiring.declaredValue === null ? 'not set' : String(wiring.declaredValue)} in ${wiring.settingLocation}, so its module never ran, `\n + `while provider '${providerRef}' still declares this endpoint (its WEBHOOK_ORIGINATOR protocol is enabled). `\n + `To serve it, set \\`${wiring.enablingSetting}: true\\` (${wiring.enablingRequires}); `\n + `or disable that protocol for '${providerRef}' if '${wiring.capability}' is not meant to run.`;\n case WebhookCapabilityWiringState.INITIALIZATION_FAILED:\n return `'${wiring.capability}' initialization failed earlier in startup${wiring.providerRef === null ? '' : ` (provider '${wiring.providerRef}')`}, `\n + `before it wired this endpoint: ${wiring.failure.replace(/[.\\s]+$/u, '')}. The full error is the '${wiring.failureLogLine}' line above; fix that failure and restart.`;\n case WebhookCapabilityWiringState.WIRED:\n if (wiring.providerRef === providerRef && wiring.endpointKey === endpointKey) return null;\n return wiring.endpointKey === null\n ? `'${wiring.capability}' is served by provider '${wiring.providerRef}', which declares no enabled endpoint for it; nothing owns '${providerRef}:${endpointKey}'.`\n : `'${wiring.capability}' is served by '${wiring.providerRef}:${wiring.endpointKey}', not by '${providerRef}:${endpointKey}'; `\n + `disable the WEBHOOK_ORIGINATOR protocol for '${providerRef}', or make it the capability's provider.`;\n default: {\n const unhandled: never = wiring;\n throw new Error(`Unknown webhook capability wiring ${JSON.stringify(unhandled)}`);\n }\n }\n}\n\n/**\n * Render a registration-key list for an operator. `(none)` rather than an empty string, because an\n * absent list and a list that happens to be empty are the two readings this log exists to separate.\n */\nfunction describeRegistrationKeys(keys: readonly string[]): string {\n return keys.length > 0 ? keys.map((key) => `'${key}'`).join(', ') : '(none)';\n}\n\n@injectable()\nexport class WebhookAutoControllerBackendService extends AbstractControllerBackendService {\n\n /** Capability handlers keyed by capability string (e.g., 'billing') */\n private capabilityHandlers = new Map<string, WebhookCapabilityHandler>();\n\n /** What each capability's owning startup step recorded (#3255), keyed by capability. Read when a route is withheld. */\n private capabilityWirings = new Map<string, WebhookCapabilityWiring>();\n\n private webhookHandler: WebhookHandlerBackendService | null = null;\n\n /** The durable inbound pipeline (#1596), when the application declares handlers. */\n private inbound: { registry: InboundHandlerRegistryBackendService; receiver: InboundDeliveryReceiverBackendService } | null = null;\n private applicationEndpointsMounted = false;\n\n /**\n * Pre-loaded endpoint configurations per provider.\n * Populated during initialize() from first-class provider runtime contracts.\n * setupRoutes() reads from this cache (sync) to register routes.\n */\n private loadedEndpoints = new Map<string, Hook_Endpoint[]>();\n\n /** Route paths recorded only after Express accepted their registration. */\n private registeredRoutePaths: string[] = [];\n\n /**\n * Declared endpoints whose route was WITHHELD because the capability could\n * not be dispatched. Kept so the decision is inspectable after startup rather\n * than only visible in a log line that has already scrolled past.\n */\n private withheldRoutes: WebhookRouteWithholding[] = [];\n\n /**\n * Set once {@link registerWebhookRoutes} has run. The mount decision is taken\n * ONCE, from the registration state at that instant, so anything registered\n * afterwards cannot change which routes exist — see\n * {@link registerCapabilityHandler}, which refuses to let that be silent.\n */\n private routesRegistered = false;\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.ErrorBuilderService) errorBuilder: ErrorBuilderBackendService,\n @inject(SAAS_SERVICE_TYPES.ErrorHandlerService) errorHandler: ErrorHandlerService,\n @inject(SAAS_SERVICE_TYPES.BackendProviderRegistryService) private readonly backendProviderRegistry: BackendProviderRegistryBackendService,\n @inject(SAAS_SERVICE_TYPES.ExternalProvidersRegistryService) private readonly externalProvidersRegistry: ExternalProvidersRegistryBackendService,\n /** #3395: where a provider endpoint reading more than the global parsers do is declared, for the body parser to read. */\n @inject(SAAS_SERVICE_TYPES.InboundLargeBodyRoutes) @optional() private readonly largeBodyRoutes?: Pick<InboundLargeBodyRoutesBackendService, 'declare'>,\n ) {\n super(logger, errorBuilder, errorHandler, 'WebhookAutoController');\n }\n\n // ════════════════════════════════════════════════════════════\n // Initialization\n // ════════════════════════════════════════════════════════════\n\n /**\n * Initialize with required dependencies, pre-load endpoint configs, AND\n * register the webhook routes.\n *\n * ── Why routes are registered HERE, not in `setupRoutes()` ──────────────\n *\n * `AbstractControllerBackendService` calls the abstract `setupRoutes()` hook\n * synchronously from *inside its own constructor* (`super(...)`). At that\n * point this controller has NOTHING to register:\n *\n * 1. The webhook handler is not injected via the constructor — it is\n * supplied to `initialize()` by `start-application` after the billing /\n * provider layers are wired.\n * 2. The route SET is data-dependent (one route per provider webhook\n * endpoint), and those endpoint contracts are only knowable after the\n * provider registries have been initialized (which happens later in the\n * startup sequence than DI construction).\n *\n * So `setupRoutes()` is a deliberate no-op (see its JSDoc) and the real,\n * data-dependent route registration runs here — the same lifecycle shape\n * `ControllerResourceBackendService` uses for its per-resource routes.\n *\n * `start-application` calls this BEFORE the controllers registry mounts the\n * router (via `getRouter()`), so the routes added here are present when the\n * master router mounts this controller's router by reference. Errors thrown\n * from webhook handlers propagate to the app-level error middleware\n * (`HttpServerBackendService`), so no router-scoped error handler is needed\n * after these routes.\n */\n /**\n * Mount the application inbound endpoints ON THEIR OWN (#1596, L4). Startup calls this in a FATAL step\n * before {@link initialize}, whose provider pre-loading runs inside a non-fatal catch: an application\n * endpoint left unmounted by an unrelated provider failure would answer 404 while the process looked\n * healthy. Idempotent — {@link initialize} mounts them only if this did not.\n */\n public mountApplicationEndpoints(inbound: { registry: InboundHandlerRegistryBackendService; receiver: InboundDeliveryReceiverBackendService }): void {\n this.inbound = inbound;\n if (this.applicationEndpointsMounted) return;\n this.applicationEndpointsMounted = true;\n this.registerApplicationEndpointRoutes();\n }\n\n public async initialize(\n webhookHandler: WebhookHandlerBackendService,\n inbound?: { registry: InboundHandlerRegistryBackendService; receiver: InboundDeliveryReceiverBackendService },\n ): Promise<void> {\n this.webhookHandler = webhookHandler;\n if (inbound) this.inbound = inbound;\n\n for (const provider of this.backendProviderRegistry.getProvidersWithProtocol(ExternalProvider_ExchangeProtocol_Kind.WEBHOOK_ORIGINATOR)) {\n const providerRef = provider.metadata.ref;\n try {\n if (\n !this.externalProvidersRegistry.isProviderEnabled(\n providerRef,\n ExternalProvider_ExchangeProtocol_Kind.WEBHOOK_ORIGINATOR,\n )\n ) {\n continue;\n }\n\n const config = this.externalProvidersRegistry.getProviderConfiguration(\n providerRef,\n ExternalProvider_ExchangeProtocol_Kind.WEBHOOK_ORIGINATOR,\n );\n // `config.endpoints` is `ReadonlyArray<Hook_Endpoint>` post the\n // 2026-05-06 webhook endpoint reshape: `Hook_Endpoint.displayName`\n // is now optional (matches the runtime emission) and the dead\n // extras (`providerRef` / `path` / `secretBinding`) were dropped\n // from `buildWebhookEndpoints`. The local cache is a\n // `Map<string, Hook_Endpoint[]>`, so we materialize a mutable\n // copy here — the cache was historically `Hook_Endpoint[]`\n // (mutable); preserving that semantics avoids touching every\n // downstream signature.\n const endpoints: Hook_Endpoint[] = [...(config?.endpoints ?? [])];\n if (endpoints.length > 0) {\n this.loadedEndpoints.set(providerRef, endpoints);\n this.logDebug(`Pre-loaded ${endpoints.length} webhook endpoint(s) for ${providerRef}`);\n } else {\n // Genuine contract fault (not the expected \"no webhook providers\"\n // case): the provider is ENABLED for WEBHOOK_ORIGINATOR yet exposes\n // zero endpoints, so it will silently never receive inbound webhooks\n // (e.g. Stripe would 404 on /webhooks/stripe/billing). Surface it\n // once, clearly — this is a mis-sequence, not steady-state noise.\n this.logger.warn(\n `WebhookAutoController: provider '${providerRef}' is enabled for WEBHOOK_ORIGINATOR but exposes no endpoints — no routes will be registered for it`,\n );\n }\n } catch (error) {\n this.logger.warn(`Failed to pre-load webhook protocol for ${providerRef}`, {\n error: (error as Error).message,\n });\n }\n }\n\n this.logDebug(`Webhook auto-controller initialized with ${this.loadedEndpoints.size} provider(s)`);\n\n // Register the routes now that the handler + endpoint contracts are known.\n this.registerWebhookRoutes();\n if (this.inbound) this.mountApplicationEndpoints(this.inbound);\n }\n\n /** Whether a capability handler owns `capability` — asked by the startup step that refuses two owners for one source. */\n public hasCapabilityHandler(capability: string): boolean {\n return this.capabilityHandlers.has(capability);\n }\n\n /**\n * Mount `POST /webhooks/app/{endpointKey}` for each application inbound endpoint (#1596) — EXCEPT one\n * whose verification secret is unset (I1 at mount: `NO_VERIFICATION_SECRET`).\n */\n private registerApplicationEndpointRoutes(): void {\n if (!this.inbound) return;\n const { registry, receiver } = this.inbound;\n for (const endpoint of registry.getApplicationEndpoints()) {\n const routePath = inboundEndpointRoutePath(INBOUND_APPLICATION_ENDPOINT_PROVIDER_REF, endpoint.endpointKey);\n // assurance-control: WILDO.SECURITY.FAIL_CLOSED — an endpoint that cannot verify is not mounted (I1).\n const secretEnvVar = deriveInboundEndpointSecretEnvVarName(endpoint.endpointKey);\n if (!process.env[secretEnvVar]) {\n this.withheldRoutes.push({\n providerRef: INBOUND_APPLICATION_ENDPOINT_PROVIDER_REF,\n endpointKey: endpoint.endpointKey,\n capability: 'inbound',\n routePath,\n reasons: [WebhookRouteWithholdingReason.NO_VERIFICATION_SECRET],\n });\n this.logger.error(\n `WebhookAutoController: NOT registering POST ${routePath} — its verification secret '${secretEnvVar}' is not set. `\n + 'An endpoint that cannot verify a signature must not exist; the sender gets a 404 until the secret is configured and the backend restarts.',\n { endpointKey: endpoint.endpointKey, secretEnvVar, reasons: [WebhookRouteWithholdingReason.NO_VERIFICATION_SECRET] },\n );\n continue;\n }\n this.router.post(routePath, this.asyncHandler(async (req: Request, res: Response) => {\n writeInboundAnswer(res, await receiver.receiveApplicationEndpoint(endpoint, this.rawRequestOf(req)));\n }));\n this.registeredRoutePaths.push(routePath);\n this.logger.info(`Inbound application endpoint registered: POST ${routePath}`);\n }\n }\n\n /**\n * The exact bytes, the headers, and the path and query the request arrived on (a scheme that signs the URL reads\n * them, #3394). Never a re-serialization: a JSON.stringify of `req.body` is not what was signed.\n */\n private rawRequestOf(req: Request): InboundRawRequest {\n const rawBody = Buffer.isBuffer(req.rawBody) ? req.rawBody : Buffer.isBuffer(req.body) ? req.body : undefined;\n return {\n rawBody,\n headers: req.headers,\n ...(req.inboundBodyTooLarge ? { bodyTooLarge: true } : {}),\n ...(typeof req.originalUrl === 'string' ? { requestTarget: req.originalUrl } : {}),\n };\n }\n\n /**\n * Register a capability handler for dispatching processed events.\n * Called at startup by capability modules (e.g., billing module).\n *\n * MUST be called before {@link initialize}. `start-application` satisfies this\n * ordering today — step 4.5 initializes capability modules (which register\n * here) and step 4.6 initializes this controller — and the guard below exists\n * so a future step inserted the other way round is LOUD instead of silent.\n *\n * The failure it catches is genuinely confusing without it: a late-registered\n * handler works perfectly at request time (the map is read per request), but\n * the route it would serve was already withheld at mount time, so the endpoint\n * answers 404 while a handler for it demonstrably exists.\n */\n registerCapabilityHandler(handler: WebhookCapabilityHandler): void {\n this.capabilityHandlers.set(handler.capability, handler);\n\n if (this.routesRegistered) {\n this.logger.error(\n `WebhookAutoController: capability handler for '${handler.capability}' was registered AFTER webhook routes were mounted. `\n + 'Route mounting is decided once, from the registrations present at that moment, so this handler cannot bring back any route '\n + 'that was withheld for a missing handler — those endpoints will keep answering 404. '\n + 'Register capability handlers before WebhookAutoControllerBackendService.initialize() runs.',\n {\n capability: handler.capability,\n withheldRoutes: this.withheldRoutes.map((withholding) => withholding.routePath),\n },\n );\n return;\n }\n\n this.logDebug(`Registered webhook capability handler for ${handler.capability}`);\n }\n\n /**\n * Record what the startup step owning a capability did with it (#3255), so a withheld endpoint of that capability\n * names its cause. Same ordering contract as {@link registerCapabilityHandler}: the mount decision and its log line\n * are taken once, at {@link initialize}, so a record arriving afterwards could explain nothing and says so.\n */\n recordCapabilityWiring(wiring: WebhookCapabilityWiring): void {\n this.capabilityWirings.set(wiring.capability, wiring);\n if (this.routesRegistered) {\n this.logger.error(\n `WebhookAutoController: the wiring of capability '${wiring.capability}' (${wiring.state}) was recorded AFTER webhook routes were mounted, `\n + 'so no withheld route could name it as its cause. Record it before WebhookAutoControllerBackendService.initialize() runs.',\n { capability: wiring.capability, state: wiring.state },\n );\n }\n }\n\n /**\n * Return the sanitized inbound-provider routes that this controller actually\n * registered. Provider configuration, signature material, endpoint payloads,\n * and handler metadata are intentionally absent.\n */\n public getRegisteredWebhookRoutePaths(): ReadonlyArray<string> {\n return [...this.registeredRoutePaths];\n }\n\n /**\n * Return the declared endpoints whose route was deliberately NOT mounted,\n * with the reason. Carries no provider configuration or signature material —\n * only the route identity, which registration was missing, and (#3255) the\n * cause its capability's owner recorded, which may carry a caught error's message.\n */\n public getWithheldWebhookRoutes(): ReadonlyArray<WebhookRouteWithholding> {\n return this.withheldRoutes.map((withholding) => ({\n ...withholding,\n reasons: [...withholding.reasons],\n ...(withholding.capabilityWiring === undefined ? {} : { capabilityWiring: { ...withholding.capabilityWiring } }),\n }));\n }\n\n // ════════════════════════════════════════════════════════════\n // Routes\n // ════════════════════════════════════════════════════════════\n\n /**\n * Required by `AbstractControllerBackendService`, which invokes this hook\n * synchronously from its constructor (`super(...)`). This controller\n * intentionally registers NOTHING here: its route set is data-dependent\n * (one route per provider webhook endpoint) and neither the webhook handler\n * nor the provider endpoint contracts exist at construction time. The real\n * registration happens in `initialize()` / `registerWebhookRoutes()` once\n * that data is available — see `initialize()`'s JSDoc for the full rationale.\n */\n protected setupRoutes(): void {\n // No-op by design — see JSDoc above and `registerWebhookRoutes()`.\n }\n\n /**\n * Register one Express route per pre-loaded provider webhook endpoint —\n * EXCEPT those whose capability cannot actually be dispatched.\n *\n * Invoked from `initialize()` after `webhookHandler` and `loadedEndpoints`\n * have been populated. Idempotent-safe against an empty cache; guards on the\n * handler so a mis-sequenced call fails visibly rather than registering dead\n * routes.\n *\n * ── Why an undispatchable endpoint is WITHHELD rather than mounted ────────\n *\n * A declared endpoint needs two registrations that this controller does not\n * own and cannot create: a `WebhookCapabilityAdapter` (verify + parse, on\n * `WebhookHandlerBackendService`) and a `WebhookCapabilityHandler` (dispatch,\n * here). Both are supplied by the capability module — for `billing`, inside\n * `start-application.initializeBillingServices`, which is deliberately\n * NON-FATAL: if it throws part-way, or if `billing.enabled` is false while the\n * provider is still enabled for `WEBHOOK_ORIGINATOR`, the application boots\n * with the provider's endpoint declared and neither registration present.\n *\n * Mounting a route in that state produces a 500 on every inbound delivery\n * (`No webhook adapter registered for ...`, or `No capability handler for ...`\n * below), and a 500 is precisely the answer that tells a vendor to RETRY — an\n * instruction that can never be satisfied, because no retry supplies a missing\n * startup registration. The endpoint therefore absorbs the vendor's full retry\n * schedule and eventually gets disabled on the vendor's side, while the only\n * local signal is a repeating error log.\n *\n * Not mounting says the true thing instead: this endpoint does not exist. The\n * vendor gets a 404 rather than a retry instruction, and the operator gets one\n * loud, remedy-naming error at startup — the moment the misconfiguration was\n * actually introduced.\n *\n * REJECTED — refusing at BOOT (throwing from here). It is the shape the rest of\n * the registry uses, and it is wrong at this site for three reasons. (1) It\n * would not even be loud: `start-application.initializeWebhookAutoController`\n * wraps `initialize()` in a non-fatal catch that downgrades a throw to a warn,\n * so the net effect would be a quieter log AND the loss of every OTHER\n * provider's working route. (2) It inverts a decision the engine already took\n * explicitly — billing initialization failure is documented as survivable\n * (\"the app can still run without billing\"); a failed optional subsystem must\n * not become a refusal to start. (3) `billing.enabled: false` beside a\n * registered Stripe provider is a COHERENT configuration, and refusing to boot\n * over it would be a false alarm. The check is per-endpoint, so a capability\n * that is wired keeps its route regardless of a sibling that is not.\n */\n private registerWebhookRoutes(): void {\n this.routesRegistered = true;\n\n if (!this.webhookHandler) {\n this.logger.warn('WebhookAutoController: initialize() ran without a webhook handler — no routes registered');\n return;\n }\n\n if (this.loadedEndpoints.size === 0) {\n this.logDebug('No webhook endpoints pre-loaded — no routes registered');\n return;\n }\n\n for (const [providerRef, endpoints] of this.loadedEndpoints) {\n for (const endpoint of endpoints) {\n const routePath = inboundEndpointRoutePath(providerRef, endpoint.key);\n\n const withholding = this.assessRouteDispatchability(providerRef, endpoint, routePath);\n if (withholding) {\n /*\n * The CAUSE, when the capability's owner recorded one (#3255). It explains the two registrations that owner\n * makes — the handler and the adapter — and nothing else, so it is read only when one of those is missing.\n * When it is known it REPLACES their generic remedies below: \"check whether billing initialization was\n * skipped or failed\" sent the test-007 reader to guess at credentials when the answer was one setting.\n */\n const wiring = this.capabilityWirings.get(endpoint.capability);\n const ownerRegistrationMissing = withholding.reasons.includes(WebhookRouteWithholdingReason.NO_CAPABILITY_HANDLER)\n || withholding.reasons.includes(WebhookRouteWithholdingReason.NO_ENDPOINT_ADAPTER);\n const cause = wiring !== undefined && ownerRegistrationMissing ? describeCapabilityWiringCause(wiring, providerRef, endpoint.key) : null;\n if (cause !== null && wiring !== undefined) withholding.capabilityWiring = wiring;\n this.withheldRoutes.push(withholding);\n /*\n * `registeredCapabilities` is what tells a MISSING registration apart from a\n * MISSPELLED one, and it is not decoration.\n *\n * Both sides of this join are typed `string`, so a capability declared\n * `'billing'` and registered `'BILLING'` produces exactly the same\n * NO_CAPABILITY_HANDLER as a module that never initialized. That happened\n * (#620): the remedy sentence that stood here sent the operator to \"billing\n * initialization was skipped or failed\", billing had initialized perfectly,\n * and the endpoint was withheld on every boot for months. Printing the keys\n * that ARE registered makes the two readings distinguishable in the one line\n * an operator sees, without them having to know either module.\n */\n const registeredCapabilities = [...this.capabilityHandlers.keys()];\n const registeredAdapterKeys = this.webhookHandler?.registeredAdapterKeys() ?? [];\n /*\n * The remedy is written PER REASON, because the two are different joins with different\n * remedies and printing both invites the operator to fix the wrong one. An earlier\n * version printed the capability-handler list unconditionally, so a route withheld\n * purely for a missing ADAPTER read \"register the capability module that owns 'BILLING'\n * … registered: 'BILLING'\" — self-contradictory, and pointing away from the join that\n * actually failed.\n */\n const remedies: string[] = [];\n if (cause === null && withholding.reasons.includes(WebhookRouteWithholdingReason.NO_CAPABILITY_HANDLER)) {\n remedies.push(\n `No capability handler owns '${endpoint.capability}'. Registered capability handlers at this moment: `\n + `${describeRegistrationKeys(registeredCapabilities)}. If one of those is the same capability under a `\n + 'different spelling, the declaration and the handler disagree and BOTH must come from the named '\n + 'capability vocabulary (BUILTIN_PROVIDER_CAPABILITY). No startup step recorded why the module owning '\n + `'${endpoint.capability}' did not register it.`,\n );\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.ENGINE_VERIFIED_WITHOUT_INBOUND_HANDLER)) {\n remedies.push(\n `'${providerRef}:${endpoint.key}' is verified by the engine (${endpoint.signatureConfig.algorithm}), which serves it only through an `\n + 'inbound handler: declare one whose source is this provider endpoint.',\n );\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.NO_EVENT_IDENTIFIER)) {\n remedies.push(\n `'${providerRef}:${endpoint.key}' uses ${endpoint.signatureConfig.algorithm}, which signs no delivery id: the provider module must `\n + 'declare `identifyEvent` on the endpoint so its events can be named and deduplicated.',\n );\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.REREAD_TRIGGER_WITHOUT_INBOUND_HANDLER)) {\n remedies.push(\n `'${providerRef}:${endpoint.key}' only triggers re-reads, which an inbound handler performs: declare one whose source is this `\n + 'provider endpoint, and whose scope resolver finds the record the notification names.',\n );\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.DECLARATION_CONTRADICTS_TRIGGER_STRATEGY)) {\n remedies.push(\n `'${providerRef}:${endpoint.key}' (${endpoint.triggerStrategy}) contradicts its strategy: a re-read trigger endpoint declares `\n + '`reReadTrigger` and no `signatureConfig`; every other endpoint declares a `signatureConfig` and no `reReadTrigger`. '\n + 'Fix the provider package.',\n );\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.REREAD_TRIGGER_LIMITS_INVALID)) {\n remedies.push(`'${providerRef}:${endpoint.key}' declares a coalescing window or rate limit that is not a positive integer. Fix the provider package.`);\n }\n if (withholding.reasons.includes(WebhookRouteWithholdingReason.REREAD_TRIGGER_WITHOUT_RATE_BUDGET)) {\n remedies.push(\n `'${providerRef}' declares no vendor rate budget, so the re-reads its unverified notifications cause cannot be held to a `\n + 'share that leaves polling the rest: declare `rateBudgets` on its connection (or `remoteCallSemantics.maxRequestsPerMinute`).',\n );\n }\n if (cause === null && withholding.reasons.includes(WebhookRouteWithholdingReason.NO_ENDPOINT_ADAPTER)) {\n remedies.push(\n `No adapter is registered for '${providerRef}:${endpoint.key}'. Registered adapter keys at this moment: `\n + `${describeRegistrationKeys(registeredAdapterKeys)}. Note this join is keyed on the endpoint KEY (the URL `\n + 'segment), not on its capability.',\n );\n }\n this.logger.error(\n `WebhookAutoController: NOT registering POST ${routePath} — the endpoint is declared but cannot be dispatched `\n + `(${withholding.reasons.join(', ')})${cause === null ? '.' : `, because ${cause}`} A route mounted in this state can only ever answer 500, which instructs the `\n + 'vendor to retry an inbound event that no retry can make processable. Withholding the route so the vendor gets a '\n + '404 instead.'\n // A known cause carries its own remedy; the generic one below is for a registration nothing explained.\n + (remedies.length === 0 ? '' : ` Remedy: ${remedies.join(' ')} Every registration must happen before `\n + `WebhookAutoControllerBackendService.initialize() runs; otherwise, disable the WEBHOOK_ORIGINATOR protocol for `\n + `provider '${providerRef}'.`),\n {\n providerRef,\n endpointKey: endpoint.key,\n capability: endpoint.capability,\n registeredCapabilities,\n registeredAdapterKeys,\n routePath,\n reasons: withholding.reasons,\n ...(withholding.capabilityWiring === undefined ? {} : { capabilityWiring: withholding.capabilityWiring }),\n },\n );\n continue;\n }\n\n // #3395: an endpoint an inbound handler takes, declaring a body larger than a delivery row (a pushed email), is read\n // raw up to its own limit by the parser mounted before the global ones, whose 10 MB would refuse it. Never past the\n // most any delivery may hold, which the receiver also enforces.\n if (endpoint.maxBodyBytes !== undefined && endpoint.maxBodyBytes > INBOUND_DELIVERY_MAX_STORED_BODY_BYTES\n && this.inbound?.registry.getProviderEndpointHandler(providerRef, endpoint.key)) {\n this.largeBodyRoutes?.declare(`${MAIN_API_BASE_PATH}${routePath}`, Math.min(endpoint.maxBodyBytes, INBOUND_DELIVERY_MAX_BODY_BYTES));\n }\n\n this.router.post(\n routePath,\n // Defense-in-depth for a future streaming mount. If this controller is\n // ever assigned the RAW_REQUEST_STREAM mount phase, this express.raw()\n // makes req.body the raw Buffer. Under the\n // current master-router mount it is an inert no-op: the global\n // express.json (HttpServerBackendService.setupBodyParsing) parses the\n // body first and sets req._body, so the signature-faithful bytes come\n // from req.rawBody — captured by that same express.json `verify` hook.\n // handleWebhookRequest reads rawBody first, then falls back to a Buffer\n // req.body for the streaming case.\n express.raw({ type: 'application/json' }),\n this.asyncHandler(async (req: Request, res: Response, _next: NextFunction) => {\n const inboundHandler = this.inbound?.registry.getProviderEndpointHandler(providerRef, endpoint.key);\n if (inboundHandler && this.inbound) {\n writeInboundAnswer(res, await this.inbound.receiver.receiveProviderEndpoint(providerRef, endpoint, inboundHandler, this.rawRequestOf(req)));\n return;\n }\n // A re-read trigger is never verified, so it never reaches the signed path (#2909 review F8): the mount gate\n // requires its handler, and one removed after mount is answered as every such request is, and logged.\n if (isReReadTriggerEndpoint(endpoint)) {\n this.logger.error('A re-read trigger notification arrived for an endpoint whose inbound handler is gone; dropped', { providerRef, endpointKey: endpoint.key });\n res.status(202).json({ received: true });\n return;\n }\n // Over the body parser's limit (#3395): no body was read, so there is nothing to verify or dispatch.\n if (req.inboundBodyTooLarge) {\n res.status(413).json({ error: 'Payload too large' });\n return;\n }\n await this.handleWebhookRequest(providerRef, endpoint, req, res);\n }),\n );\n\n this.registeredRoutePaths.push(routePath);\n this.logger.info(`Webhook endpoint registered: POST ${routePath}`);\n }\n }\n }\n\n /**\n * Whether `providerRef`'s re-reads spend a declared vendor budget (#2909): its own `maxRequestsPerMinute`, or\n * `rateBudgets` on the connection its grant belongs to. The same two sources `ConnectionRateBudgetBackendService` builds\n * the budgets from, so a \"yes\" here is a budget the triggered share is cut from.\n */\n private declaresVendorRateBudget(providerRef: string): boolean {\n const registry = this.externalProvidersRegistry;\n const own = registry.getProviderRuntimeContract(providerRef, ExternalProvider_ExchangeProtocol_Kind.REST_API);\n if (own?.kind === ProviderProtocolRuntimeKind.REST && own.remoteCallSemantics?.maxRequestsPerMinute !== undefined) return true;\n const connectionRef = registry.resolveCredentialConnectionRef(providerRef) ?? providerRef;\n const connection = registry.getProviderRuntimeContract(connectionRef, ExternalProvider_ExchangeProtocol_Kind.REST_API);\n return connection?.kind === ProviderProtocolRuntimeKind.REST && (connection.rateBudgets?.length ?? 0) > 0;\n }\n\n /**\n * Decide whether a declared endpoint can actually be served, and if not, say\n * which registration is missing.\n *\n * Returns `null` when the route is dispatchable. Both prerequisites are\n * evaluated (rather than short-circuiting on the first) so an operator gets\n * the WHOLE remedy in one log line instead of fixing one registration and\n * meeting the next on the following restart.\n */\n private assessRouteDispatchability(\n providerRef: string,\n endpoint: Hook_Endpoint,\n routePath: string,\n ): WebhookRouteWithholding | null {\n const reasons: WebhookRouteWithholdingReason[] = [];\n\n // A provider endpoint bound to an inbound handler (#1596) is dispatched by that handler, so it needs\n // no capability handler — only the provider's adapter, which still verifies it.\n const boundToInboundHandler = Boolean(this.inbound?.registry.getProviderEndpointHandler(providerRef, endpoint.key));\n\n // A re-read trigger (#2909) is handled by the engine and served only by an inbound handler: no capability handler,\n // no adapter, no signature.\n const reReadTrigger = isReReadTriggerEndpoint(endpoint);\n if (reReadTrigger !== (endpoint.reReadTrigger !== undefined) || reReadTrigger === (endpoint.signatureConfig !== undefined)) {\n reasons.push(WebhookRouteWithholdingReason.DECLARATION_CONTRADICTS_TRIGGER_STRATEGY);\n }\n if (reReadTrigger) {\n if (!boundToInboundHandler) reasons.push(WebhookRouteWithholdingReason.REREAD_TRIGGER_WITHOUT_INBOUND_HANDLER);\n if (endpoint.reReadTrigger && !reReadTriggerLimitsAreSound(endpoint.reReadTrigger)) reasons.push(WebhookRouteWithholdingReason.REREAD_TRIGGER_LIMITS_INVALID);\n if (!this.declaresVendorRateBudget(providerRef)) reasons.push(WebhookRouteWithholdingReason.REREAD_TRIGGER_WITHOUT_RATE_BUDGET);\n return reasons.length === 0 ? null : { providerRef, endpointKey: endpoint.key, capability: endpoint.capability, routePath, reasons };\n }\n if (!boundToInboundHandler && !this.capabilityHandlers.has(endpoint.capability)) {\n reasons.push(WebhookRouteWithholdingReason.NO_CAPABILITY_HANDLER);\n }\n // An engine-verified endpoint (Svix #1600, Slack v0 and the Bot Framework token #2659) is verified by engine code\n // and takes no adapter — and so is served only by an inbound handler, never by the capability path.\n if (isEngineVerifiedWebhookEndpoint(endpoint)) {\n if (!boundToInboundHandler) reasons.push(WebhookRouteWithholdingReason.ENGINE_VERIFIED_WITHOUT_INBOUND_HANDLER);\n if (!engineSchemeSignsDeliveryId(endpoint) && !endpoint.identifyEvent) reasons.push(WebhookRouteWithholdingReason.NO_EVENT_IDENTIFIER);\n if (!hookSignatureDeclarationIsComplete(endpoint.signatureConfig)) reasons.push(WebhookRouteWithholdingReason.SIGNATURE_DECLARATION_INCOMPLETE);\n } else if (!this.webhookHandler?.hasAdapter(providerRef, endpoint.key)) {\n reasons.push(WebhookRouteWithholdingReason.NO_ENDPOINT_ADAPTER);\n }\n\n if (reasons.length === 0) {\n return null;\n }\n return { providerRef, endpointKey: endpoint.key, capability: endpoint.capability, routePath, reasons };\n }\n\n // ════════════════════════════════════════════════════════════\n // Handler\n // ════════════════════════════════════════════════════════════\n\n private async handleWebhookRequest(\n providerRef: string,\n endpoint: Hook_Endpoint,\n req: Request,\n res: Response,\n ): Promise<void> {\n if (!this.webhookHandler) {\n res.status(503).json({ error: 'Webhook handler not initialized' });\n return;\n }\n\n // Raw request bytes for signature verification. Order matters:\n // 1. req.rawBody — captured by the global express.json `verify` hook\n // (HttpServerBackendService.setupBodyParsing). This is the provider's\n // EXACT original payload and the ONLY byte-faithful source under the\n // current master-router mount, where global express.json parses the\n // body before this route runs (making the per-route express.raw() a\n // no-op, so req.body is a parsed object here).\n // 2. Buffer req.body — only populated if this controller is ever\n // streaming-mounted before body parsing (per-route express.raw() fires).\n // 3. string / JSON.stringify — last-resort fallbacks; JSON.stringify will\n // NOT byte-match the provider (key ordering / whitespace), so it exists\n // only to avoid a crash, never as a correctness path for signatures.\n const rawBody = Buffer.isBuffer(req.rawBody)\n ? req.rawBody.toString('utf-8')\n : Buffer.isBuffer(req.body)\n ? req.body.toString('utf-8')\n : typeof req.body === 'string'\n ? req.body\n : JSON.stringify(req.body);\n\n let result: Awaited<ReturnType<WebhookHandlerBackendService['processWebhook']>> | null = null;\n try {\n result = await this.webhookHandler.processWebhook({\n providerRef,\n endpointKey: endpoint.key,\n endpoint,\n rawBody,\n headers: req.headers as Record<string, string>,\n });\n\n // null = idempotent duplicate or unparseable event — already acknowledged\n if (!result) {\n res.status(200).json({ received: true });\n return;\n }\n\n // Dispatch to capability handler.\n //\n // Defence in depth only: `registerWebhookRoutes` refuses to MOUNT a route\n // whose capability has no handler, so this branch is unreachable while that\n // gate holds — reaching it means the handler map was mutated after mounting\n // (which `registerCapabilityHandler` refuses to do silently). The throw is\n // kept rather than removed because the alternative — dispatching to\n // `undefined` — would 500 anyway, with no explanation.\n const handler = this.capabilityHandlers.get(endpoint.capability);\n if (handler) {\n await handler.handleEvent(result.executionContext, result.parsedEvent);\n } else {\n throw new Error(`No capability handler for ${endpoint.capability} on ${providerRef}/${endpoint.key}`);\n }\n\n await this.webhookHandler.markWebhookProcessed(result.idempotencyKey);\n res.status(200).json({ received: true });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : undefined;\n\n /*\n * `isWildoBackendError` + `.type`, never `(error as any).errorType`.\n *\n * `ErrorBuilderBackendService.buildError` stamps the field **`type`**; nothing in the engine\n * throws an object carrying `errorType`. So this predicate was `undefined === 'AUTHORIZATION'`\n * — permanently false — and every signature failure fell into the 500 branch below, which\n * tells the vendor to RETRY a delivery no retry can make valid. On Stripe that absorbs the\n * full retry schedule and can get the endpoint disabled vendor-side.\n *\n * It went unnoticed because until 2026-09-10 this route was WITHHELD at startup (#620), so\n * the whole handler was unreachable. Fixing the mount is what made this live.\n */\n if (isWildoBackendError(error) && error.type === ErrorType.AUTHORIZATION) {\n this.logDebug('Webhook signature verification failed', { providerRef, endpointKey: endpoint.key });\n res.status(401).json({ error: 'Invalid signature' });\n return;\n }\n\n /*\n * All other errors → 500 (trigger provider retry).\n *\n * Projected through `projectCaughtErrorLogFields` rather than reported as\n * `(error as Error).message`, because a `WildoError_Backend` IS NOT an `Error`: it has no\n * `message` property, so that read yields `undefined` and the `?? 'Unknown error'` fallback\n * fires. This line published the literal string **\"Unknown error\"** for the entire class of\n * error the engine actually raises — the classified ones, carrying the type, the custom\n * message reference and the context naming what failed.\n *\n * Measured 2026-09-10 while executing #544: a forwarded Stripe `checkout.session.completed`\n * failed, and this LOG LINE carried `\"error\":\"Unknown error\"` and nothing else, so the\n * delivery failure was unreadable and the provider retried against a fault nobody could name.\n * (The wire response is the unconditional `{ error: 'Processing failed' }` below and never\n * carried that string — naming the right surface matters, because the next reader will go\n * looking where this comment points.) `errorMessage` is still passed for a plain `Error`: a\n * `TypeError` from a bad read has a real message and no classified fields.\n */\n this.logger.error('Webhook processing failed', {\n providerRef,\n endpointKey: endpoint.key,\n // Only for a plain `Error` (a TypeError from a bad read has a real message and no classified\n // fields). Omitted rather than defaulted to the string \"Unknown error\": that literal is what\n // this line used to publish for every classified error, and leaving it in place would keep\n // it findable by an alert grep that should now be finding the projected cause instead.\n ...(errorMessage === undefined ? {} : { error: errorMessage }),\n ...projectCaughtErrorLogFields(error),\n });\n await this.webhookHandler.releaseWebhookClaim(result?.idempotencyKey);\n res.status(500).json({ error: 'Processing failed' });\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"m2m-webhook-delivery-log.custom-impl.backend.service.d.ts","sourceRoot":"","sources":["../../../../../../src/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAaH,OAAO,EAGL,KAAK,0CAA0C,EAChD,MAAM,4GAA4G,CAAC;AAmCpH,wBAAgB,yCAAyC,IAAI,0CAA0C,EAAE,CA2ExG;AAED,wBAAgB,4CAA4C,IAAI,0CAA0C,EAAE,CAgE3G"}
1
+ {"version":3,"file":"m2m-webhook-delivery-log.custom-impl.backend.service.d.ts","sourceRoot":"","sources":["../../../../../../src/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAaH,OAAO,EAGL,KAAK,0CAA0C,EAChD,MAAM,4GAA4G,CAAC;AAmCpH,wBAAgB,yCAAyC,IAAI,0CAA0C,EAAE,CA2ExG;AAED,wBAAgB,4CAA4C,IAAI,0CAA0C,EAAE,CAkE3G"}
@@ -133,7 +133,9 @@ export function createM2MWebhookDeliveryLogPurgeOldFactories() {
133
133
  },
134
134
  requestDtoSchema: M2MWebhookDeliveryLog_PurgeOldRequestDto,
135
135
  // #2297: the candidate read and the delete go through utils.serviceOptions; a legal hold that cannot be read throws
136
- // before anything is deleted. A multi-row write with no selection ceiling, so it stays best effort for THAT reason.
136
+ // before anything is deleted. It stays best effort as an unbounded multi-row write: the HOOK selects every terminal
137
+ // row older than the cutoff, so the framework's per-transaction chunking (wave 4) cannot reach it, and bounding it
138
+ // means changing what the operation answers (a partial purge reporting what remains), not declaring a number here.
137
139
  hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,
138
140
  handlers: {
139
141
  replaceCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {
@@ -1 +1 @@
1
- {"version":3,"file":"m2m-webhook-delivery-log.custom-impl.backend.service.js","sourceRoot":"","sources":["../../../../../../src/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * M2M Webhook Delivery Log — RETRY + PURGE_OLD custom implementations.\n *\n * Both operations are declared on\n * `m2m-webhook-delivery-log.shared.resources-config.schemas.ts` (org + app\n * variants); this file authors the REPLACE_CORE_OPERATIONS handlers that make\n * them real:\n *\n * - **RETRY** (`resourceOperationLike: UPDATE` → returns the updated row):\n * CAS-reset a FAILED row to PENDING with an immediate retry slot + fresh\n * attempt budget ({@link M2MWebhookDeliveryLogRepository.resetForRetry}),\n * then enqueue a delivery job — the exact `{ scope, deliveryLogId }` input\n * the dispatcher enqueues, so the drain worker path is IDENTICAL for\n * first-time and manually-retried deliveries (no parallel delivery code).\n * The worker's own `markInFlight` CAS makes the manual path race-safe\n * against a concurrent cron sweep: only one job wins the PENDING lease.\n *\n * - **PURGE_OLD** (borrows DELETE, `customResponseDto` purge summary):\n * bulk-delete terminal DELIVERED/FAILED rows older than the requested\n * retention window via\n * {@link M2MWebhookDeliveryLogRepository.purgeTerminalOlderThan}.\n *\n * Scope resolution mirrors the polymorphic variant: the ORG variant reads\n * `executionContext.organizationId`, the APP variant `applicationId` — the\n * same `M2MWebhookScope` shape the dispatcher/worker use, so the retried\n * job's scope FK can never drift from the row it targets.\n */\n\nimport {\n AuthScopeType,\n CoreResourceType,\n ErrorCustomMessageReference,\n ErrorType,\n M2MWebhookDeliveryLog_Operations,\n M2MWebhookDeliveryLog_RetryRequestDto,\n M2MWebhookDeliveryLog_PurgeOldRequestDto,\n ResourceOperationVariantType,\n} from '@wildo-ai/saas-models';\nimport type { Container } from 'inversify';\nimport {\n createResourceCustomServiceImplementation,\n ResourceCustomServiceImplementationHookTransactionPosture,\n type ResourceCustomServiceImplementationFactory,\n} from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation.factory.backend';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport { M2M_WEBHOOK_DELIVERY_BATCH_REF } from '~wildo-backend-lib/base-classes/services/batches/engine-custom-batch-manifests';\nimport type { QueueBackendService } from '~wildo-backend-lib/queue/queue.backend.service';\nimport { legalHoldCandidateOf, legalHoldUnverifiableRefusalContext, resolveLegalHeldRows } from '~wildo-backend-lib/compliance/privacy/legal-hold.backend';\nimport {\n M2MWebhookDeliveryLogRepository,\n type M2MWebhookScope,\n} from './m2m-webhook-delivery-log.repository';\nimport { engineRepositoriesRegistry } from '~wildo-backend-lib/base-classes/services/services/engine-repositories-registry.backend.utils';\n\n/**\n * Variant → scope-type pairing. The polymorphic resource type determines\n * which execution-context id anchors the `M2MWebhookScope`.\n */\nconst DELIVERY_LOG_VARIANTS = [\n { resourceType: CoreResourceType.ORGANIZATION_M2M_WEBHOOK_DELIVERY_LOG, scopeType: AuthScopeType.ORGANIZATION },\n { resourceType: CoreResourceType.APPLICATION_M2M_WEBHOOK_DELIVERY_LOG, scopeType: AuthScopeType.APPLICATION },\n] as const;\n\n/**\n * Resolve the `M2MWebhookScope` for this variant from the execution context.\n * Returns `null` when the context lacks the scope id (a routing/authorization\n * invariant violation for these org/app-scoped operations — caller throws).\n */\nfunction resolveScopeFromContext(\n scopeType: AuthScopeType,\n executionContext: { organizationId?: string | null; applicationId?: string | null },\n): M2MWebhookScope | null {\n const id = scopeType === AuthScopeType.ORGANIZATION\n ? executionContext.organizationId\n : executionContext.applicationId;\n return id ? { type: scopeType, id } : null;\n}\n\nexport function createM2MWebhookDeliveryLogRetryFactories(): ResourceCustomServiceImplementationFactory[] {\n return DELIVERY_LOG_VARIANTS.map(({ resourceType, scopeType }): ResourceCustomServiceImplementationFactory => {\n return (_resourcesRegistryService, container: Container) => {\n return createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: resourceType,\n operationIdentifier: M2MWebhookDeliveryLog_Operations.RETRY,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n requestDtoSchema: M2MWebhookDeliveryLog_RetryRequestDto,\n handlers: {\n replaceCoreOperations: async (_id, _input, executionContext, _operationPath, utils) => {\n if (typeof _id !== 'string' || _id.length === 0) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: 'Webhook delivery RETRY requires the delivery-log id from the route path.' },\n });\n }\n const deliveryLogId = _id;\n const scope = resolveScopeFromContext(scopeType, executionContext);\n if (!scope) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: `Webhook delivery RETRY requires a ${scopeType}-scoped execution context.` },\n });\n }\n\n const deliveryLogRepo = container.get<M2MWebhookDeliveryLogRepository>(\n SAAS_SERVICE_TYPES.M2MWebhookDeliveryLogRepository,\n );\n const queueService = container.get<QueueBackendService>(SAAS_SERVICE_TYPES.QueueBackendService);\n\n // CAS reset — `null` means the row is missing OR not FAILED.\n // Disambiguate for the admin: a precise error beats a generic one.\n const reset = await deliveryLogRepo.resetForRetry(scope, executionContext, deliveryLogId);\n if (!reset) {\n const existing = await deliveryLogRepo.read(scope, executionContext, deliveryLogId);\n if (!existing) {\n throw utils.errorBuilder.buildError(ErrorType.NOT_FOUND, executionContext, {\n customMessageReference: ErrorCustomMessageReference.NOT_FOUND,\n context: { message: 'Webhook delivery log row not found for retry.', deliveryLogId },\n });\n }\n throw utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n customMessageReference: ErrorCustomMessageReference.CONFLICT,\n context: {\n message: `Only FAILED deliveries can be retried — this row is '${existing.status}'.`,\n deliveryLogId,\n status: existing.status,\n },\n });\n }\n\n // Same job input the dispatcher enqueues — one worker path for\n // first-time and retried deliveries. Enqueue failure is non-fatal:\n // the row is already PENDING with `nextAttemptAt: now`, so the\n // cron retry sweep picks it up (same posture as the dispatcher's\n // own enqueue-failure branch).\n try {\n await queueService.enqueueCustomBatch(M2M_WEBHOOK_DELIVERY_BATCH_REF, {\n scope,\n deliveryLogId,\n });\n } catch {\n // Row stays PENDING — recovered by the retry sweep.\n }\n\n // RETRY is `resourceOperationLike: UPDATE` → return the updated row.\n return reset;\n },\n },\n });\n };\n });\n}\n\nexport function createM2MWebhookDeliveryLogPurgeOldFactories(): ResourceCustomServiceImplementationFactory[] {\n return DELIVERY_LOG_VARIANTS.map(({ resourceType, scopeType }): ResourceCustomServiceImplementationFactory => {\n return (resourcesRegistryService, container: Container) => {\n return createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: resourceType,\n operationIdentifier: M2MWebhookDeliveryLog_Operations.PURGE_OLD,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n requestDtoSchema: M2MWebhookDeliveryLog_PurgeOldRequestDto,\n // #2297: the candidate read and the delete go through utils.serviceOptions; a legal hold that cannot be read throws\n // before anything is deleted. A multi-row write with no selection ceiling, so it stays best effort for THAT reason.\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n handlers: {\n replaceCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { olderThanDays } = input as { olderThanDays: number };\n const scope = resolveScopeFromContext(scopeType, executionContext);\n if (!scope) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: `Webhook delivery PURGE_OLD requires a ${scopeType}-scoped execution context.` },\n });\n }\n\n const deliveryLogRepo = container.get<M2MWebhookDeliveryLogRepository>(\n SAAS_SERVICE_TYPES.M2MWebhookDeliveryLogRepository,\n );\n const deliveryLogResourceType: CoreResourceType = resourceType;\n // assurance-control: WILDO.PRIVACY.STORAGE_LIMITATION — a delivery record under a legal hold is not purged.\n // A delivery log is what the tenant's systems were sent, and so part of what a hold preserves. Held\n // rows are KEPT and counted rather than failing the purge, like every other retention path; a hold\n // state that cannot be read purges nothing.\n const { purgedCount, keptByLegalHoldCount } = await deliveryLogRepo.purgeTerminalOlderThan(\n scope,\n executionContext,\n olderThanDays,\n async (candidates) => {\n const resolution = await resolveLegalHeldRows(\n { repositoriesRegistry: engineRepositoriesRegistry(utils), resourcesRegistry: resourcesRegistryService, logger: utils.logger },\n { resourceType: deliveryLogResourceType, rows: candidates.map((row) => legalHoldCandidateOf(deliveryLogResourceType, row)) },\n );\n if (resolution.unverifiable) {\n throw utils.errorBuilder.buildError(ErrorType.INFRASTRUCTURE, executionContext, {\n customMessageReference: ErrorCustomMessageReference.LEGAL_HOLD_STATE_UNVERIFIABLE,\n context: legalHoldUnverifiableRefusalContext(deliveryLogResourceType, resolution),\n });\n }\n return new Set(resolution.held.keys());\n },\n utils.serviceOptions,\n );\n\n // Matches the declared `customResponseDto` purge summary.\n return {\n purgedCount,\n message: `Purged ${purgedCount} delivered/failed webhook deliveries older than ${olderThanDays} day(s).`\n + (keptByLegalHoldCount > 0 ? ` Kept ${keptByLegalHoldCount} under an active legal hold.` : ''),\n };\n },\n },\n });\n };\n });\n}\n"]}
1
+ {"version":3,"file":"m2m-webhook-delivery-log.custom-impl.backend.service.js","sourceRoot":"","sources":["../../../../../../src/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,2BAA2B,EAC3B,SAAS,EACT,gCAAgC,EAChC,qCAAqC,EACrC,wCAAwC,EACxC,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,yCAAyC,EACzC,yDAAyD,GAE1D,MAAM,4GAA4G,CAAC;AACpH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AACpF,OAAO,EAAE,8BAA8B,EAAE,MAAM,gFAAgF,CAAC;AAEhI,OAAO,EAAE,oBAAoB,EAAE,mCAAmC,EAAE,oBAAoB,EAAE,MAAM,0DAA0D,CAAC;AAK3J,OAAO,EAAE,0BAA0B,EAAE,MAAM,8FAA8F,CAAC;AAE1I;;;GAGG;AACH,MAAM,qBAAqB,GAAG;IAC5B,EAAE,YAAY,EAAE,gBAAgB,CAAC,qCAAqC,EAAE,SAAS,EAAE,aAAa,CAAC,YAAY,EAAE;IAC/G,EAAE,YAAY,EAAE,gBAAgB,CAAC,oCAAoC,EAAE,SAAS,EAAE,aAAa,CAAC,WAAW,EAAE;CACrG,CAAC;AAEX;;;;GAIG;AACH,SAAS,uBAAuB,CAC9B,SAAwB,EACxB,gBAAmF;IAEnF,MAAM,EAAE,GAAG,SAAS,KAAK,aAAa,CAAC,YAAY;QACjD,CAAC,CAAC,gBAAgB,CAAC,cAAc;QACjC,CAAC,CAAC,gBAAgB,CAAC,aAAa,CAAC;IACnC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,yCAAyC;IACvD,OAAO,qBAAqB,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,EAA8C,EAAE;QAC3G,OAAO,CAAC,yBAAyB,EAAE,SAAoB,EAAE,EAAE;YACzD,OAAO,yCAAyC,CAAC;gBAC/C,aAAa,EAAE;oBACb,kBAAkB,EAAE,YAAY;oBAChC,mBAAmB,EAAE,gCAAgC,CAAC,KAAK;oBAC3D,WAAW,EAAE,4BAA4B,CAAC,QAAQ;oBAClD,kBAAkB,EAAE,IAAI;iBACzB;gBACD,gBAAgB,EAAE,qCAAqC;gBACvD,QAAQ,EAAE;oBACR,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,gBAAgB,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE;wBACpF,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;4BAChD,MAAM,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,EAAE,gBAAgB,EAAE;gCAC1E,sBAAsB,EAAE,2BAA2B,CAAC,UAAU;gCAC9D,OAAO,EAAE,EAAE,OAAO,EAAE,0EAA0E,EAAE;6BACjG,CAAC,CAAC;wBACL,CAAC;wBACD,MAAM,aAAa,GAAG,GAAG,CAAC;wBAC1B,MAAM,KAAK,GAAG,uBAAuB,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;wBACnE,IAAI,CAAC,KAAK,EAAE,CAAC;4BACX,MAAM,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,EAAE,gBAAgB,EAAE;gCAC1E,sBAAsB,EAAE,2BAA2B,CAAC,UAAU;gCAC9D,OAAO,EAAE,EAAE,OAAO,EAAE,qCAAqC,SAAS,4BAA4B,EAAE;6BACjG,CAAC,CAAC;wBACL,CAAC;wBAED,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,CACnC,kBAAkB,CAAC,+BAA+B,CACnD,CAAC;wBACF,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,CAAsB,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;wBAEhG,6DAA6D;wBAC7D,mEAAmE;wBACnE,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,KAAK,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC;wBAC1F,IAAI,CAAC,KAAK,EAAE,CAAC;4BACX,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC;4BACpF,IAAI,CAAC,QAAQ,EAAE,CAAC;gCACd,MAAM,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,SAAS,EAAE,gBAAgB,EAAE;oCACzE,sBAAsB,EAAE,2BAA2B,CAAC,SAAS;oCAC7D,OAAO,EAAE,EAAE,OAAO,EAAE,+CAA+C,EAAE,aAAa,EAAE;iCACrF,CAAC,CAAC;4BACL,CAAC;4BACD,MAAM,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,gBAAgB,EAAE;gCACxE,sBAAsB,EAAE,2BAA2B,CAAC,QAAQ;gCAC5D,OAAO,EAAE;oCACP,OAAO,EAAE,wDAAwD,QAAQ,CAAC,MAAM,IAAI;oCACpF,aAAa;oCACb,MAAM,EAAE,QAAQ,CAAC,MAAM;iCACxB;6BACF,CAAC,CAAC;wBACL,CAAC;wBAED,+DAA+D;wBAC/D,mEAAmE;wBACnE,+DAA+D;wBAC/D,iEAAiE;wBACjE,+BAA+B;wBAC/B,IAAI,CAAC;4BACH,MAAM,YAAY,CAAC,kBAAkB,CAAC,8BAA8B,EAAE;gCACpE,KAAK;gCACL,aAAa;6BACd,CAAC,CAAC;wBACL,CAAC;wBAAC,MAAM,CAAC;4BACP,oDAAoD;wBACtD,CAAC;wBAED,qEAAqE;wBACrE,OAAO,KAAK,CAAC;oBACf,CAAC;iBACF;aACF,CAAC,CAAC;QACL,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,4CAA4C;IAC1D,OAAO,qBAAqB,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,EAA8C,EAAE;QAC3G,OAAO,CAAC,wBAAwB,EAAE,SAAoB,EAAE,EAAE;YACxD,OAAO,yCAAyC,CAAC;gBAC/C,aAAa,EAAE;oBACb,kBAAkB,EAAE,YAAY;oBAChC,mBAAmB,EAAE,gCAAgC,CAAC,SAAS;oBAC/D,WAAW,EAAE,4BAA4B,CAAC,QAAQ;oBAClD,kBAAkB,EAAE,IAAI;iBACzB;gBACD,gBAAgB,EAAE,wCAAwC;gBAC1D,oHAAoH;gBACpH,oHAAoH;gBACpH,mHAAmH;gBACnH,mHAAmH;gBACnH,sBAAsB,EAAE,yDAAyD,CAAC,uBAAuB;gBACzG,QAAQ,EAAE;oBACR,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE;wBACnF,MAAM,EAAE,aAAa,EAAE,GAAG,KAAkC,CAAC;wBAC7D,MAAM,KAAK,GAAG,uBAAuB,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;wBACnE,IAAI,CAAC,KAAK,EAAE,CAAC;4BACX,MAAM,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,EAAE,gBAAgB,EAAE;gCAC1E,sBAAsB,EAAE,2BAA2B,CAAC,UAAU;gCAC9D,OAAO,EAAE,EAAE,OAAO,EAAE,yCAAyC,SAAS,4BAA4B,EAAE;6BACrG,CAAC,CAAC;wBACL,CAAC;wBAED,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,CACnC,kBAAkB,CAAC,+BAA+B,CACnD,CAAC;wBACF,MAAM,uBAAuB,GAAqB,YAAY,CAAC;wBAC/D,4GAA4G;wBAC5G,oGAAoG;wBACpG,mGAAmG;wBACnG,4CAA4C;wBAC5C,MAAM,EAAE,WAAW,EAAE,oBAAoB,EAAE,GAAG,MAAM,eAAe,CAAC,sBAAsB,CACxF,KAAK,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,EAAE,UAAU,EAAE,EAAE;4BACnB,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAC3C,EAAE,oBAAoB,EAAE,0BAA0B,CAAC,KAAK,CAAC,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAC9H,EAAE,YAAY,EAAE,uBAAuB,EAAE,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,oBAAoB,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC,EAAE,CAC7H,CAAC;4BACF,IAAI,UAAU,CAAC,YAAY,EAAE,CAAC;gCAC5B,MAAM,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,cAAc,EAAE,gBAAgB,EAAE;oCAC9E,sBAAsB,EAAE,2BAA2B,CAAC,6BAA6B;oCACjF,OAAO,EAAE,mCAAmC,CAAC,uBAAuB,EAAE,UAAU,CAAC;iCAClF,CAAC,CAAC;4BACL,CAAC;4BACD,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;wBACzC,CAAC,EACD,KAAK,CAAC,cAAc,CACrB,CAAC;wBAEF,0DAA0D;wBAC1D,OAAO;4BACL,WAAW;4BACX,OAAO,EAAE,UAAU,WAAW,mDAAmD,aAAa,UAAU;kCACpG,CAAC,oBAAoB,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,oBAAoB,8BAA8B,CAAC,CAAC,CAAC,EAAE,CAAC;yBAClG,CAAC;oBACJ,CAAC;iBACF;aACF,CAAC,CAAC;QACL,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * M2M Webhook Delivery Log — RETRY + PURGE_OLD custom implementations.\n *\n * Both operations are declared on\n * `m2m-webhook-delivery-log.shared.resources-config.schemas.ts` (org + app\n * variants); this file authors the REPLACE_CORE_OPERATIONS handlers that make\n * them real:\n *\n * - **RETRY** (`resourceOperationLike: UPDATE` → returns the updated row):\n * CAS-reset a FAILED row to PENDING with an immediate retry slot + fresh\n * attempt budget ({@link M2MWebhookDeliveryLogRepository.resetForRetry}),\n * then enqueue a delivery job — the exact `{ scope, deliveryLogId }` input\n * the dispatcher enqueues, so the drain worker path is IDENTICAL for\n * first-time and manually-retried deliveries (no parallel delivery code).\n * The worker's own `markInFlight` CAS makes the manual path race-safe\n * against a concurrent cron sweep: only one job wins the PENDING lease.\n *\n * - **PURGE_OLD** (borrows DELETE, `customResponseDto` purge summary):\n * bulk-delete terminal DELIVERED/FAILED rows older than the requested\n * retention window via\n * {@link M2MWebhookDeliveryLogRepository.purgeTerminalOlderThan}.\n *\n * Scope resolution mirrors the polymorphic variant: the ORG variant reads\n * `executionContext.organizationId`, the APP variant `applicationId` — the\n * same `M2MWebhookScope` shape the dispatcher/worker use, so the retried\n * job's scope FK can never drift from the row it targets.\n */\n\nimport {\n AuthScopeType,\n CoreResourceType,\n ErrorCustomMessageReference,\n ErrorType,\n M2MWebhookDeliveryLog_Operations,\n M2MWebhookDeliveryLog_RetryRequestDto,\n M2MWebhookDeliveryLog_PurgeOldRequestDto,\n ResourceOperationVariantType,\n} from '@wildo-ai/saas-models';\nimport type { Container } from 'inversify';\nimport {\n createResourceCustomServiceImplementation,\n ResourceCustomServiceImplementationHookTransactionPosture,\n type ResourceCustomServiceImplementationFactory,\n} from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation.factory.backend';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport { M2M_WEBHOOK_DELIVERY_BATCH_REF } from '~wildo-backend-lib/base-classes/services/batches/engine-custom-batch-manifests';\nimport type { QueueBackendService } from '~wildo-backend-lib/queue/queue.backend.service';\nimport { legalHoldCandidateOf, legalHoldUnverifiableRefusalContext, resolveLegalHeldRows } from '~wildo-backend-lib/compliance/privacy/legal-hold.backend';\nimport {\n M2MWebhookDeliveryLogRepository,\n type M2MWebhookScope,\n} from './m2m-webhook-delivery-log.repository';\nimport { engineRepositoriesRegistry } from '~wildo-backend-lib/base-classes/services/services/engine-repositories-registry.backend.utils';\n\n/**\n * Variant → scope-type pairing. The polymorphic resource type determines\n * which execution-context id anchors the `M2MWebhookScope`.\n */\nconst DELIVERY_LOG_VARIANTS = [\n { resourceType: CoreResourceType.ORGANIZATION_M2M_WEBHOOK_DELIVERY_LOG, scopeType: AuthScopeType.ORGANIZATION },\n { resourceType: CoreResourceType.APPLICATION_M2M_WEBHOOK_DELIVERY_LOG, scopeType: AuthScopeType.APPLICATION },\n] as const;\n\n/**\n * Resolve the `M2MWebhookScope` for this variant from the execution context.\n * Returns `null` when the context lacks the scope id (a routing/authorization\n * invariant violation for these org/app-scoped operations — caller throws).\n */\nfunction resolveScopeFromContext(\n scopeType: AuthScopeType,\n executionContext: { organizationId?: string | null; applicationId?: string | null },\n): M2MWebhookScope | null {\n const id = scopeType === AuthScopeType.ORGANIZATION\n ? executionContext.organizationId\n : executionContext.applicationId;\n return id ? { type: scopeType, id } : null;\n}\n\nexport function createM2MWebhookDeliveryLogRetryFactories(): ResourceCustomServiceImplementationFactory[] {\n return DELIVERY_LOG_VARIANTS.map(({ resourceType, scopeType }): ResourceCustomServiceImplementationFactory => {\n return (_resourcesRegistryService, container: Container) => {\n return createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: resourceType,\n operationIdentifier: M2MWebhookDeliveryLog_Operations.RETRY,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n requestDtoSchema: M2MWebhookDeliveryLog_RetryRequestDto,\n handlers: {\n replaceCoreOperations: async (_id, _input, executionContext, _operationPath, utils) => {\n if (typeof _id !== 'string' || _id.length === 0) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: 'Webhook delivery RETRY requires the delivery-log id from the route path.' },\n });\n }\n const deliveryLogId = _id;\n const scope = resolveScopeFromContext(scopeType, executionContext);\n if (!scope) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: `Webhook delivery RETRY requires a ${scopeType}-scoped execution context.` },\n });\n }\n\n const deliveryLogRepo = container.get<M2MWebhookDeliveryLogRepository>(\n SAAS_SERVICE_TYPES.M2MWebhookDeliveryLogRepository,\n );\n const queueService = container.get<QueueBackendService>(SAAS_SERVICE_TYPES.QueueBackendService);\n\n // CAS reset — `null` means the row is missing OR not FAILED.\n // Disambiguate for the admin: a precise error beats a generic one.\n const reset = await deliveryLogRepo.resetForRetry(scope, executionContext, deliveryLogId);\n if (!reset) {\n const existing = await deliveryLogRepo.read(scope, executionContext, deliveryLogId);\n if (!existing) {\n throw utils.errorBuilder.buildError(ErrorType.NOT_FOUND, executionContext, {\n customMessageReference: ErrorCustomMessageReference.NOT_FOUND,\n context: { message: 'Webhook delivery log row not found for retry.', deliveryLogId },\n });\n }\n throw utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n customMessageReference: ErrorCustomMessageReference.CONFLICT,\n context: {\n message: `Only FAILED deliveries can be retried — this row is '${existing.status}'.`,\n deliveryLogId,\n status: existing.status,\n },\n });\n }\n\n // Same job input the dispatcher enqueues — one worker path for\n // first-time and retried deliveries. Enqueue failure is non-fatal:\n // the row is already PENDING with `nextAttemptAt: now`, so the\n // cron retry sweep picks it up (same posture as the dispatcher's\n // own enqueue-failure branch).\n try {\n await queueService.enqueueCustomBatch(M2M_WEBHOOK_DELIVERY_BATCH_REF, {\n scope,\n deliveryLogId,\n });\n } catch {\n // Row stays PENDING — recovered by the retry sweep.\n }\n\n // RETRY is `resourceOperationLike: UPDATE` → return the updated row.\n return reset;\n },\n },\n });\n };\n });\n}\n\nexport function createM2MWebhookDeliveryLogPurgeOldFactories(): ResourceCustomServiceImplementationFactory[] {\n return DELIVERY_LOG_VARIANTS.map(({ resourceType, scopeType }): ResourceCustomServiceImplementationFactory => {\n return (resourcesRegistryService, container: Container) => {\n return createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: resourceType,\n operationIdentifier: M2MWebhookDeliveryLog_Operations.PURGE_OLD,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n requestDtoSchema: M2MWebhookDeliveryLog_PurgeOldRequestDto,\n // #2297: the candidate read and the delete go through utils.serviceOptions; a legal hold that cannot be read throws\n // before anything is deleted. It stays best effort as an unbounded multi-row write: the HOOK selects every terminal\n // row older than the cutoff, so the framework's per-transaction chunking (wave 4) cannot reach it, and bounding it\n // means changing what the operation answers (a partial purge reporting what remains), not declaring a number here.\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n handlers: {\n replaceCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { olderThanDays } = input as { olderThanDays: number };\n const scope = resolveScopeFromContext(scopeType, executionContext);\n if (!scope) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: `Webhook delivery PURGE_OLD requires a ${scopeType}-scoped execution context.` },\n });\n }\n\n const deliveryLogRepo = container.get<M2MWebhookDeliveryLogRepository>(\n SAAS_SERVICE_TYPES.M2MWebhookDeliveryLogRepository,\n );\n const deliveryLogResourceType: CoreResourceType = resourceType;\n // assurance-control: WILDO.PRIVACY.STORAGE_LIMITATION — a delivery record under a legal hold is not purged.\n // A delivery log is what the tenant's systems were sent, and so part of what a hold preserves. Held\n // rows are KEPT and counted rather than failing the purge, like every other retention path; a hold\n // state that cannot be read purges nothing.\n const { purgedCount, keptByLegalHoldCount } = await deliveryLogRepo.purgeTerminalOlderThan(\n scope,\n executionContext,\n olderThanDays,\n async (candidates) => {\n const resolution = await resolveLegalHeldRows(\n { repositoriesRegistry: engineRepositoriesRegistry(utils), resourcesRegistry: resourcesRegistryService, logger: utils.logger },\n { resourceType: deliveryLogResourceType, rows: candidates.map((row) => legalHoldCandidateOf(deliveryLogResourceType, row)) },\n );\n if (resolution.unverifiable) {\n throw utils.errorBuilder.buildError(ErrorType.INFRASTRUCTURE, executionContext, {\n customMessageReference: ErrorCustomMessageReference.LEGAL_HOLD_STATE_UNVERIFIABLE,\n context: legalHoldUnverifiableRefusalContext(deliveryLogResourceType, resolution),\n });\n }\n return new Set(resolution.held.keys());\n },\n utils.serviceOptions,\n );\n\n // Matches the declared `customResponseDto` purge summary.\n return {\n purgedCount,\n message: `Purged ${purgedCount} delivered/failed webhook deliveries older than ${olderThanDays} day(s).`\n + (keptByLegalHoldCount > 0 ? ` Kept ${keptByLegalHoldCount} under an active legal hold.` : ''),\n };\n },\n },\n });\n };\n });\n}\n"]}
@@ -8,6 +8,7 @@ import { ControllersRegistryHandlerBackendService } from '../../base-classes/ser
8
8
  import { AbstractControllerBackendService } from '../../base-classes/services/controllers/abstract-controller.backend.service';
9
9
  import { ErrorBuilderBackendService } from '../../errors/services/error-builder.backend.service';
10
10
  import { ErrorHandlerService } from '../../errors/services/error-handler.backend.service';
11
+ import { type InboundLargeBodyRoutesBackendService } from '../../runtime/services/utils/inbound-endpoint-raw-body.backend.utils';
11
12
  import { WebSocketService } from '../../requests/service/websocket.service';
12
13
  import { HealthControllerBackendService } from '../../runtime/controllers/health-controller.backend.service';
13
14
  import { RedisService } from '../../databases/services/redis.service';
@@ -80,6 +81,7 @@ export declare class HttpServerBackendService {
80
81
  private readonly redisService;
81
82
  private readonly customDomainHostResolver?;
82
83
  private readonly customDomainEdge?;
84
+ private readonly inboundLargeBodyRoutes?;
83
85
  private readonly app;
84
86
  private server;
85
87
  /**
@@ -112,7 +114,7 @@ export declare class HttpServerBackendService {
112
114
  */
113
115
  private readonly rawBodyRequiredPrefixes;
114
116
  protected readonly logDebug: (message: string, context?: Record<string, unknown>) => void;
115
- constructor(logger: LoggerService, appConfigService: AppConfigurationService, controllersRegistry: ControllersRegistryHandlerBackendService, errorBuilder: ErrorBuilderBackendService, errorHandler: ErrorHandlerService, webSocketService: WebSocketService, healthController: HealthControllerBackendService, redisService: RedisService, customDomainHostResolver?: Pick<CustomDomainHostResolverBackendService, 'resolveOrigin'>, customDomainEdge?: Pick<CustomDomainEdgeBackendService, 'servedDomains'>);
117
+ constructor(logger: LoggerService, appConfigService: AppConfigurationService, controllersRegistry: ControllersRegistryHandlerBackendService, errorBuilder: ErrorBuilderBackendService, errorHandler: ErrorHandlerService, webSocketService: WebSocketService, healthController: HealthControllerBackendService, redisService: RedisService, customDomainHostResolver?: Pick<CustomDomainHostResolverBackendService, 'resolveOrigin'>, customDomainEdge?: Pick<CustomDomainEdgeBackendService, 'servedDomains'>, inboundLargeBodyRoutes?: Pick<InboundLargeBodyRoutesBackendService, 'limitFor'>);
116
118
  initialize(options?: HttpServerInitOptions): Promise<void>;
117
119
  /**
118
120
  * Register a custom controller
@@ -1 +1 @@
1
- {"version":3,"file":"http-server.backend.service.d.ts","sourceRoot":"","sources":["../../../../src/runtime/services/http-server.backend.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http-server.backend.service.d.ts","sourceRoot":"","sources":["../../../../src/runtime/services/http-server.backend.service.ts"],"names":[],"mappings":"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"}
@@ -32,7 +32,7 @@ import { projectCaughtErrorLogFields } from '../../errors/utils/error-log-level-
32
32
  import { applyOAuthBodyCap } from '../../runtime/services/utils/oauth-body-cap.backend.utils.js';
33
33
  import { applyCspViolationReportBodyCap } from '../../monitoring/csp-violation-reports/csp-violation-report-body-cap.backend.utils.js';
34
34
  import { ENGINE_CORS_ALLOWED_REQUEST_HEADERS, ENGINE_CORS_EXPOSED_RESPONSE_HEADERS } from '../../runtime/services/utils/engine-cors-headers.backend.utils.js';
35
- import { applyInboundApplicationEndpointRawBody, retainRawBodyUnder, translateOversizedInboundBody } from '../../runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js';
35
+ import { applyInboundApplicationEndpointRawBody, applyInboundLargeBodyProviderEndpoints, retainRawBodyUnder, translateOversizedInboundBody } from '../../runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js';
36
36
  import { describeUnusableContainerHostGatewayListenHost, openContainerHostGatewayListener } from '../../runtime/services/utils/container-host-gateway-listener.backend.utils.js';
37
37
  import { RuntimeConfigurationSchema } from '../../runtime/models/runtime.backend.schemas.js';
38
38
  import { ClientInstanceIdScope, ErrorRequestOutcome, ErrorSeverity, ErrorType, ErrorCustomMessageReference, isAppConfigurationNotInitializedError, WildoHeaderKeys, ENGINE_ROOT_ROUTES, EngineRootRouteKey, MAIN_API_BASE_PATH, MANUAL_CONTROLLER_ROUTES_URLS, ManualControllerRouteKey, rfc8414AuthorizationServerMetadataPath, rfc9728ProtectedResourceMetadataPath, ResourceSerializationUtils, COMPOSE_EDGE_CERT_RESOLVER, COMPOSE_EDGE_SECURE_ENTRYPOINT } from '@wildo-ai/saas-models';
@@ -94,6 +94,7 @@ let HttpServerBackendService = class HttpServerBackendService {
94
94
  redisService;
95
95
  customDomainHostResolver;
96
96
  customDomainEdge;
97
+ inboundLargeBodyRoutes;
97
98
  app;
98
99
  server = null;
99
100
  /**
@@ -128,7 +129,7 @@ let HttpServerBackendService = class HttpServerBackendService {
128
129
  `${MAIN_API_BASE_PATH}/webhooks/`,
129
130
  ];
130
131
  logDebug;
131
- constructor(logger, appConfigService, controllersRegistry, errorBuilder, errorHandler, webSocketService, healthController, redisService, customDomainHostResolver, customDomainEdge) {
132
+ constructor(logger, appConfigService, controllersRegistry, errorBuilder, errorHandler, webSocketService, healthController, redisService, customDomainHostResolver, customDomainEdge, inboundLargeBodyRoutes) {
132
133
  this.logger = logger;
133
134
  this.appConfigService = appConfigService;
134
135
  this.controllersRegistry = controllersRegistry;
@@ -139,6 +140,7 @@ let HttpServerBackendService = class HttpServerBackendService {
139
140
  this.redisService = redisService;
140
141
  this.customDomainHostResolver = customDomainHostResolver;
141
142
  this.customDomainEdge = customDomainEdge;
143
+ this.inboundLargeBodyRoutes = inboundLargeBodyRoutes;
142
144
  this.app = express();
143
145
  this.logDebug = this.logger.debugByType('HttpServer');
144
146
  this.logger.setDebugTypeLogging('HttpServer', false);
@@ -837,6 +839,10 @@ let HttpServerBackendService = class HttpServerBackendService {
837
839
  applyOAuthBodyCap(this.app, MAIN_API_BASE_PATH);
838
840
  // Application inbound endpoints take their body raw, so the receiver audits a malformed one (#1596).
839
841
  applyInboundApplicationEndpointRawBody(this.app, MAIN_API_BASE_PATH);
842
+ // A provider endpoint that may receive more than the global parsers read (a pushed email, #3395) takes its body raw,
843
+ // up to its own declared limit. The routes are declared by the webhook controller when it mounts them.
844
+ if (this.inboundLargeBodyRoutes)
845
+ applyInboundLargeBodyProviderEndpoints(this.app, this.inboundLargeBodyRoutes, MAIN_API_BASE_PATH);
840
846
  // The CSP violation collector's 64 KiB cap, and the only parser of `application/csp-report` (#2867): unauthenticated,
841
847
  // so it is bounded before the global parser's multi-megabyte limit can apply.
842
848
  applyCspViolationReportBodyCap(this.app, MAIN_API_BASE_PATH);
@@ -1367,6 +1373,8 @@ HttpServerBackendService = __decorate([
1367
1373
  __param(8, optional()),
1368
1374
  __param(9, inject(SAAS_SERVICE_TYPES.CustomDomainEdgeService)),
1369
1375
  __param(9, optional()),
1376
+ __param(10, inject(SAAS_SERVICE_TYPES.InboundLargeBodyRoutes)),
1377
+ __param(10, optional()),
1370
1378
  __metadata("design:paramtypes", [LoggerService,
1371
1379
  AppConfigurationService,
1372
1380
  ControllersRegistryHandlerBackendService,
@@ -1374,7 +1382,7 @@ HttpServerBackendService = __decorate([
1374
1382
  ErrorHandlerService,
1375
1383
  WebSocketService,
1376
1384
  HealthControllerBackendService,
1377
- RedisService, Object, Object])
1385
+ RedisService, Object, Object, Object])
1378
1386
  ], HttpServerBackendService);
1379
1387
  export { HttpServerBackendService };
1380
1388
  //# sourceMappingURL=http-server.backend.service.js.map