@wildo-ai/saas-backend-lib 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (972) hide show
  1. package/dist/esm/applications/services/worker-remote-client-factory.backend.service.d.ts.map +1 -1
  2. package/dist/esm/applications/services/worker-remote-client-factory.backend.service.js +19 -1
  3. package/dist/esm/applications/services/worker-remote-client-factory.backend.service.js.map +1 -1
  4. package/dist/esm/base-classes/models/manual-controllers.backend.definition.d.ts.map +1 -1
  5. package/dist/esm/base-classes/models/manual-controllers.backend.definition.js +4 -0
  6. package/dist/esm/base-classes/models/manual-controllers.backend.definition.js.map +1 -1
  7. package/dist/esm/base-classes/services/batches/child-lifecycle-teardown.batch.backend.service.d.ts +35 -0
  8. package/dist/esm/base-classes/services/batches/child-lifecycle-teardown.batch.backend.service.d.ts.map +1 -0
  9. package/dist/esm/base-classes/services/batches/child-lifecycle-teardown.batch.backend.service.js +111 -0
  10. package/dist/esm/base-classes/services/batches/child-lifecycle-teardown.batch.backend.service.js.map +1 -0
  11. package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.d.ts +50 -0
  12. package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.d.ts.map +1 -0
  13. package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.js +199 -0
  14. package/dist/esm/base-classes/services/batches/credential-expiry-sweep.batch.backend.service.js.map +1 -0
  15. package/dist/esm/base-classes/services/batches/engine-custom-batch-manifests.d.ts +111 -0
  16. package/dist/esm/base-classes/services/batches/engine-custom-batch-manifests.d.ts.map +1 -1
  17. package/dist/esm/base-classes/services/batches/engine-custom-batch-manifests.js +140 -0
  18. package/dist/esm/base-classes/services/batches/engine-custom-batch-manifests.js.map +1 -1
  19. package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.d.ts +14 -3
  20. package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.d.ts.map +1 -1
  21. package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.js +138 -24
  22. package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.js.map +1 -1
  23. package/dist/esm/base-classes/services/controllers/controllers-registry-handler.backend.service.d.ts +3 -1
  24. package/dist/esm/base-classes/services/controllers/controllers-registry-handler.backend.service.d.ts.map +1 -1
  25. package/dist/esm/base-classes/services/controllers/controllers-registry-handler.backend.service.js +8 -3
  26. package/dist/esm/base-classes/services/controllers/controllers-registry-handler.backend.service.js.map +1 -1
  27. package/dist/esm/base-classes/services/repositories/field-clearing-partition.backend.d.ts +11 -0
  28. package/dist/esm/base-classes/services/repositories/field-clearing-partition.backend.d.ts.map +1 -1
  29. package/dist/esm/base-classes/services/repositories/field-clearing-partition.backend.js +11 -2
  30. package/dist/esm/base-classes/services/repositories/field-clearing-partition.backend.js.map +1 -1
  31. package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.d.ts +124 -13
  32. package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.d.ts.map +1 -1
  33. package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.js +207 -21
  34. package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.js.map +1 -1
  35. package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.d.ts +60 -8
  36. package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.d.ts.map +1 -1
  37. package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.js +174 -26
  38. package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.js.map +1 -1
  39. package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.d.ts +48 -4
  40. package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.d.ts.map +1 -1
  41. package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.js +102 -30
  42. package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.js.map +1 -1
  43. package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.d.ts +55 -0
  44. package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.d.ts.map +1 -0
  45. package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.js +114 -0
  46. package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.js.map +1 -0
  47. package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.d.ts +89 -14
  48. package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.d.ts.map +1 -1
  49. package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.js +84 -11
  50. package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.js.map +1 -1
  51. package/dist/esm/base-classes/services/repositories/http-api/odata-query-compiler.backend.d.ts.map +1 -1
  52. package/dist/esm/base-classes/services/repositories/http-api/odata-query-compiler.backend.js +16 -0
  53. package/dist/esm/base-classes/services/repositories/http-api/odata-query-compiler.backend.js.map +1 -1
  54. package/dist/esm/base-classes/services/repositories/infrastructure-tier-contract.backend.d.ts +20 -6
  55. package/dist/esm/base-classes/services/repositories/infrastructure-tier-contract.backend.d.ts.map +1 -1
  56. package/dist/esm/base-classes/services/repositories/infrastructure-tier-contract.backend.js +96 -32
  57. package/dist/esm/base-classes/services/repositories/infrastructure-tier-contract.backend.js.map +1 -1
  58. package/dist/esm/base-classes/services/repositories/introspection/introspection-resource-repository.backend.service.d.ts +3 -1
  59. package/dist/esm/base-classes/services/repositories/introspection/introspection-resource-repository.backend.service.d.ts.map +1 -1
  60. package/dist/esm/base-classes/services/repositories/introspection/introspection-resource-repository.backend.service.js +32 -7
  61. package/dist/esm/base-classes/services/repositories/introspection/introspection-resource-repository.backend.service.js.map +1 -1
  62. package/dist/esm/base-classes/services/repositories/introspection/introspection-resource-source.backend.port.d.ts +8 -5
  63. package/dist/esm/base-classes/services/repositories/introspection/introspection-resource-source.backend.port.d.ts.map +1 -1
  64. package/dist/esm/base-classes/services/repositories/introspection/introspection-resource-source.backend.port.js.map +1 -1
  65. package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.d.ts +80 -0
  66. package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.d.ts.map +1 -1
  67. package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.js +298 -23
  68. package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.js.map +1 -1
  69. package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.d.ts +71 -1
  70. package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.d.ts.map +1 -1
  71. package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.js +85 -5
  72. package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.js.map +1 -1
  73. package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.d.ts +21 -0
  74. package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.d.ts.map +1 -1
  75. package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.js +146 -4
  76. package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.js.map +1 -1
  77. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.d.ts +22 -0
  78. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.d.ts.map +1 -1
  79. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.js.map +1 -1
  80. package/dist/esm/base-classes/services/services/resource-operation-implementation-coverage.backend.utils.d.ts +3 -26
  81. package/dist/esm/base-classes/services/services/resource-operation-implementation-coverage.backend.utils.d.ts.map +1 -1
  82. package/dist/esm/base-classes/services/services/resource-operation-implementation-coverage.backend.utils.js +3 -68
  83. package/dist/esm/base-classes/services/services/resource-operation-implementation-coverage.backend.utils.js.map +1 -1
  84. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts.map +1 -1
  85. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js +4 -1
  86. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js.map +1 -1
  87. package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.d.ts +11 -0
  88. package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.d.ts.map +1 -1
  89. package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.js +39 -5
  90. package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.js.map +1 -1
  91. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts +181 -2
  92. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts.map +1 -1
  93. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js +533 -43
  94. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js.map +1 -1
  95. package/dist/esm/base-classes/services/services/system-access.backend.service.d.ts +36 -3
  96. package/dist/esm/base-classes/services/services/system-access.backend.service.d.ts.map +1 -1
  97. package/dist/esm/base-classes/services/services/system-access.backend.service.js +70 -8
  98. package/dist/esm/base-classes/services/services/system-access.backend.service.js.map +1 -1
  99. package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.d.ts +28 -0
  100. package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.d.ts.map +1 -0
  101. package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.js +90 -0
  102. package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.js.map +1 -0
  103. package/dist/esm/billing/batches/usage-flush.batch.backend.service.d.ts +44 -0
  104. package/dist/esm/billing/batches/usage-flush.batch.backend.service.d.ts.map +1 -0
  105. package/dist/esm/billing/batches/usage-flush.batch.backend.service.js +99 -0
  106. package/dist/esm/billing/batches/usage-flush.batch.backend.service.js.map +1 -0
  107. package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.d.ts +91 -0
  108. package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.d.ts.map +1 -0
  109. package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.js +152 -0
  110. package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.js.map +1 -0
  111. package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.d.ts +186 -0
  112. package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.d.ts.map +1 -0
  113. package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.js +474 -0
  114. package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.js.map +1 -0
  115. package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.d.ts +100 -0
  116. package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.d.ts.map +1 -1
  117. package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.js +209 -6
  118. package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.js.map +1 -1
  119. package/dist/esm/billing/services/back-office/usage-metering.backend.service.d.ts +200 -4
  120. package/dist/esm/billing/services/back-office/usage-metering.backend.service.d.ts.map +1 -1
  121. package/dist/esm/billing/services/back-office/usage-metering.backend.service.js +593 -64
  122. package/dist/esm/billing/services/back-office/usage-metering.backend.service.js.map +1 -1
  123. package/dist/esm/billing/services/billing-adapter-registry.backend.d.ts +36 -0
  124. package/dist/esm/billing/services/billing-adapter-registry.backend.d.ts.map +1 -0
  125. package/dist/esm/billing/services/billing-adapter-registry.backend.js +83 -0
  126. package/dist/esm/billing/services/billing-adapter-registry.backend.js.map +1 -0
  127. package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.d.ts +9 -0
  128. package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.d.ts.map +1 -1
  129. package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.js +11 -1
  130. package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.js.map +1 -1
  131. package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.d.ts.map +1 -1
  132. package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.js +54 -13
  133. package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.js.map +1 -1
  134. package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.d.ts +38 -1
  135. package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.d.ts.map +1 -1
  136. package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.js +67 -2
  137. package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.js.map +1 -1
  138. package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.d.ts +30 -1
  139. package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.d.ts.map +1 -1
  140. package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.js +43 -1
  141. package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.js.map +1 -1
  142. package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.d.ts +11 -3
  143. package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.d.ts.map +1 -1
  144. package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.js +30 -16
  145. package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.js.map +1 -1
  146. package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.d.ts.map +1 -1
  147. package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.js +104 -25
  148. package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.js.map +1 -1
  149. package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.d.ts +18 -1
  150. package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.d.ts.map +1 -1
  151. package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.js +106 -2
  152. package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.js.map +1 -1
  153. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.d.ts +52 -0
  154. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.d.ts.map +1 -0
  155. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js +74 -0
  156. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js.map +1 -0
  157. package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.d.ts +104 -11
  158. package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.d.ts.map +1 -1
  159. package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.js +260 -26
  160. package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.js.map +1 -1
  161. package/dist/esm/billing/testing/mock-billing-provider.d.ts +30 -1
  162. package/dist/esm/billing/testing/mock-billing-provider.d.ts.map +1 -1
  163. package/dist/esm/billing/testing/mock-billing-provider.js +25 -0
  164. package/dist/esm/billing/testing/mock-billing-provider.js.map +1 -1
  165. package/dist/esm/compliance/audit-trails/batches/audit-logs-archive.batch.backend.service.js +11 -4
  166. package/dist/esm/compliance/audit-trails/batches/audit-logs-archive.batch.backend.service.js.map +1 -1
  167. package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.d.ts +263 -13
  168. package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.d.ts.map +1 -1
  169. package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.js +376 -58
  170. package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.js.map +1 -1
  171. package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.d.ts +264 -7
  172. package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.d.ts.map +1 -1
  173. package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.js +414 -5
  174. package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.js.map +1 -1
  175. package/dist/esm/compliance/audit-trails/services/composite-audit-log-sink.backend.d.ts.map +1 -1
  176. package/dist/esm/compliance/audit-trails/services/composite-audit-log-sink.backend.js +7 -1
  177. package/dist/esm/compliance/audit-trails/services/composite-audit-log-sink.backend.js.map +1 -1
  178. package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.d.ts +16 -0
  179. package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.d.ts.map +1 -0
  180. package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.js +140 -0
  181. package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.js.map +1 -0
  182. package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.d.ts +42 -0
  183. package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.d.ts.map +1 -1
  184. package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.js +65 -6
  185. package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.js.map +1 -1
  186. package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.d.ts +110 -0
  187. package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.d.ts.map +1 -0
  188. package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.js +192 -0
  189. package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.js.map +1 -0
  190. package/dist/esm/compliance/audit-trails/services/utils/ocsf-activity-mapping.backend.utils.d.ts.map +1 -1
  191. package/dist/esm/compliance/audit-trails/services/utils/ocsf-activity-mapping.backend.utils.js +45 -0
  192. package/dist/esm/compliance/audit-trails/services/utils/ocsf-activity-mapping.backend.utils.js.map +1 -1
  193. package/dist/esm/config/bootstrap/application-runtime-profile.backend.d.ts +5 -0
  194. package/dist/esm/config/bootstrap/application-runtime-profile.backend.d.ts.map +1 -1
  195. package/dist/esm/config/bootstrap/application-runtime-profile.backend.js +6 -0
  196. package/dist/esm/config/bootstrap/application-runtime-profile.backend.js.map +1 -1
  197. package/dist/esm/config/custom/application-config-controller.backend.service.d.ts.map +1 -1
  198. package/dist/esm/config/custom/application-config-controller.backend.service.js +7 -1
  199. package/dist/esm/config/custom/application-config-controller.backend.service.js.map +1 -1
  200. package/dist/esm/config/models/app-config.backend.schemas.d.ts +146 -46
  201. package/dist/esm/config/models/app-config.backend.schemas.d.ts.map +1 -1
  202. package/dist/esm/config/models/app-config.backend.schemas.js +121 -12
  203. package/dist/esm/config/models/app-config.backend.schemas.js.map +1 -1
  204. package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.d.ts +38 -15
  205. package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.d.ts.map +1 -1
  206. package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.js +17 -2
  207. package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.js.map +1 -1
  208. package/dist/esm/config/services/app-configuration-loader.backend.service.d.ts +0 -1
  209. package/dist/esm/config/services/app-configuration-loader.backend.service.d.ts.map +1 -1
  210. package/dist/esm/config/services/app-configuration-loader.backend.service.js +68 -76
  211. package/dist/esm/config/services/app-configuration-loader.backend.service.js.map +1 -1
  212. package/dist/esm/config/services/app-configuration.backend.service.d.ts.map +1 -1
  213. package/dist/esm/config/services/app-configuration.backend.service.js +23 -1
  214. package/dist/esm/config/services/app-configuration.backend.service.js.map +1 -1
  215. package/dist/esm/config/services/app-configuration.backend.utils.d.ts +43 -1
  216. package/dist/esm/config/services/app-configuration.backend.utils.d.ts.map +1 -1
  217. package/dist/esm/config/services/app-configuration.backend.utils.js +52 -3
  218. package/dist/esm/config/services/app-configuration.backend.utils.js.map +1 -1
  219. package/dist/esm/config/services/application-startup-config-validator.backend.service.d.ts +25 -0
  220. package/dist/esm/config/services/application-startup-config-validator.backend.service.d.ts.map +1 -1
  221. package/dist/esm/config/services/application-startup-config-validator.backend.service.js +41 -1
  222. package/dist/esm/config/services/application-startup-config-validator.backend.service.js.map +1 -1
  223. package/dist/esm/data-seeding/services/shared/data-seed-scope-iteration.shared.utils.d.ts +2 -2
  224. package/dist/esm/data-seeding/services/shared/data-seed-scope-iteration.shared.utils.js +2 -2
  225. package/dist/esm/data-seeding/services/shared/data-seed-scope-iteration.shared.utils.js.map +1 -1
  226. package/dist/esm/databases/models/filter.backend.schemas.js +2 -2
  227. package/dist/esm/databases/models/filter.backend.schemas.js.map +1 -1
  228. package/dist/esm/databases/services/aggregation/aggregation-authorization.backend.service.d.ts.map +1 -1
  229. package/dist/esm/databases/services/aggregation/aggregation-authorization.backend.service.js +20 -1
  230. package/dist/esm/databases/services/aggregation/aggregation-authorization.backend.service.js.map +1 -1
  231. package/dist/esm/databases/services/postgresql-schema-plan-diff.backend.d.ts.map +1 -1
  232. package/dist/esm/databases/services/postgresql-schema-plan-diff.backend.js +48 -0
  233. package/dist/esm/databases/services/postgresql-schema-plan-diff.backend.js.map +1 -1
  234. package/dist/esm/databases/services/redis.service.d.ts +27 -0
  235. package/dist/esm/databases/services/redis.service.d.ts.map +1 -1
  236. package/dist/esm/databases/services/redis.service.js +29 -0
  237. package/dist/esm/databases/services/redis.service.js.map +1 -1
  238. package/dist/esm/errors/services/error-builder.backend.service.d.ts +13 -1
  239. package/dist/esm/errors/services/error-builder.backend.service.d.ts.map +1 -1
  240. package/dist/esm/errors/services/error-builder.backend.service.js +13 -1
  241. package/dist/esm/errors/services/error-builder.backend.service.js.map +1 -1
  242. package/dist/esm/errors/services/error-handler.backend.service.d.ts +70 -7
  243. package/dist/esm/errors/services/error-handler.backend.service.d.ts.map +1 -1
  244. package/dist/esm/errors/services/error-handler.backend.service.js +134 -8
  245. package/dist/esm/errors/services/error-handler.backend.service.js.map +1 -1
  246. package/dist/esm/errors/services/rate-limit.backend.service.d.ts +66 -0
  247. package/dist/esm/errors/services/rate-limit.backend.service.d.ts.map +1 -1
  248. package/dist/esm/errors/services/rate-limit.backend.service.js +102 -25
  249. package/dist/esm/errors/services/rate-limit.backend.service.js.map +1 -1
  250. package/dist/esm/errors/utils/error-log-level-classification.backend.utils.d.ts +5 -0
  251. package/dist/esm/errors/utils/error-log-level-classification.backend.utils.d.ts.map +1 -1
  252. package/dist/esm/errors/utils/error-log-level-classification.backend.utils.js +25 -0
  253. package/dist/esm/errors/utils/error-log-level-classification.backend.utils.js.map +1 -1
  254. package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.d.ts +33 -0
  255. package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.d.ts.map +1 -1
  256. package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.js +40 -0
  257. package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.js.map +1 -1
  258. package/dist/esm/external-data/controllers/external-data-admin.backend.contracts.d.ts +41 -0
  259. package/dist/esm/external-data/controllers/external-data-admin.backend.contracts.d.ts.map +1 -0
  260. package/dist/esm/external-data/controllers/external-data-admin.backend.contracts.js +40 -0
  261. package/dist/esm/external-data/controllers/external-data-admin.backend.contracts.js.map +1 -0
  262. package/dist/esm/external-data/controllers/external-data-admin.backend.controller.d.ts +64 -0
  263. package/dist/esm/external-data/controllers/external-data-admin.backend.controller.d.ts.map +1 -0
  264. package/dist/esm/external-data/controllers/external-data-admin.backend.controller.js +193 -0
  265. package/dist/esm/external-data/controllers/external-data-admin.backend.controller.js.map +1 -0
  266. package/dist/esm/external-data/external-data-pipeline-run.backend.service.d.ts +72 -4
  267. package/dist/esm/external-data/external-data-pipeline-run.backend.service.d.ts.map +1 -1
  268. package/dist/esm/external-data/external-data-pipeline-run.backend.service.js +60 -19
  269. package/dist/esm/external-data/external-data-pipeline-run.backend.service.js.map +1 -1
  270. package/dist/esm/external-data/external-data-transform.backend.d.ts.map +1 -1
  271. package/dist/esm/external-data/external-data-transform.backend.js +7 -1
  272. package/dist/esm/external-data/external-data-transform.backend.js.map +1 -1
  273. package/dist/esm/external-data/models/external-data-pipeline-state.backend.schemas.d.ts +2 -0
  274. package/dist/esm/external-data/models/external-data-pipeline-state.backend.schemas.d.ts.map +1 -1
  275. package/dist/esm/external-data/models/external-data-pipeline-state.backend.schemas.js +13 -0
  276. package/dist/esm/external-data/models/external-data-pipeline-state.backend.schemas.js.map +1 -1
  277. package/dist/esm/external-providers/models/provider-selection-resolution-evidence.backend.definitions.d.ts +4 -2
  278. package/dist/esm/external-providers/models/provider-selection-resolution-evidence.backend.definitions.d.ts.map +1 -1
  279. package/dist/esm/external-providers/models/provider-selection-resolution-evidence.backend.definitions.js.map +1 -1
  280. package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.d.ts +256 -0
  281. package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.d.ts.map +1 -0
  282. package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.js +333 -0
  283. package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.js.map +1 -0
  284. package/dist/esm/external-providers/operations/provider-operation-request.backend.d.ts +56 -0
  285. package/dist/esm/external-providers/operations/provider-operation-request.backend.d.ts.map +1 -0
  286. package/dist/esm/external-providers/operations/provider-operation-request.backend.js +211 -0
  287. package/dist/esm/external-providers/operations/provider-operation-request.backend.js.map +1 -0
  288. package/dist/esm/external-providers/operations/provider-request-signing.backend.d.ts +45 -0
  289. package/dist/esm/external-providers/operations/provider-request-signing.backend.d.ts.map +1 -0
  290. package/dist/esm/external-providers/operations/provider-request-signing.backend.js +216 -0
  291. package/dist/esm/external-providers/operations/provider-request-signing.backend.js.map +1 -0
  292. package/dist/esm/external-providers/operations/provider-rest-call-client.backend.d.ts +56 -0
  293. package/dist/esm/external-providers/operations/provider-rest-call-client.backend.d.ts.map +1 -0
  294. package/dist/esm/external-providers/operations/provider-rest-call-client.backend.js +78 -0
  295. package/dist/esm/external-providers/operations/provider-rest-call-client.backend.js.map +1 -0
  296. package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.d.ts +1 -1
  297. package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.d.ts.map +1 -1
  298. package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.js +2 -2
  299. package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.js.map +1 -1
  300. package/dist/esm/external-providers/services/backend-provider-loader.backend.service.d.ts +89 -0
  301. package/dist/esm/external-providers/services/backend-provider-loader.backend.service.d.ts.map +1 -0
  302. package/dist/esm/external-providers/services/backend-provider-loader.backend.service.js +164 -0
  303. package/dist/esm/external-providers/services/backend-provider-loader.backend.service.js.map +1 -0
  304. package/dist/esm/external-providers/services/backend-provider-registry.backend.service.d.ts +26 -27
  305. package/dist/esm/external-providers/services/backend-provider-registry.backend.service.d.ts.map +1 -1
  306. package/dist/esm/external-providers/services/backend-provider-registry.backend.service.js +50 -64
  307. package/dist/esm/external-providers/services/backend-provider-registry.backend.service.js.map +1 -1
  308. package/dist/esm/external-providers/services/document-extraction.backend.service.d.ts.map +1 -1
  309. package/dist/esm/external-providers/services/document-extraction.backend.service.js +3 -3
  310. package/dist/esm/external-providers/services/document-extraction.backend.service.js.map +1 -1
  311. package/dist/esm/external-providers/services/embeddings.backend.service.d.ts.map +1 -1
  312. package/dist/esm/external-providers/services/embeddings.backend.service.js +4 -4
  313. package/dist/esm/external-providers/services/embeddings.backend.service.js.map +1 -1
  314. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +306 -7
  315. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -1
  316. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +539 -45
  317. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
  318. package/dist/esm/external-providers/services/frontend-bootstrap.backend.service.d.ts.map +1 -1
  319. package/dist/esm/external-providers/services/frontend-bootstrap.backend.service.js +25 -2
  320. package/dist/esm/external-providers/services/frontend-bootstrap.backend.service.js.map +1 -1
  321. package/dist/esm/files/controllers/file.controller.d.ts +24 -1
  322. package/dist/esm/files/controllers/file.controller.d.ts.map +1 -1
  323. package/dist/esm/files/controllers/file.controller.js +83 -11
  324. package/dist/esm/files/controllers/file.controller.js.map +1 -1
  325. package/dist/esm/files/handlers/file-upload-route-locals.backend.types.d.ts +17 -0
  326. package/dist/esm/files/handlers/file-upload-route-locals.backend.types.d.ts.map +1 -0
  327. package/dist/esm/files/handlers/file-upload-route-locals.backend.types.js +1 -0
  328. package/dist/esm/files/handlers/file-upload-route-locals.backend.types.js.map +1 -0
  329. package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.d.ts +5 -1
  330. package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.d.ts.map +1 -1
  331. package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.js +76 -13
  332. package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.js.map +1 -1
  333. package/dist/esm/files/services/file-operation-handler.backend.service.d.ts +18 -0
  334. package/dist/esm/files/services/file-operation-handler.backend.service.d.ts.map +1 -1
  335. package/dist/esm/files/services/file-operation-handler.backend.service.js +36 -28
  336. package/dist/esm/files/services/file-operation-handler.backend.service.js.map +1 -1
  337. package/dist/esm/files/services/file-scanning.backend.service.d.ts +94 -9
  338. package/dist/esm/files/services/file-scanning.backend.service.d.ts.map +1 -1
  339. package/dist/esm/files/services/file-scanning.backend.service.js +197 -17
  340. package/dist/esm/files/services/file-scanning.backend.service.js.map +1 -1
  341. package/dist/esm/files/services/file-text-extraction.backend.service.d.ts +60 -1
  342. package/dist/esm/files/services/file-text-extraction.backend.service.d.ts.map +1 -1
  343. package/dist/esm/files/services/file-text-extraction.backend.service.js +167 -8
  344. package/dist/esm/files/services/file-text-extraction.backend.service.js.map +1 -1
  345. package/dist/esm/files/services/file-upload-grant.backend.service.d.ts +214 -0
  346. package/dist/esm/files/services/file-upload-grant.backend.service.d.ts.map +1 -0
  347. package/dist/esm/files/services/file-upload-grant.backend.service.js +566 -0
  348. package/dist/esm/files/services/file-upload-grant.backend.service.js.map +1 -0
  349. package/dist/esm/files/services/files.backend.service.d.ts +87 -0
  350. package/dist/esm/files/services/files.backend.service.d.ts.map +1 -1
  351. package/dist/esm/files/services/files.backend.service.js +252 -19
  352. package/dist/esm/files/services/files.backend.service.js.map +1 -1
  353. package/dist/esm/files/storage/application-storage-key.backend.utils.d.ts +109 -0
  354. package/dist/esm/files/storage/application-storage-key.backend.utils.d.ts.map +1 -0
  355. package/dist/esm/files/storage/application-storage-key.backend.utils.js +123 -0
  356. package/dist/esm/files/storage/application-storage-key.backend.utils.js.map +1 -0
  357. package/dist/esm/files/storage/file-storage-provider.types.d.ts +16 -10
  358. package/dist/esm/files/storage/file-storage-provider.types.d.ts.map +1 -1
  359. package/dist/esm/files/storage/file-storage-provider.types.js.map +1 -1
  360. package/dist/esm/files/storage/local-directory-storage-provider.backend.service.d.ts +67 -8
  361. package/dist/esm/files/storage/local-directory-storage-provider.backend.service.d.ts.map +1 -1
  362. package/dist/esm/files/storage/local-directory-storage-provider.backend.service.js +101 -28
  363. package/dist/esm/files/storage/local-directory-storage-provider.backend.service.js.map +1 -1
  364. package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.d.ts.map +1 -1
  365. package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.js +8 -55
  366. package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.js.map +1 -1
  367. package/dist/esm/files/utils/file-field-schema-path.backend.utils.d.ts.map +1 -1
  368. package/dist/esm/files/utils/file-field-schema-path.backend.utils.js +20 -0
  369. package/dist/esm/files/utils/file-field-schema-path.backend.utils.js.map +1 -1
  370. package/dist/esm/files/utils/file-uploader.utils.d.ts.map +1 -1
  371. package/dist/esm/files/utils/file-uploader.utils.js +12 -0
  372. package/dist/esm/files/utils/file-uploader.utils.js.map +1 -1
  373. package/dist/esm/files/utils/office-document-text-extraction.backend.utils.d.ts +86 -0
  374. package/dist/esm/files/utils/office-document-text-extraction.backend.utils.d.ts.map +1 -0
  375. package/dist/esm/files/utils/office-document-text-extraction.backend.utils.js +288 -0
  376. package/dist/esm/files/utils/office-document-text-extraction.backend.utils.js.map +1 -0
  377. package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.d.ts +15 -0
  378. package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.d.ts.map +1 -1
  379. package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.js +76 -5
  380. package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.js.map +1 -1
  381. package/dist/esm/flows-actors/a2a/controllers/a2a.controller.d.ts.map +1 -1
  382. package/dist/esm/flows-actors/a2a/controllers/a2a.controller.js +6 -1
  383. package/dist/esm/flows-actors/a2a/controllers/a2a.controller.js.map +1 -1
  384. package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.d.ts +60 -0
  385. package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.d.ts.map +1 -1
  386. package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.js +63 -0
  387. package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.js.map +1 -1
  388. package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.d.ts +74 -0
  389. package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.d.ts.map +1 -1
  390. package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.js +200 -44
  391. package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.js.map +1 -1
  392. package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.d.ts +7 -1
  393. package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.d.ts.map +1 -1
  394. package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.js +53 -1
  395. package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.js.map +1 -1
  396. package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.d.ts +18 -0
  397. package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.d.ts.map +1 -1
  398. package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.js +18 -0
  399. package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.js.map +1 -1
  400. package/dist/esm/flows-actors/a2a/services/a2a.backend.service.d.ts +12 -7
  401. package/dist/esm/flows-actors/a2a/services/a2a.backend.service.d.ts.map +1 -1
  402. package/dist/esm/flows-actors/a2a/services/a2a.backend.service.js.map +1 -1
  403. package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.d.ts +0 -13
  404. package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.d.ts.map +1 -1
  405. package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.js +14 -22
  406. package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.js.map +1 -1
  407. package/dist/esm/flows-actors/models/core-facets.backend.definitions.d.ts +8 -3
  408. package/dist/esm/flows-actors/models/core-facets.backend.definitions.d.ts.map +1 -1
  409. package/dist/esm/flows-actors/models/core-facets.backend.definitions.js +25 -15
  410. package/dist/esm/flows-actors/models/core-facets.backend.definitions.js.map +1 -1
  411. package/dist/esm/flows-actors/models/flows-actors.backend.schemas.d.ts +13 -1
  412. package/dist/esm/flows-actors/models/flows-actors.backend.schemas.d.ts.map +1 -1
  413. package/dist/esm/flows-actors/models/flows-actors.backend.schemas.js.map +1 -1
  414. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts +88 -8
  415. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts.map +1 -1
  416. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js +333 -31
  417. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js.map +1 -1
  418. package/dist/esm/flows-actors/models/market-generation.actors-system.backend.definitions.d.ts.map +1 -1
  419. package/dist/esm/flows-actors/models/market-generation.actors-system.backend.definitions.js +4 -2
  420. package/dist/esm/flows-actors/models/market-generation.actors-system.backend.definitions.js.map +1 -1
  421. package/dist/esm/flows-actors/models/mcp-client.backend.definitions.d.ts +113 -0
  422. package/dist/esm/flows-actors/models/mcp-client.backend.definitions.d.ts.map +1 -0
  423. package/dist/esm/flows-actors/models/mcp-client.backend.definitions.js +62 -0
  424. package/dist/esm/flows-actors/models/mcp-client.backend.definitions.js.map +1 -0
  425. package/dist/esm/flows-actors/services/actors-system.backend.service.d.ts.map +1 -1
  426. package/dist/esm/flows-actors/services/actors-system.backend.service.js +0 -2
  427. package/dist/esm/flows-actors/services/actors-system.backend.service.js.map +1 -1
  428. package/dist/esm/flows-actors/services/agents.backend.service.d.ts +107 -1
  429. package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
  430. package/dist/esm/flows-actors/services/agents.backend.service.js +519 -56
  431. package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
  432. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts +5 -1
  433. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts.map +1 -1
  434. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js +79 -16
  435. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js.map +1 -1
  436. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts +34 -5
  437. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts.map +1 -1
  438. package/dist/esm/flows-actors/services/flows-actors-registry.service.js +154 -20
  439. package/dist/esm/flows-actors/services/flows-actors-registry.service.js.map +1 -1
  440. package/dist/esm/flows-actors/services/flows.backend.services.d.ts.map +1 -1
  441. package/dist/esm/flows-actors/services/flows.backend.services.js +27 -23
  442. package/dist/esm/flows-actors/services/flows.backend.services.js.map +1 -1
  443. package/dist/esm/flows-actors/services/llm-observability-agent-call-trace-sink.backend.d.ts.map +1 -1
  444. package/dist/esm/flows-actors/services/llm-observability-agent-call-trace-sink.backend.js +7 -1
  445. package/dist/esm/flows-actors/services/llm-observability-agent-call-trace-sink.backend.js.map +1 -1
  446. package/dist/esm/flows-actors/services/mcp-client.backend.service.d.ts +90 -0
  447. package/dist/esm/flows-actors/services/mcp-client.backend.service.d.ts.map +1 -0
  448. package/dist/esm/flows-actors/services/mcp-client.backend.service.js +368 -0
  449. package/dist/esm/flows-actors/services/mcp-client.backend.service.js.map +1 -0
  450. package/dist/esm/flows-actors/services/prompt-compiler.backend.service.d.ts +9 -5
  451. package/dist/esm/flows-actors/services/prompt-compiler.backend.service.d.ts.map +1 -1
  452. package/dist/esm/flows-actors/services/prompt-compiler.backend.service.js +12 -17
  453. package/dist/esm/flows-actors/services/prompt-compiler.backend.service.js.map +1 -1
  454. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts +151 -41
  455. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts.map +1 -1
  456. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js +308 -143
  457. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
  458. package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.d.ts +0 -207
  459. package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.d.ts.map +1 -1
  460. package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.js +8 -243
  461. package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.js.map +1 -1
  462. package/dist/esm/flows-actors/utils/meta-workflow-structured-generation-plan.backend.utils.d.ts.map +1 -1
  463. package/dist/esm/flows-actors/utils/meta-workflow-structured-generation-plan.backend.utils.js.map +1 -1
  464. package/dist/esm/guidance/services/milestone-evaluator.backend.service.d.ts +9 -14
  465. package/dist/esm/guidance/services/milestone-evaluator.backend.service.d.ts.map +1 -1
  466. package/dist/esm/guidance/services/milestone-evaluator.backend.service.js +18 -89
  467. package/dist/esm/guidance/services/milestone-evaluator.backend.service.js.map +1 -1
  468. package/dist/esm/guidance/services/progression-state-store.backend.service.d.ts +86 -0
  469. package/dist/esm/guidance/services/progression-state-store.backend.service.d.ts.map +1 -0
  470. package/dist/esm/guidance/services/progression-state-store.backend.service.js +155 -0
  471. package/dist/esm/guidance/services/progression-state-store.backend.service.js.map +1 -0
  472. package/dist/esm/i18n/controllers/i18n-controller.backend.service.d.ts +10 -0
  473. package/dist/esm/i18n/controllers/i18n-controller.backend.service.d.ts.map +1 -1
  474. package/dist/esm/i18n/controllers/i18n-controller.backend.service.js +55 -5
  475. package/dist/esm/i18n/controllers/i18n-controller.backend.service.js.map +1 -1
  476. package/dist/esm/index.d.ts +15 -5
  477. package/dist/esm/index.d.ts.map +1 -1
  478. package/dist/esm/index.js +45 -5
  479. package/dist/esm/index.js.map +1 -1
  480. package/dist/esm/inject/models/container.d.ts.map +1 -1
  481. package/dist/esm/inject/models/container.js +82 -10
  482. package/dist/esm/inject/models/container.js.map +1 -1
  483. package/dist/esm/inject/models/service-types.d.ts +20 -3
  484. package/dist/esm/inject/models/service-types.d.ts.map +1 -1
  485. package/dist/esm/inject/models/service-types.js +21 -3
  486. package/dist/esm/inject/models/service-types.js.map +1 -1
  487. package/dist/esm/mcp/controllers/mcp.controller.d.ts.map +1 -1
  488. package/dist/esm/mcp/controllers/mcp.controller.js +32 -4
  489. package/dist/esm/mcp/controllers/mcp.controller.js.map +1 -1
  490. package/dist/esm/mcp/models/mcp-tool.backend.schemas.d.ts +34 -0
  491. package/dist/esm/mcp/models/mcp-tool.backend.schemas.d.ts.map +1 -1
  492. package/dist/esm/mcp/models/mcp-tool.backend.schemas.js +42 -0
  493. package/dist/esm/mcp/models/mcp-tool.backend.schemas.js.map +1 -1
  494. package/dist/esm/mcp/services/mcp-server.backend.service.d.ts +84 -1
  495. package/dist/esm/mcp/services/mcp-server.backend.service.d.ts.map +1 -1
  496. package/dist/esm/mcp/services/mcp-server.backend.service.js +235 -11
  497. package/dist/esm/mcp/services/mcp-server.backend.service.js.map +1 -1
  498. package/dist/esm/mcp/services/mcp-tool-adapter.backend.service.d.ts +64 -2
  499. package/dist/esm/mcp/services/mcp-tool-adapter.backend.service.d.ts.map +1 -1
  500. package/dist/esm/mcp/services/mcp-tool-adapter.backend.service.js +152 -6
  501. package/dist/esm/mcp/services/mcp-tool-adapter.backend.service.js.map +1 -1
  502. package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.d.ts.map +1 -1
  503. package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.js +49 -4
  504. package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.js.map +1 -1
  505. package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.d.ts +66 -0
  506. package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.d.ts.map +1 -0
  507. package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.js +199 -0
  508. package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.js.map +1 -0
  509. package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.d.ts +149 -13
  510. package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.d.ts.map +1 -1
  511. package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.js +411 -19
  512. package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.js.map +1 -1
  513. package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.d.ts +11 -2
  514. package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.d.ts.map +1 -1
  515. package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.js.map +1 -1
  516. package/dist/esm/monitoring/logger/models/logger.backend.schemas.d.ts +28 -9
  517. package/dist/esm/monitoring/logger/models/logger.backend.schemas.d.ts.map +1 -1
  518. package/dist/esm/monitoring/logger/models/logger.backend.schemas.js +30 -10
  519. package/dist/esm/monitoring/logger/models/logger.backend.schemas.js.map +1 -1
  520. package/dist/esm/monitoring/logger/services/logger.service.d.ts +12 -0
  521. package/dist/esm/monitoring/logger/services/logger.service.d.ts.map +1 -1
  522. package/dist/esm/monitoring/logger/services/logger.service.js +52 -11
  523. package/dist/esm/monitoring/logger/services/logger.service.js.map +1 -1
  524. package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.d.ts +62 -0
  525. package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.d.ts.map +1 -0
  526. package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.js +78 -0
  527. package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.js.map +1 -0
  528. package/dist/esm/monitoring/observability/audit-observation-emission.backend.d.ts +309 -0
  529. package/dist/esm/monitoring/observability/audit-observation-emission.backend.d.ts.map +1 -0
  530. package/dist/esm/monitoring/observability/audit-observation-emission.backend.js +385 -0
  531. package/dist/esm/monitoring/observability/audit-observation-emission.backend.js.map +1 -0
  532. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts +1 -0
  533. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts.map +1 -1
  534. package/dist/esm/monitoring/observability/models/observability.backend.schemas.js.map +1 -1
  535. package/dist/esm/monitoring/observability/services/metrics.service.d.ts +21 -0
  536. package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -1
  537. package/dist/esm/monitoring/observability/services/metrics.service.js +38 -0
  538. package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -1
  539. package/dist/esm/notifications/email/models/email-context-provider.interface.d.ts +0 -80
  540. package/dist/esm/notifications/email/models/email-context-provider.interface.d.ts.map +0 -1
  541. package/dist/esm/notifications/email/models/email-context-provider.interface.js +0 -25
  542. package/dist/esm/notifications/email/models/email-context-provider.interface.js.map +0 -1
  543. package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.d.ts +0 -49
  544. package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.d.ts.map +0 -1
  545. package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.js +0 -141
  546. package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.js.map +0 -1
  547. package/dist/esm/notifications/email/services/email-template-compiler.backend.service.d.ts +0 -37
  548. package/dist/esm/notifications/email/services/email-template-compiler.backend.service.d.ts.map +0 -1
  549. package/dist/esm/notifications/email/services/email-template-compiler.backend.service.js +0 -121
  550. package/dist/esm/notifications/email/services/email-template-compiler.backend.service.js.map +0 -1
  551. package/dist/esm/notifications/email/services/email-template-registry.backend.service.d.ts +66 -1
  552. package/dist/esm/notifications/email/services/email-template-registry.backend.service.d.ts.map +1 -1
  553. package/dist/esm/notifications/email/services/email-template-registry.backend.service.js +105 -10
  554. package/dist/esm/notifications/email/services/email-template-registry.backend.service.js.map +1 -1
  555. package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.d.ts +0 -58
  556. package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.d.ts.map +0 -1
  557. package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.js +0 -223
  558. package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.js.map +0 -1
  559. package/dist/esm/notifications/email/services/email-template-validator.backend.service.d.ts.map +1 -1
  560. package/dist/esm/notifications/email/services/email-template-validator.backend.service.js +10 -1
  561. package/dist/esm/notifications/email/services/email-template-validator.backend.service.js.map +1 -1
  562. package/dist/esm/notifications/email/services/email.backend.service.d.ts +60 -4
  563. package/dist/esm/notifications/email/services/email.backend.service.d.ts.map +1 -1
  564. package/dist/esm/notifications/email/services/email.backend.service.js +145 -43
  565. package/dist/esm/notifications/email/services/email.backend.service.js.map +1 -1
  566. package/dist/esm/notifications/email/utils/color-conversion.utils.d.ts +0 -1
  567. package/dist/esm/notifications/email/utils/color-conversion.utils.d.ts.map +1 -1
  568. package/dist/esm/notifications/email/utils/color-conversion.utils.js.map +1 -1
  569. package/dist/esm/notifications/services/notification-badge.backend.service.d.ts +142 -21
  570. package/dist/esm/notifications/services/notification-badge.backend.service.d.ts.map +1 -1
  571. package/dist/esm/notifications/services/notification-badge.backend.service.js +283 -58
  572. package/dist/esm/notifications/services/notification-badge.backend.service.js.map +1 -1
  573. package/dist/esm/notifications/services/notifications-dispatcher.backend.service.d.ts +108 -13
  574. package/dist/esm/notifications/services/notifications-dispatcher.backend.service.d.ts.map +1 -1
  575. package/dist/esm/notifications/services/notifications-dispatcher.backend.service.js +432 -101
  576. package/dist/esm/notifications/services/notifications-dispatcher.backend.service.js.map +1 -1
  577. package/dist/esm/notifications/sms/services/sms.backend.service.d.ts +2 -2
  578. package/dist/esm/notifications/sms/services/sms.backend.service.d.ts.map +1 -1
  579. package/dist/esm/notifications/sms/services/sms.backend.service.js +5 -5
  580. package/dist/esm/notifications/sms/services/sms.backend.service.js.map +1 -1
  581. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts +117 -5
  582. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts.map +1 -1
  583. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js +164 -6
  584. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js.map +1 -1
  585. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.d.ts +0 -6
  586. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.d.ts.map +1 -1
  587. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.js +54 -7
  588. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.js.map +1 -1
  589. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.utils.d.ts +5 -5
  590. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.utils.d.ts.map +1 -1
  591. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.utils.js +14 -13
  592. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.utils.js.map +1 -1
  593. package/dist/esm/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.d.ts +2 -1
  594. package/dist/esm/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.d.ts.map +1 -1
  595. package/dist/esm/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.js +18 -8
  596. package/dist/esm/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.js.map +1 -1
  597. package/dist/esm/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.d.ts.map +1 -1
  598. package/dist/esm/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.js +20 -18
  599. package/dist/esm/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.js.map +1 -1
  600. package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.d.ts +16 -0
  601. package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.d.ts.map +1 -1
  602. package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.js +18 -0
  603. package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.js.map +1 -1
  604. package/dist/esm/organizations/batches/organization-purge.batch.backend.service.d.ts +2 -2
  605. package/dist/esm/organizations/batches/organization-purge.batch.backend.service.js +2 -2
  606. package/dist/esm/organizations/batches/organization-purge.batch.backend.service.js.map +1 -1
  607. package/dist/esm/organizations/services/organization-custom-implementation.backend.service.d.ts.map +1 -1
  608. package/dist/esm/organizations/services/organization-custom-implementation.backend.service.js +63 -2
  609. package/dist/esm/organizations/services/organization-custom-implementation.backend.service.js.map +1 -1
  610. package/dist/esm/organizations/services/organization-unit-custom-implementation.backend.service.d.ts.map +1 -1
  611. package/dist/esm/organizations/services/organization-unit-custom-implementation.backend.service.js +4 -1
  612. package/dist/esm/organizations/services/organization-unit-custom-implementation.backend.service.js.map +1 -1
  613. package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.d.ts +66 -0
  614. package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.d.ts.map +1 -0
  615. package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.js +257 -0
  616. package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.js.map +1 -0
  617. package/dist/esm/queue/adapters/queue-adapter.backend.binding.d.ts +12 -0
  618. package/dist/esm/queue/adapters/queue-adapter.backend.binding.d.ts.map +1 -0
  619. package/dist/esm/queue/adapters/queue-adapter.backend.binding.js +47 -0
  620. package/dist/esm/queue/adapters/queue-adapter.backend.binding.js.map +1 -0
  621. package/dist/esm/queue/adapters/queue-adapter.backend.interface.d.ts +87 -0
  622. package/dist/esm/queue/adapters/queue-adapter.backend.interface.d.ts.map +1 -0
  623. package/dist/esm/queue/adapters/queue-adapter.backend.interface.js +1 -0
  624. package/dist/esm/queue/adapters/queue-adapter.backend.interface.js.map +1 -0
  625. package/dist/esm/queue/adapters/queue-adapter.backend.options.d.ts +31 -0
  626. package/dist/esm/queue/adapters/queue-adapter.backend.options.d.ts.map +1 -0
  627. package/dist/esm/queue/adapters/queue-adapter.backend.options.js +13 -0
  628. package/dist/esm/queue/adapters/queue-adapter.backend.options.js.map +1 -0
  629. package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.d.ts +19 -25
  630. package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.d.ts.map +1 -1
  631. package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.js +33 -0
  632. package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.js.map +1 -1
  633. package/dist/esm/queue/domain-queue-consumer.backend.service.d.ts +2 -2
  634. package/dist/esm/queue/domain-queue-consumer.backend.service.d.ts.map +1 -1
  635. package/dist/esm/queue/domain-queue-consumer.backend.service.js +1 -4
  636. package/dist/esm/queue/domain-queue-consumer.backend.service.js.map +1 -1
  637. package/dist/esm/queue/job-consumer.backend.service.d.ts +2 -2
  638. package/dist/esm/queue/job-consumer.backend.service.d.ts.map +1 -1
  639. package/dist/esm/queue/job-consumer.backend.service.js +1 -4
  640. package/dist/esm/queue/job-consumer.backend.service.js.map +1 -1
  641. package/dist/esm/queue/job-executor.backend.service.d.ts +2 -2
  642. package/dist/esm/queue/job-executor.backend.service.d.ts.map +1 -1
  643. package/dist/esm/queue/job-executor.backend.service.js +1 -4
  644. package/dist/esm/queue/job-executor.backend.service.js.map +1 -1
  645. package/dist/esm/queue/queue-monitoring.backend.service.d.ts +8 -4
  646. package/dist/esm/queue/queue-monitoring.backend.service.d.ts.map +1 -1
  647. package/dist/esm/queue/queue-monitoring.backend.service.js +25 -17
  648. package/dist/esm/queue/queue-monitoring.backend.service.js.map +1 -1
  649. package/dist/esm/queue/queue-worker-initializer.backend.service.d.ts +16 -1
  650. package/dist/esm/queue/queue-worker-initializer.backend.service.d.ts.map +1 -1
  651. package/dist/esm/queue/queue-worker-initializer.backend.service.js +16 -1
  652. package/dist/esm/queue/queue-worker-initializer.backend.service.js.map +1 -1
  653. package/dist/esm/queue/queue.backend.service.d.ts +3 -3
  654. package/dist/esm/queue/queue.backend.service.d.ts.map +1 -1
  655. package/dist/esm/queue/queue.backend.service.js +26 -4
  656. package/dist/esm/queue/queue.backend.service.js.map +1 -1
  657. package/dist/esm/queue/worker-shutdown-manager.backend.service.d.ts +2 -2
  658. package/dist/esm/queue/worker-shutdown-manager.backend.service.d.ts.map +1 -1
  659. package/dist/esm/queue/worker-shutdown-manager.backend.service.js +18 -3
  660. package/dist/esm/queue/worker-shutdown-manager.backend.service.js.map +1 -1
  661. package/dist/esm/rag/utils/rag-chunking.backend.utils.d.ts +50 -25
  662. package/dist/esm/rag/utils/rag-chunking.backend.utils.d.ts.map +1 -1
  663. package/dist/esm/rag/utils/rag-chunking.backend.utils.js +147 -39
  664. package/dist/esm/rag/utils/rag-chunking.backend.utils.js.map +1 -1
  665. package/dist/esm/rag/utils/rag-context-assembly.backend.utils.d.ts +12 -3
  666. package/dist/esm/rag/utils/rag-context-assembly.backend.utils.d.ts.map +1 -1
  667. package/dist/esm/rag/utils/rag-context-assembly.backend.utils.js +12 -3
  668. package/dist/esm/rag/utils/rag-context-assembly.backend.utils.js.map +1 -1
  669. package/dist/esm/requests/service/websocket.service.d.ts +9 -0
  670. package/dist/esm/requests/service/websocket.service.d.ts.map +1 -1
  671. package/dist/esm/requests/service/websocket.service.js +88 -15
  672. package/dist/esm/requests/service/websocket.service.js.map +1 -1
  673. package/dist/esm/resources/models/custom-service-implementations.backend.definition.d.ts.map +1 -1
  674. package/dist/esm/resources/models/custom-service-implementations.backend.definition.js +16 -2
  675. package/dist/esm/resources/models/custom-service-implementations.backend.definition.js.map +1 -1
  676. package/dist/esm/resources/models/resources-operations.backend.definitions.d.ts.map +1 -1
  677. package/dist/esm/resources/models/resources-operations.backend.definitions.js +2 -0
  678. package/dist/esm/resources/models/resources-operations.backend.definitions.js.map +1 -1
  679. package/dist/esm/resources/models/resources-relationships.backend.definitions.d.ts.map +1 -1
  680. package/dist/esm/resources/models/resources-relationships.backend.definitions.js +14 -0
  681. package/dist/esm/resources/models/resources-relationships.backend.definitions.js.map +1 -1
  682. package/dist/esm/resources/models/resources-types.backend.schemas.d.ts +2 -1
  683. package/dist/esm/resources/models/resources-types.backend.schemas.d.ts.map +1 -1
  684. package/dist/esm/resources/models/resources-types.backend.schemas.js +8 -0
  685. package/dist/esm/resources/models/resources-types.backend.schemas.js.map +1 -1
  686. package/dist/esm/resources/services/resource-id.backend.service.js +3 -3
  687. package/dist/esm/resources/services/resource-id.backend.service.js.map +1 -1
  688. package/dist/esm/resources/services/resources-registry.backend.service.d.ts +60 -5
  689. package/dist/esm/resources/services/resources-registry.backend.service.d.ts.map +1 -1
  690. package/dist/esm/resources/services/resources-registry.backend.service.js +91 -7
  691. package/dist/esm/resources/services/resources-registry.backend.service.js.map +1 -1
  692. package/dist/esm/runtime/controllers/health-controller.backend.service.d.ts +36 -3
  693. package/dist/esm/runtime/controllers/health-controller.backend.service.d.ts.map +1 -1
  694. package/dist/esm/runtime/controllers/health-controller.backend.service.js +32 -10
  695. package/dist/esm/runtime/controllers/health-controller.backend.service.js.map +1 -1
  696. package/dist/esm/runtime/domain-module.backend.definitions.d.ts +24 -0
  697. package/dist/esm/runtime/domain-module.backend.definitions.d.ts.map +1 -1
  698. package/dist/esm/runtime/domain-module.backend.definitions.js +24 -0
  699. package/dist/esm/runtime/domain-module.backend.definitions.js.map +1 -1
  700. package/dist/esm/runtime/services/execution-context-creator.backend.service.d.ts.map +1 -1
  701. package/dist/esm/runtime/services/execution-context-creator.backend.service.js +13 -7
  702. package/dist/esm/runtime/services/execution-context-creator.backend.service.js.map +1 -1
  703. package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.d.ts +51 -0
  704. package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.d.ts.map +1 -1
  705. package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.js.map +1 -1
  706. package/dist/esm/runtime/services/http-server.backend.service.d.ts +26 -0
  707. package/dist/esm/runtime/services/http-server.backend.service.d.ts.map +1 -1
  708. package/dist/esm/runtime/services/http-server.backend.service.js +181 -1
  709. package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -1
  710. package/dist/esm/runtime/services/start-application.backend.service.d.ts +47 -1
  711. package/dist/esm/runtime/services/start-application.backend.service.d.ts.map +1 -1
  712. package/dist/esm/runtime/services/start-application.backend.service.js +343 -77
  713. package/dist/esm/runtime/services/start-application.backend.service.js.map +1 -1
  714. package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.d.ts +15 -0
  715. package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.d.ts.map +1 -1
  716. package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.js +28 -0
  717. package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.js.map +1 -1
  718. package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.d.ts +5 -1
  719. package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.d.ts.map +1 -1
  720. package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.js +24 -4
  721. package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.js.map +1 -1
  722. package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.d.ts.map +1 -1
  723. package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.js +29 -4
  724. package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.js.map +1 -1
  725. package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.d.ts +114 -0
  726. package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.d.ts.map +1 -1
  727. package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.js +354 -3
  728. package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.js.map +1 -1
  729. package/dist/esm/security/authentications/models/cimd.backend.schemas.d.ts +1 -0
  730. package/dist/esm/security/authentications/models/cimd.backend.schemas.d.ts.map +1 -1
  731. package/dist/esm/security/authentications/models/cimd.backend.schemas.js +22 -0
  732. package/dist/esm/security/authentications/models/cimd.backend.schemas.js.map +1 -1
  733. package/dist/esm/security/authentications/models/jwt.backend.schemas.d.ts +3 -23
  734. package/dist/esm/security/authentications/models/jwt.backend.schemas.d.ts.map +1 -1
  735. package/dist/esm/security/authentications/models/jwt.backend.schemas.js +20 -45
  736. package/dist/esm/security/authentications/models/jwt.backend.schemas.js.map +1 -1
  737. package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.d.ts +15 -0
  738. package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.d.ts.map +1 -1
  739. package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.js.map +1 -1
  740. package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.d.ts +0 -2
  741. package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.d.ts.map +1 -1
  742. package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.js +23 -14
  743. package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.js.map +1 -1
  744. package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.d.ts +0 -1
  745. package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.d.ts.map +1 -1
  746. package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.js +15 -12
  747. package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.js.map +1 -1
  748. package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.d.ts +113 -3
  749. package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.d.ts.map +1 -1
  750. package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.js +207 -30
  751. package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.js.map +1 -1
  752. package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.d.ts +95 -2
  753. package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.d.ts.map +1 -1
  754. package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.js +153 -9
  755. package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.js.map +1 -1
  756. package/dist/esm/security/authentications/services/anonymous-session.backend.service.d.ts +190 -0
  757. package/dist/esm/security/authentications/services/anonymous-session.backend.service.d.ts.map +1 -1
  758. package/dist/esm/security/authentications/services/anonymous-session.backend.service.js +377 -53
  759. package/dist/esm/security/authentications/services/anonymous-session.backend.service.js.map +1 -1
  760. package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.d.ts +9 -1
  761. package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.d.ts.map +1 -1
  762. package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.js +77 -2
  763. package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.js.map +1 -1
  764. package/dist/esm/security/authentications/services/auth-methods/auth-mfa.backend.service.d.ts.map +1 -1
  765. package/dist/esm/security/authentications/services/auth-methods/auth-mfa.backend.service.js +5 -3
  766. package/dist/esm/security/authentications/services/auth-methods/auth-mfa.backend.service.js.map +1 -1
  767. package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.d.ts +41 -0
  768. package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.d.ts.map +1 -1
  769. package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.js +202 -23
  770. package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.js.map +1 -1
  771. package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.d.ts.map +1 -1
  772. package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.js +42 -1
  773. package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.js.map +1 -1
  774. package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.d.ts.map +1 -1
  775. package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.js +34 -4
  776. package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.js.map +1 -1
  777. package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.d.ts +29 -5
  778. package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.d.ts.map +1 -1
  779. package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.js +77 -5
  780. package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.js.map +1 -1
  781. package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.d.ts +41 -1
  782. package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.d.ts.map +1 -1
  783. package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.js +87 -4
  784. package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.js.map +1 -1
  785. package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.d.ts +43 -1
  786. package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.d.ts.map +1 -1
  787. package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.js +277 -97
  788. package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.js.map +1 -1
  789. package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.d.ts +28 -5
  790. package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.d.ts.map +1 -1
  791. package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.js +72 -12
  792. package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.js.map +1 -1
  793. package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.d.ts.map +1 -1
  794. package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.js +3 -0
  795. package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.js.map +1 -1
  796. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts +28 -0
  797. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts.map +1 -0
  798. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js +283 -0
  799. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js.map +1 -0
  800. package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.d.ts +4 -3
  801. package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.d.ts.map +1 -1
  802. package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.js +4 -3
  803. package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.js.map +1 -1
  804. package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.d.ts +35 -0
  805. package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.d.ts.map +1 -1
  806. package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.js +111 -21
  807. package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.js.map +1 -1
  808. package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.d.ts +14 -1
  809. package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.d.ts.map +1 -1
  810. package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.js +49 -8
  811. package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.js.map +1 -1
  812. package/dist/esm/security/authentications/services/utils/auth-policy-resolution.backend.utils.d.ts.map +1 -1
  813. package/dist/esm/security/authentications/services/utils/auth-policy-resolution.backend.utils.js +4 -0
  814. package/dist/esm/security/authentications/services/utils/auth-policy-resolution.backend.utils.js.map +1 -1
  815. package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.d.ts.map +1 -1
  816. package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.js +6 -0
  817. package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.js.map +1 -1
  818. package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.d.ts +37 -1
  819. package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.d.ts.map +1 -1
  820. package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.js +51 -0
  821. package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.js.map +1 -1
  822. package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.d.ts +41 -0
  823. package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.d.ts.map +1 -1
  824. package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.js +45 -0
  825. package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.js.map +1 -1
  826. package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.d.ts +116 -0
  827. package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.d.ts.map +1 -0
  828. package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.js +162 -0
  829. package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.js.map +1 -0
  830. package/dist/esm/security/authorizations/initiator-organization-confinement.backend.d.ts.map +1 -1
  831. package/dist/esm/security/authorizations/initiator-organization-confinement.backend.js +24 -1
  832. package/dist/esm/security/authorizations/initiator-organization-confinement.backend.js.map +1 -1
  833. package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.d.ts +20 -20
  834. package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.d.ts.map +1 -1
  835. package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.js +27 -28
  836. package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.js.map +1 -1
  837. package/dist/esm/security/authorizations/platform-access-grant-custom-implementation.backend.service.d.ts.map +1 -1
  838. package/dist/esm/security/authorizations/platform-access-grant-custom-implementation.backend.service.js +77 -3
  839. package/dist/esm/security/authorizations/platform-access-grant-custom-implementation.backend.service.js.map +1 -1
  840. package/dist/esm/security/authorizations/privileged-access-review.backend.utils.d.ts +117 -0
  841. package/dist/esm/security/authorizations/privileged-access-review.backend.utils.d.ts.map +1 -0
  842. package/dist/esm/security/authorizations/privileged-access-review.backend.utils.js +104 -0
  843. package/dist/esm/security/authorizations/privileged-access-review.backend.utils.js.map +1 -0
  844. package/dist/esm/security/authorizations/role-ceiling.backend.utils.d.ts +4 -0
  845. package/dist/esm/security/authorizations/role-ceiling.backend.utils.d.ts.map +1 -1
  846. package/dist/esm/security/authorizations/role-ceiling.backend.utils.js +4 -0
  847. package/dist/esm/security/authorizations/role-ceiling.backend.utils.js.map +1 -1
  848. package/dist/esm/security/authorizations/role-conferral.backend.utils.d.ts +93 -0
  849. package/dist/esm/security/authorizations/role-conferral.backend.utils.d.ts.map +1 -0
  850. package/dist/esm/security/authorizations/role-conferral.backend.utils.js +95 -0
  851. package/dist/esm/security/authorizations/role-conferral.backend.utils.js.map +1 -0
  852. package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.d.ts +124 -1
  853. package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.d.ts.map +1 -1
  854. package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.js +142 -5
  855. package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.js.map +1 -1
  856. package/dist/esm/security/authorizations/services/authorizations.backend.service.d.ts +175 -14
  857. package/dist/esm/security/authorizations/services/authorizations.backend.service.d.ts.map +1 -1
  858. package/dist/esm/security/authorizations/services/authorizations.backend.service.js +385 -49
  859. package/dist/esm/security/authorizations/services/authorizations.backend.service.js.map +1 -1
  860. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts +6 -14
  861. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts.map +1 -1
  862. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js +13 -22
  863. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js.map +1 -1
  864. package/dist/esm/security/connected-accounts/connection-target-authorization.backend.d.ts +60 -0
  865. package/dist/esm/security/connected-accounts/connection-target-authorization.backend.d.ts.map +1 -0
  866. package/dist/esm/security/connected-accounts/connection-target-authorization.backend.js +79 -0
  867. package/dist/esm/security/connected-accounts/connection-target-authorization.backend.js.map +1 -0
  868. package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.d.ts +161 -0
  869. package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.d.ts.map +1 -0
  870. package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.js +512 -0
  871. package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.js.map +1 -0
  872. package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.d.ts +59 -0
  873. package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.d.ts.map +1 -0
  874. package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.js +22 -0
  875. package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.js.map +1 -0
  876. package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.d.ts +44 -0
  877. package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.d.ts.map +1 -0
  878. package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.js +20 -0
  879. package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.js.map +1 -0
  880. package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.d.ts +191 -0
  881. package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.d.ts.map +1 -0
  882. package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.js +385 -0
  883. package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.js.map +1 -0
  884. package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.d.ts +41 -0
  885. package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.d.ts.map +1 -0
  886. package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.js +358 -0
  887. package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.js.map +1 -0
  888. package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.d.ts +160 -0
  889. package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.d.ts.map +1 -0
  890. package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.js +266 -0
  891. package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.js.map +1 -0
  892. package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.d.ts +111 -0
  893. package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.d.ts.map +1 -0
  894. package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.js +107 -0
  895. package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.js.map +1 -0
  896. package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.d.ts +54 -0
  897. package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.d.ts.map +1 -0
  898. package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.js +153 -0
  899. package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.js.map +1 -0
  900. package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.d.ts +195 -0
  901. package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.d.ts.map +1 -0
  902. package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.js +387 -0
  903. package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.js.map +1 -0
  904. package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.d.ts +45 -0
  905. package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.d.ts.map +1 -0
  906. package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.js +291 -0
  907. package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.js.map +1 -0
  908. package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.d.ts +62 -0
  909. package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.d.ts.map +1 -0
  910. package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.js +29 -0
  911. package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.js.map +1 -0
  912. package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.d.ts +127 -0
  913. package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.d.ts.map +1 -0
  914. package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.js +277 -0
  915. package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.js.map +1 -0
  916. package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.d.ts +66 -0
  917. package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.d.ts.map +1 -0
  918. package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.js +75 -0
  919. package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.js.map +1 -0
  920. package/dist/esm/security/consumable-tokens/batches/consumable-tokens-cleanup.batch.backend.service.d.ts +18 -1
  921. package/dist/esm/security/consumable-tokens/batches/consumable-tokens-cleanup.batch.backend.service.d.ts.map +1 -1
  922. package/dist/esm/security/consumable-tokens/batches/consumable-tokens-cleanup.batch.backend.service.js +110 -74
  923. package/dist/esm/security/consumable-tokens/batches/consumable-tokens-cleanup.batch.backend.service.js.map +1 -1
  924. package/dist/esm/security/consumable-tokens/consumable-token-models.exports.d.ts +22 -0
  925. package/dist/esm/security/consumable-tokens/consumable-token-models.exports.d.ts.map +1 -0
  926. package/dist/esm/security/consumable-tokens/consumable-token-models.exports.js +22 -0
  927. package/dist/esm/security/consumable-tokens/consumable-token-models.exports.js.map +1 -0
  928. package/dist/esm/security/consumable-tokens/models/consumable-tokens.backend.resources-config.schemas.d.ts +17 -3
  929. package/dist/esm/security/consumable-tokens/models/consumable-tokens.backend.resources-config.schemas.d.ts.map +1 -1
  930. package/dist/esm/security/consumable-tokens/models/consumable-tokens.backend.resources-config.schemas.js +12 -0
  931. package/dist/esm/security/consumable-tokens/models/consumable-tokens.backend.resources-config.schemas.js.map +1 -1
  932. package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.d.ts +41 -3
  933. package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.d.ts.map +1 -1
  934. package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.js +83 -20
  935. package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.js.map +1 -1
  936. package/dist/esm/security/credential-rotation-grace.backend.utils.d.ts +9 -4
  937. package/dist/esm/security/credential-rotation-grace.backend.utils.d.ts.map +1 -1
  938. package/dist/esm/security/credential-rotation-grace.backend.utils.js +9 -4
  939. package/dist/esm/security/credential-rotation-grace.backend.utils.js.map +1 -1
  940. package/dist/esm/security/jwt/services/jwt.backend.service.d.ts.map +1 -1
  941. package/dist/esm/security/jwt/services/jwt.backend.service.js +1 -18
  942. package/dist/esm/security/jwt/services/jwt.backend.service.js.map +1 -1
  943. package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.d.ts +26 -0
  944. package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.d.ts.map +1 -1
  945. package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.js +43 -0
  946. package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.js.map +1 -1
  947. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts +8 -1
  948. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts.map +1 -1
  949. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js +49 -0
  950. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js.map +1 -1
  951. package/dist/esm/security/scim/controllers/scim.backend.controller.d.ts.map +1 -1
  952. package/dist/esm/security/scim/controllers/scim.backend.controller.js +17 -5
  953. package/dist/esm/security/scim/controllers/scim.backend.controller.js.map +1 -1
  954. package/dist/esm/security/scim/models/scim-protocol.backend.schemas.d.ts +67 -29
  955. package/dist/esm/security/scim/models/scim-protocol.backend.schemas.d.ts.map +1 -1
  956. package/dist/esm/security/scim/models/scim-protocol.backend.schemas.js +47 -25
  957. package/dist/esm/security/scim/models/scim-protocol.backend.schemas.js.map +1 -1
  958. package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.d.ts +10 -2
  959. package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.d.ts.map +1 -1
  960. package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.js +10 -2
  961. package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.js.map +1 -1
  962. package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.d.ts +143 -0
  963. package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.d.ts.map +1 -0
  964. package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.js +258 -0
  965. package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.js.map +1 -0
  966. package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.d.ts +39 -0
  967. package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.d.ts.map +1 -0
  968. package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.js +159 -0
  969. package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.js.map +1 -0
  970. package/dist/tsconfig.build.tsbuildinfo +1 -1
  971. package/package.json +17 -9
  972. package/dist/esm/.builder.pid +0 -9
@@ -1 +1 @@
1
- {"version":3,"file":"m2m-webhook-signed-request.backend.utils.js","sourceRoot":"","sources":["../../../../../../src/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The single outbound-transport primitive for M2M webhooks.\n *\n * Every signed request Wildo emits to a customer endpoint goes through\n * {@link sendSignedWebhookRequest} — the retry worker's real deliveries AND the\n * `webhookConfig.testEndpoint` synthetic probe. Two call sites, one implementation, on\n * purpose: a probe that reached the endpoint through a *different* code path would\n * validate that path rather than the delivery path, which is precisely the reassurance an\n * admin is asking for when they press \"test\". Timeout, User-Agent, signature header name,\n * and body-truncation behaviour are therefore not re-decided per caller.\n *\n * Scope boundary — this module owns the WIRE, nothing else. It does not sign (callers hold\n * their own claims), does not classify (see `classifyResponseStatus`), does not persist,\n * and never throws on a transport failure: an unreachable endpoint is data the caller must\n * report, not an exception. The only way to get an exception out of here is to pass\n * something that is not a valid request.\n *\n * The tunables come from `./batches/m2m-webhook-delivery.batch.utils`, which is\n * deliberately import-free so its pure-decision tests load without the DI graph. They are\n * left there rather than moved up here precisely to preserve that property — this module\n * performs I/O and would drag `@wildo-ai/saas-models` into those tests.\n *\n * @see batches/m2m-webhook-delivery.batch.backend.service.ts — real deliveries.\n * @see services/webhook-config-test-endpoint.custom-impl.backend.service.ts — synthetic probe.\n */\n\nimport { WildoHeaderKeys } from '@wildo-ai/saas-models';\nimport {\n OutboundTargetRejection,\n classifyOutboundTargetUrl,\n} from '~wildo-backend-lib/security/ssrf/outbound-target-guard.backend.utils';\nimport {\n REQUEST_TIMEOUT_MS,\n WEBHOOK_USER_AGENT,\n truncateBody,\n} from './batches/m2m-webhook-delivery.batch.utils';\n\n/**\n * Schemes an outbound webhook delivery may use.\n *\n * `http:` is admitted, and that is a DEFERRED decision rather than an endorsement. The A2A sibling\n * requires HTTPS unconditionally, and the same argument applies here — the signature JWT in transit\n * is a credential. But `WebhookEndpointSchema.url` is a bare `z.url()`, so plaintext endpoints are\n * authorable today and may already be authored; refusing them here would silently stop deliveries for\n * tenants whose configuration was accepted by the framework. Tightening this is a product decision\n * with a migration, not a hardening pass.\n */\nconst M2M_WEBHOOK_ADMITTED_PROTOCOLS = ['https:', 'http:'] as const;\n\n/**\n * Refuse a destination that would turn this server into a request-forgery tool.\n *\n * ## Why the guard is HERE and not on the schema\n *\n * `WebhookEndpointSchema.url` validates shape (`z.url()`) and nothing else, so an admin could author\n * `http://169.254.169.254/latest/meta-data/` and the engine would POST signed payloads to the cloud\n * instance-metadata service — then capture the answer into the delivery log as\n * `responseBodyTruncated`. That makes it a READ primitive, not a blind SSRF, and\n * `webhookConfig.testEndpoint` is a low-friction oracle for it.\n *\n * A schema refine would leave two holes this placement does not have: it would not cover endpoints\n * ALREADY STORED before the refine existed, and it would not cover the A2A push-delivery worker,\n * which reaches this same primitive with a URL its own (separate) guard validated at configuration\n * time. Putting the check at the wire makes it unbypassable for every caller — present and future —\n * which is what `.claude/rules/invariant-call-site-enumeration.md` means by preferring one\n * chokepoint over N hand-applied predicates.\n *\n * ## What it cannot do\n *\n * An ordinary hostname is not resolved, so `hook.attacker.test` with an A record of `169.254.169.254`\n * still passes. That residual is inherited from the shared classifier and is stated there; closing it\n * needs either a resolving check (a check-then-connect, still open to rebinding) or egress-path\n * enforcement. It is a deliberate open item, not an oversight.\n */\nfunction refuseUnsafeWebhookTarget(url: string): string | undefined {\n const rejection = classifyOutboundTargetUrl(url, { admittedProtocols: M2M_WEBHOOK_ADMITTED_PROTOCOLS });\n switch (rejection) {\n case undefined:\n return undefined;\n case OutboundTargetRejection.NOT_ABSOLUTE_ADMITTED_SCHEME:\n return 'refused: endpoint is not an absolute http(s) URL';\n case OutboundTargetRejection.CREDENTIALS_IN_URL:\n // Credentials in the URL would be replayed on every delivery and would land in any log or\n // delivery row that records the target.\n return 'refused: endpoint URL carries embedded credentials';\n case OutboundTargetRejection.PRIVATE_OR_RESERVED_ADDRESS:\n return 'refused: endpoint resolves to a private, loopback, link-local or otherwise reserved address';\n case OutboundTargetRejection.RESERVED_SPECIAL_USE_HOSTNAME:\n return 'refused: endpoint uses a reserved special-use hostname';\n }\n}\n\n/** Consumer-facing digest algorithm carried in every outbound webhook JWT. */\nexport const M2M_WEBHOOK_BODY_HASH_ALGORITHM = 'sha256' as const;\n\n/**\n * Outcome of one attempt at the wire level.\n *\n * `responseStatus` and `networkError` are mutually exclusive and exhaustive: either the\n * endpoint produced an HTTP response or it did not. Callers classify from there — this\n * type deliberately carries no verdict of its own, because \"429 is retryable\" is a\n * delivery-policy question and \"429 means the endpoint is reachable\" is a probe question,\n * and the same status answers both differently.\n */\nexport type SignedWebhookRequestResult = {\n /** Set when the endpoint answered, whatever the status. */\n responseStatus?: number;\n /** Best-effort capture of the consumer's response body, truncated on a UTF-8 boundary. */\n responseBodyTruncated?: string;\n /** Set when no HTTP response was obtained (DNS/TLS/connection failure, or timeout). */\n networkError?: string;\n /** Wall-clock duration of this attempt alone, excluding any caller-side work. */\n durationMs: number;\n};\n\n/**\n * Render a `fetch` rejection into something an operator can act on.\n *\n * Node's `fetch` (undici) rejects with a flat `TypeError: fetch failed` and buries the actual\n * cause — `ECONNREFUSED`, `ENOTFOUND`, `EHOSTUNREACH`, a TLS failure — one or more levels down in\n * `error.cause`. Reporting only `error.message` tells an admin their endpoint failed without\n * telling them whether the hostname is wrong, the port is closed, or the certificate is bad; for a\n * diagnostic whose entire job is to explain a failure, that is barely better than the silent\n * success this operation used to return. So walk the cause chain and append what it names.\n *\n * `AggregateError` (emitted when every resolved address fails, e.g. happy-eyeballs against a dead\n * host) carries its detail in `errors[]` rather than `cause`, so that shape is unwrapped too.\n * Depth-capped and de-duplicated: the chain is attacker-adjacent input in the sense that a hostile\n * endpoint controls how deep it goes, and a repeated message adds nothing.\n */\nfunction describeFetchFailure(error: unknown): string {\n if (!(error instanceof Error)) return String(error);\n\n const parts: string[] = [];\n const seen = new Set<string>();\n let current: unknown = error;\n\n for (let depth = 0; depth < 4 && current instanceof Error; depth += 1) {\n // `code` is where Node puts the actionable token (ECONNREFUSED, …); the message often repeats it.\n const code = (current as NodeJS.ErrnoException).code;\n const label = code && !current.message.includes(code) ? `${current.message} (${code})` : current.message;\n if (label && !seen.has(label)) {\n seen.add(label);\n parts.push(label);\n }\n const aggregated = current instanceof AggregateError ? current.errors?.[0] : undefined;\n current = aggregated ?? (current as { cause?: unknown }).cause;\n }\n\n return parts.join(': ') || 'fetch failed';\n}\n\n/**\n * POST a pre-signed body to a webhook endpoint under a hard timeout.\n *\n * Never throws for a transport failure — a refused connection, a DNS miss and a timeout\n * all come back as `networkError`. A timeout is reported with its budget spelled out\n * because \"timed out\" alone sends an operator hunting for the wrong thing.\n *\n * Body capture is best-effort: a consumer that returns an unreadable body still produced a\n * valid status, and losing the body must not turn a successful attempt into a failed one.\n */\nexport async function sendSignedWebhookRequest(params: {\n /** Absolute destination URL. */\n url: string;\n /** Exact bytes to send — already the string whose hash the caller signed. */\n body: string;\n /**\n * Value for the `X-Webhook-Signature` header. Omit when the caller authenticates by another\n * mechanism and supplies its own {@link headers} — see below.\n */\n signature?: string;\n /**\n * Caller-supplied headers, MERGED OVER the defaults.\n *\n * Added for the A2A push-notification worker, which authenticates with the CLIENT's declared\n * scheme (`Authorization: {scheme} {credentials}`) and sends `application/a2a+json` rather than\n * Wildo's own ES256 signature and `application/json`.\n *\n * Widening this primitive instead of writing a second POST is deliberate, and follows the module\n * header's own claim to own THE WIRE: timeout, abort handling, failure description and body\n * truncation are the parts that are easy to get subtly wrong and expensive to have two of. What\n * varies between callers is authentication and media type — which are exactly the two things a\n * caller is in a position to decide. Purely additive: `signature` stays optional-by-absence for\n * the two existing M2M call sites, whose behaviour is byte-for-byte unchanged.\n */\n headers?: Record<string, string>;\n}): Promise<SignedWebhookRequestResult> {\n const startedAt = Date.now();\n\n // Refused BEFORE any timer or connection: a target the guard rejects must produce no DNS lookup,\n // no socket, and no signed body on the wire. Reported as `networkError` rather than thrown, because\n // this module's contract is that a destination problem is DATA the caller reports — the probe\n // surfaces it to the admin as UNREACHABLE and the delivery worker records it on the attempt row.\n const refusal = refuseUnsafeWebhookTarget(params.url);\n if (refusal) {\n return { networkError: refusal, durationMs: Date.now() - startedAt };\n }\n\n const abort = new AbortController();\n const timer = setTimeout(() => abort.abort(), REQUEST_TIMEOUT_MS);\n\n let responseStatus: number | undefined;\n let responseBodyTruncated: string | undefined;\n let networkError: string | undefined;\n\n try {\n const response = await fetch(params.url, {\n method: 'POST',\n signal: abort.signal,\n /**\n * A redirect is REPORTED, never followed.\n *\n * Following one re-points the request at a target the guard above never saw, which is the\n * guard's most obvious bypass — an admin authors a public URL that 302s to\n * `http://169.254.169.254/`. It also silently defeats a decision this subsystem had ALREADY\n * taken and could not enforce: `classifyResponseStatus` classifies 3xx as `fatal` and\n * `resolveProbeOutcome` classifies it as REJECTED (\"webhooks must not redirect, and a\n * CDN/proxy redirect on a wrong URL is one of the most common real misconfigurations an admin\n * uses this probe to find\") — but with `fetch`'s default follow behaviour neither of those\n * branches could ever execute, because a 3xx never reached them.\n *\n * `'manual'` rather than `'error'` on purpose: `'error'` would surface as an opaque network\n * failure, whereas `'manual'` hands back the 3xx status so both classifiers see the redirect\n * and tell the admin exactly what their endpoint did.\n */\n redirect: 'manual',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': WEBHOOK_USER_AGENT,\n ...(params.signature ? { [WildoHeaderKeys.X_WEBHOOK_SIGNATURE]: params.signature } : {}),\n ...params.headers,\n },\n body: params.body,\n });\n responseStatus = response.status;\n try {\n const text = await response.text();\n responseBodyTruncated = text ? truncateBody(text) : undefined;\n } catch {\n // Best-effort body capture — never fail the attempt on a non-readable body.\n responseBodyTruncated = undefined;\n }\n } catch (error) {\n networkError = abort.signal.aborted\n ? `request timed out after ${REQUEST_TIMEOUT_MS}ms`\n : describeFetchFailure(error);\n } finally {\n clearTimeout(timer);\n }\n\n return {\n responseStatus,\n responseBodyTruncated,\n networkError,\n durationMs: Date.now() - startedAt,\n };\n}\n"]}
1
+ {"version":3,"file":"m2m-webhook-signed-request.backend.utils.js","sourceRoot":"","sources":["../../../../../../src/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The single outbound-transport primitive for M2M webhooks.\n *\n * Every signed request Wildo emits to a customer endpoint goes through\n * {@link sendSignedWebhookRequest} — the retry worker's real deliveries AND the\n * `webhookConfig.testEndpoint` synthetic probe. Two call sites, one implementation, on\n * purpose: a probe that reached the endpoint through a *different* code path would\n * validate that path rather than the delivery path, which is precisely the reassurance an\n * admin is asking for when they press \"test\". Timeout, User-Agent, signature header name,\n * and body-truncation behaviour are therefore not re-decided per caller.\n *\n * Scope boundary — this module owns the WIRE, nothing else. It does not sign (callers hold\n * their own claims), does not classify (see `classifyResponseStatus`), does not persist,\n * and never throws on a transport failure: an unreachable endpoint is data the caller must\n * report, not an exception. The only way to get an exception out of here is to pass\n * something that is not a valid request.\n *\n * The tunables come from `./batches/m2m-webhook-delivery.batch.utils`, which is\n * deliberately import-free so its pure-decision tests load without the DI graph. They are\n * left there rather than moved up here precisely to preserve that property — this module\n * performs I/O and would drag `@wildo-ai/saas-models` into those tests.\n *\n * @see batches/m2m-webhook-delivery.batch.backend.service.ts — real deliveries.\n * @see services/webhook-config-test-endpoint.custom-impl.backend.service.ts — synthetic probe.\n */\n\nimport { M2M_WEBHOOK_DELIVERY_CONTRACT, WildoHeaderKeys } from '@wildo-ai/saas-models';\nimport {\n OutboundTargetRejection,\n classifyOutboundTargetUrl,\n} from '~wildo-backend-lib/security/ssrf/outbound-target-guard.backend.utils';\nimport {\n REQUEST_TIMEOUT_MS,\n WEBHOOK_USER_AGENT,\n truncateBody,\n} from './batches/m2m-webhook-delivery.batch.utils';\n\n/**\n * Schemes an outbound webhook delivery may use.\n *\n * `http:` is admitted. DECIDED 2026-09-08 (#492): keep admitting it, and document the exposure where\n * a customer authors the endpoint — which is now done, on `WebhookEndpointSchema.url`.\n *\n * This is a COMMERCIAL accommodation, not a security assessment, and the distinction is the whole\n * point of writing it down. The A2A sibling requires HTTPS unconditionally and the same argument\n * applies here — the signature JWT in transit is a credential, readable on the path and replayable\n * until it expires, so an observer of one delivery can forge the next. What was chosen is not to break\n * endpoints that a previous version of the framework accepted.\n *\n * The two options NOT taken, either of which is the better security answer: require HTTPS with a\n * migration that identifies and notifies existing plaintext endpoints, or require it for new endpoints\n * and grandfather existing ones behind an explicit acknowledgement. The second is the one to revisit\n * first — it stops the plaintext population growing without breaking anyone today.\n *\n * Reopen on an observed interception, or on a customer compliance requirement. Do not reopen it as a\n * tidy-up: the asymmetry with the A2A caller is deliberate and is recorded at both sites.\n */\nconst M2M_WEBHOOK_ADMITTED_PROTOCOLS = ['https:', 'http:'] as const;\n\n/**\n * Refuse a destination that would turn this server into a request-forgery tool.\n *\n * ## Why the guard is HERE and not on the schema\n *\n * `WebhookEndpointSchema.url` validates shape (`z.url()`) and nothing else, so an admin could author\n * `http://169.254.169.254/latest/meta-data/` and the engine would POST signed payloads to the cloud\n * instance-metadata service — then capture the answer into the delivery log as\n * `responseBodyTruncated`. That makes it a READ primitive, not a blind SSRF, and\n * `webhookConfig.testEndpoint` is a low-friction oracle for it.\n *\n * A schema refine would leave two holes this placement does not have: it would not cover endpoints\n * ALREADY STORED before the refine existed, and it would not cover the A2A push-delivery worker,\n * which reaches this same primitive with a URL its own (separate) guard validated at configuration\n * time. Putting the check at the wire makes it unbypassable for every caller — present and future —\n * which is what `.claude/rules/invariant-call-site-enumeration.md` means by preferring one\n * chokepoint over N hand-applied predicates.\n *\n * ## What it cannot do\n *\n * An ordinary hostname is not resolved, so `hook.attacker.test` with an A record of `169.254.169.254`\n * still passes. That residual is inherited from the shared classifier and is stated there; closing it\n * needs either a resolving check (a check-then-connect, still open to rebinding) or egress-path\n * enforcement. It is a deliberate open item, not an oversight.\n */\nfunction refuseUnsafeWebhookTarget(url: string): string | undefined {\n const rejection = classifyOutboundTargetUrl(url, { admittedProtocols: M2M_WEBHOOK_ADMITTED_PROTOCOLS });\n switch (rejection) {\n case undefined:\n return undefined;\n case OutboundTargetRejection.NOT_ABSOLUTE_ADMITTED_SCHEME:\n return 'refused: endpoint is not an absolute http(s) URL';\n case OutboundTargetRejection.CREDENTIALS_IN_URL:\n // Credentials in the URL would be replayed on every delivery and would land in any log or\n // delivery row that records the target.\n return 'refused: endpoint URL carries embedded credentials';\n case OutboundTargetRejection.PRIVATE_OR_RESERVED_ADDRESS:\n return 'refused: endpoint resolves to a private, loopback, link-local or otherwise reserved address';\n case OutboundTargetRejection.RESERVED_SPECIAL_USE_HOSTNAME:\n return 'refused: endpoint uses a reserved special-use hostname';\n }\n}\n\n/** Consumer-facing digest algorithm carried in every outbound webhook JWT. */\nexport const M2M_WEBHOOK_BODY_HASH_ALGORITHM: typeof M2M_WEBHOOK_DELIVERY_CONTRACT.bodyHashAlgorithm = M2M_WEBHOOK_DELIVERY_CONTRACT.bodyHashAlgorithm;\n\n/**\n * Outcome of one attempt at the wire level.\n *\n * `responseStatus` and `networkError` are mutually exclusive and exhaustive: either the\n * endpoint produced an HTTP response or it did not. Callers classify from there — this\n * type deliberately carries no verdict of its own, because \"429 is retryable\" is a\n * delivery-policy question and \"429 means the endpoint is reachable\" is a probe question,\n * and the same status answers both differently.\n */\nexport type SignedWebhookRequestResult = {\n /** Set when the endpoint answered, whatever the status. */\n responseStatus?: number;\n /** Best-effort capture of the consumer's response body, truncated on a UTF-8 boundary. */\n responseBodyTruncated?: string;\n /** Set when no HTTP response was obtained (DNS/TLS/connection failure, or timeout). */\n networkError?: string;\n /** Wall-clock duration of this attempt alone, excluding any caller-side work. */\n durationMs: number;\n};\n\n/**\n * Render a `fetch` rejection into something an operator can act on.\n *\n * Node's `fetch` (undici) rejects with a flat `TypeError: fetch failed` and buries the actual\n * cause — `ECONNREFUSED`, `ENOTFOUND`, `EHOSTUNREACH`, a TLS failure — one or more levels down in\n * `error.cause`. Reporting only `error.message` tells an admin their endpoint failed without\n * telling them whether the hostname is wrong, the port is closed, or the certificate is bad; for a\n * diagnostic whose entire job is to explain a failure, that is barely better than the silent\n * success this operation used to return. So walk the cause chain and append what it names.\n *\n * `AggregateError` (emitted when every resolved address fails, e.g. happy-eyeballs against a dead\n * host) carries its detail in `errors[]` rather than `cause`, so that shape is unwrapped too.\n * Depth-capped and de-duplicated: the chain is attacker-adjacent input in the sense that a hostile\n * endpoint controls how deep it goes, and a repeated message adds nothing.\n */\nfunction describeFetchFailure(error: unknown): string {\n if (!(error instanceof Error)) return String(error);\n\n const parts: string[] = [];\n const seen = new Set<string>();\n let current: unknown = error;\n\n for (let depth = 0; depth < 4 && current instanceof Error; depth += 1) {\n // `code` is where Node puts the actionable token (ECONNREFUSED, …); the message often repeats it.\n const code = (current as NodeJS.ErrnoException).code;\n const label = code && !current.message.includes(code) ? `${current.message} (${code})` : current.message;\n if (label && !seen.has(label)) {\n seen.add(label);\n parts.push(label);\n }\n const aggregated = current instanceof AggregateError ? current.errors?.[0] : undefined;\n current = aggregated ?? (current as { cause?: unknown }).cause;\n }\n\n return parts.join(': ') || 'fetch failed';\n}\n\n/**\n * POST a pre-signed body to a webhook endpoint under a hard timeout.\n *\n * Never throws for a transport failure — a refused connection, a DNS miss and a timeout\n * all come back as `networkError`. A timeout is reported with its budget spelled out\n * because \"timed out\" alone sends an operator hunting for the wrong thing.\n *\n * Body capture is best-effort: a consumer that returns an unreadable body still produced a\n * valid status, and losing the body must not turn a successful attempt into a failed one.\n */\nexport async function sendSignedWebhookRequest(params: {\n /** Absolute destination URL. */\n url: string;\n /** Exact bytes to send — already the string whose hash the caller signed. */\n body: string;\n /**\n * Value for the `X-Webhook-Signature` header. Omit when the caller authenticates by another\n * mechanism and supplies its own {@link headers} — see below.\n */\n signature?: string;\n /**\n * Caller-supplied headers, MERGED OVER the defaults.\n *\n * Added for the A2A push-notification worker, which authenticates with the CLIENT's declared\n * scheme (`Authorization: {scheme} {credentials}`) and sends `application/a2a+json` rather than\n * Wildo's own ES256 signature and `application/json`.\n *\n * Widening this primitive instead of writing a second POST is deliberate, and follows the module\n * header's own claim to own THE WIRE: timeout, abort handling, failure description and body\n * truncation are the parts that are easy to get subtly wrong and expensive to have two of. What\n * varies between callers is authentication and media type — which are exactly the two things a\n * caller is in a position to decide. Purely additive: `signature` stays optional-by-absence for\n * the two existing M2M call sites, whose behaviour is byte-for-byte unchanged.\n */\n headers?: Record<string, string>;\n}): Promise<SignedWebhookRequestResult> {\n const startedAt = Date.now();\n\n // Refused BEFORE any timer or connection: a target the guard rejects must produce no DNS lookup,\n // no socket, and no signed body on the wire. Reported as `networkError` rather than thrown, because\n // this module's contract is that a destination problem is DATA the caller reports — the probe\n // surfaces it to the admin as UNREACHABLE and the delivery worker records it on the attempt row.\n const refusal = refuseUnsafeWebhookTarget(params.url);\n if (refusal) {\n return { networkError: refusal, durationMs: Date.now() - startedAt };\n }\n\n const abort = new AbortController();\n const timer = setTimeout(() => abort.abort(), REQUEST_TIMEOUT_MS);\n\n let responseStatus: number | undefined;\n let responseBodyTruncated: string | undefined;\n let networkError: string | undefined;\n\n try {\n const response = await fetch(params.url, {\n method: 'POST',\n signal: abort.signal,\n /**\n * A redirect is REPORTED, never followed.\n *\n * Following one re-points the request at a target the guard above never saw, which is the\n * guard's most obvious bypass — an admin authors a public URL that 302s to\n * `http://169.254.169.254/`. It also silently defeats a decision this subsystem had ALREADY\n * taken and could not enforce: `classifyResponseStatus` classifies 3xx as `fatal` and\n * `resolveProbeOutcome` classifies it as REJECTED (\"webhooks must not redirect, and a\n * CDN/proxy redirect on a wrong URL is one of the most common real misconfigurations an admin\n * uses this probe to find\") — but with `fetch`'s default follow behaviour neither of those\n * branches could ever execute, because a 3xx never reached them.\n *\n * `'manual'` rather than `'error'` on purpose: `'error'` would surface as an opaque network\n * failure, whereas `'manual'` hands back the 3xx status so both classifiers see the redirect\n * and tell the admin exactly what their endpoint did.\n */\n redirect: 'manual',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': WEBHOOK_USER_AGENT,\n ...(params.signature ? { [WildoHeaderKeys.X_WEBHOOK_SIGNATURE]: params.signature } : {}),\n ...params.headers,\n },\n body: params.body,\n });\n responseStatus = response.status;\n try {\n const text = await response.text();\n responseBodyTruncated = text ? truncateBody(text) : undefined;\n } catch {\n // Best-effort body capture — never fail the attempt on a non-readable body.\n responseBodyTruncated = undefined;\n }\n } catch (error) {\n networkError = abort.signal.aborted\n ? `request timed out after ${REQUEST_TIMEOUT_MS}ms`\n : describeFetchFailure(error);\n } finally {\n clearTimeout(timer);\n }\n\n return {\n responseStatus,\n responseBodyTruncated,\n networkError,\n durationMs: Date.now() - startedAt,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-config-test-endpoint.custom-impl.backend.service.d.ts","sourceRoot":"","sources":["../../../../../../../src/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,OAAO,EAWL,2BAA2B,EAI5B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAEL,KAAK,0CAA0C,EAChD,MAAM,4GAA4G,CAAC;AAiDpH;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,2BAA2B,CAKnG;AAED,wBAAgB,wCAAwC,IAAI,0CAA0C,EAAE,CA8LvG"}
1
+ {"version":3,"file":"webhook-config-test-endpoint.custom-impl.backend.service.d.ts","sourceRoot":"","sources":["../../../../../../../src/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,OAAO,EAWL,2BAA2B,EAO5B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAEL,KAAK,0CAA0C,EAChD,MAAM,4GAA4G,CAAC;AAyCpH;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,2BAA2B,CAKnG;AAED,wBAAgB,wCAAwC,IAAI,0CAA0C,EAAE,CAyMvG"}
@@ -38,7 +38,7 @@
38
38
  * @see m2m-webhook-delivery-log.custom-impl.backend.service.ts — sibling REPLACE impls.
39
39
  */
40
40
  import { createHash, randomUUID } from 'node:crypto';
41
- import { AuthScopeType, CoreAuditableEventType, CoreM2MNotificationChannel, CoreResourceType, ErrorCustomMessageReference, ErrorType, ResourceOperationRiskLevel, ResourceOperationVariantType, WebhookConfig_Operations, WebhookConfig_TestEndpointRequestDto, WebhookEndpointProbeOutcome, } from '@wildo-ai/saas-models';
41
+ import { AuthScopeType, CoreAuditableEventType, CoreM2MNotificationChannel, CoreResourceType, ErrorCustomMessageReference, ErrorType, ResourceOperationRiskLevel, ResourceOperationVariantType, WebhookConfig_Operations, WebhookConfig_TestEndpointRequestDto, WebhookEndpointProbeOutcome, webhookEndpointDestinationHost, webhookEndpointTransportIsPlaintext, M2M_WEBHOOK_DELIVERY_CONTRACT, } from '@wildo-ai/saas-models';
42
42
  import { createResourceCustomServiceImplementation, } from '../../../../base-classes/services/services/resource-operation-custom-implementation.factory.backend.js';
43
43
  import { describeCaughtError } from '../../../../errors/utils/error-log-level-classification.backend.utils.js';
44
44
  import { relaxAbuseThrottleMaxForEnvironment } from '../../../../errors/utils/rate-limit-environment-relaxation.backend.utils.js';
@@ -71,15 +71,6 @@ const WEBHOOK_CONFIG_VARIANTS = [
71
71
  */
72
72
  const PROBE_RATE_LIMIT_WINDOW_SECONDS = 60;
73
73
  const PROBE_RATE_LIMIT_MAX_PER_WINDOW = 5;
74
- /** Host-only projection for the audit trail — see the audit schema for why the path is withheld. */
75
- function extractHost(url) {
76
- try {
77
- return new URL(url).host;
78
- }
79
- catch {
80
- return 'unparseable';
81
- }
82
- }
83
74
  /**
84
75
  * Map a transport result onto the reported verdict.
85
76
  *
@@ -194,12 +185,14 @@ export function createWebhookConfigTestEndpointFactories() {
194
185
  let signature;
195
186
  try {
196
187
  signature = await jwtService.sign({
197
- jti: signatureJti,
198
- bodyHash,
199
- bodyHashAlg: M2M_WEBHOOK_BODY_HASH_ALGORITHM,
200
- eventChannel: channel,
201
- resourceIdentifier: String(resourceType),
202
- operationIdentifier: String(WebhookConfig_Operations.TEST_ENDPOINT),
188
+ // Claim names come from the published receiver contract, exactly as the
189
+ // delivery worker signs them; a probe must be verifiable by the same receiver code.
190
+ [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.deliveryId]: signatureJti,
191
+ [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.bodyHash]: bodyHash,
192
+ [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.bodyHashAlgorithm]: M2M_WEBHOOK_BODY_HASH_ALGORITHM,
193
+ [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.eventChannel]: channel,
194
+ [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.resourceIdentifier]: String(resourceType),
195
+ [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.operationIdentifier]: String(WebhookConfig_Operations.TEST_ENDPOINT),
203
196
  // Present ONLY on probes. Lets a consumer that wants to hard-refuse
204
197
  // synthetic traffic do so on the signed envelope rather than on body text.
205
198
  synthetic: true,
@@ -215,6 +208,10 @@ export function createWebhookConfigTestEndpointFactories() {
215
208
  const notSent = {
216
209
  endpointId,
217
210
  url: endpoint.url,
211
+ // Reported even though nothing left the platform: the scheme is a property of the
212
+ // STORED destination, not of this attempt, so an admin fixing a signing fault is
213
+ // still told what the endpoint will cost them once it works (#492).
214
+ transportIsPlaintext: webhookEndpointTransportIsPlaintext(endpoint.url),
218
215
  outcome: WebhookEndpointProbeOutcome.NOT_SENT,
219
216
  failureReason,
220
217
  durationMs: 0,
@@ -232,9 +229,13 @@ export function createWebhookConfigTestEndpointFactories() {
232
229
  // ── Send ──────────────────────────────────────────────────
233
230
  const result = await sendSignedWebhookRequest({ url: endpoint.url, body, signature });
234
231
  const outcome = resolveProbeOutcome(result.responseStatus);
232
+ const transportIsPlaintext = webhookEndpointTransportIsPlaintext(endpoint.url);
235
233
  utils.logger.info('Webhook endpoint test dispatched', {
236
234
  scopeType, scopeId, endpointId,
237
- destinationHost: extractHost(endpoint.url),
235
+ destinationHost: webhookEndpointDestinationHost(endpoint.url),
236
+ // A probe is the moment an operator is looking at ONE endpoint, so it is also the
237
+ // cheapest moment to notice the signature JWT is going out in the clear (#492).
238
+ transportIsPlaintext,
238
239
  outcome,
239
240
  responseStatus: result.responseStatus,
240
241
  durationMs: result.durationMs,
@@ -251,6 +252,7 @@ export function createWebhookConfigTestEndpointFactories() {
251
252
  return {
252
253
  endpointId,
253
254
  url: endpoint.url,
255
+ transportIsPlaintext,
254
256
  outcome,
255
257
  responseStatus: result.responseStatus,
256
258
  responseBodyTruncated: result.responseBodyTruncated,
@@ -295,7 +297,7 @@ async function recordProbeAudit(container, executionContext, data) {
295
297
  // over it — an unattributable egress probe is itself the thing worth noticing.
296
298
  dispatchedBy: actorUserId ?? 'unattributed',
297
299
  endpointId: data.endpointId,
298
- destinationHost: extractHost(data.url),
300
+ destinationHost: webhookEndpointDestinationHost(data.url),
299
301
  outcome: data.outcome,
300
302
  responseStatus: data.responseStatus,
301
303
  durationMs: data.durationMs,
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-config-test-endpoint.custom-impl.backend.service.js","sourceRoot":"","sources":["../../../../../../../src/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Webhook Config TEST_ENDPOINT — REPLACE_CORE_OPERATIONS factory.\n *\n * Makes `webhookConfig.testEndpoint` (org + app variants) do the thing it is named after:\n * fire one signed synthetic delivery at a single stored endpoint and report what came back.\n *\n * Before this implementation the operation was declared `resourceOperationLike: READ` with\n * no handler, so the generic core read answered 200 with the config row. An admin pressing\n * \"test\" on an endpoint whose URL had rotted was told it worked. A connectivity probe that\n * cannot fail is worse than no probe — it converts an unknown into a false assurance — so\n * every failure mode is now a distinct, reported outcome.\n *\n * Design commitments:\n *\n * - **Same transport as real deliveries.** The POST goes through\n * {@link sendSignedWebhookRequest}, shared verbatim with the delivery worker. A probe\n * that reached the endpoint by a different route would attest to that route, not to the\n * delivery path the admin actually cares about.\n * - **Signed like a real delivery.** Same key (`JwtPrivateKeys.APPLICATION_WEBHOOK`), same\n * claim shape, same `X-Webhook-Signature` header, so the consumer's verification code is\n * genuinely exercised rather than bypassed.\n * - **Unmistakably synthetic.** The claims carry `synthetic: true` and the body is a\n * self-describing test envelope. We are POSTing to a customer's production listener; a\n * probe indistinguishable from a real event would invite consumers to act on a fake one.\n * Unknown claims are ignored by existing consumers, so this adds no breaking change.\n * - **No delivery-log row.** Per the operation contract, test traffic stays out of the user\n * event log. The audit trail below is where a probe is recorded.\n * - **A dead endpoint is a 200.** Transport failure at the customer's side is a successful\n * probe carrying `outcome: UNREACHABLE`. HTTP errors are reserved for faults in the\n * request itself — unknown `endpointId`, absent config, rate limit exceeded.\n *\n * Scope resolution mirrors the sibling delivery-log impls: the ORG variant reads\n * `executionContext.organizationId`, the APP variant `applicationId`. The endpoint is then\n * selected by `endpointId` *within that scope's config only*, so a caller cannot aim the\n * probe at another tenant's endpoint — or at an arbitrary URL of their own choosing.\n *\n * @see ../m2m-webhook-signed-request.backend.utils.ts — the shared transport.\n * @see m2m-webhook-delivery-log.custom-impl.backend.service.ts — sibling REPLACE impls.\n */\n\nimport { createHash, randomUUID } from 'node:crypto';\nimport {\n AuthScopeType,\n CoreAuditableEventType,\n CoreM2MNotificationChannel,\n CoreResourceType,\n ErrorCustomMessageReference,\n ErrorType,\n ResourceOperationRiskLevel,\n ResourceOperationVariantType,\n WebhookConfig_Operations,\n WebhookConfig_TestEndpointRequestDto,\n WebhookEndpointProbeOutcome,\n type AuditableEvent_Webhook_EndpointTestDispatchedEventData,\n type WebhookConfigBase,\n type WebhookEndpoint,\n} from '@wildo-ai/saas-models';\nimport type { Container } from 'inversify';\nimport {\n createResourceCustomServiceImplementation,\n type ResourceCustomServiceImplementationFactory,\n} from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation.factory.backend';\nimport type { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';\nimport type { RedisService } from '~wildo-backend-lib/databases/services/redis.service';\nimport { describeCaughtError } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport { relaxAbuseThrottleMaxForEnvironment } from '~wildo-backend-lib/errors/utils/rate-limit-environment-relaxation.backend.utils';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport { JwtPrivateKeys } from '~wildo-backend-lib/security/authentications/models/jwt.backend.schemas';\nimport type { JwtBackendService } from '~wildo-backend-lib/security/jwt/services/jwt.backend.service';\nimport { M2M_WEBHOOK_BODY_HASH_ALGORITHM, sendSignedWebhookRequest } from '../m2m-webhook-signed-request.backend.utils';\n\n/**\n * Variant → (scope type, notification channel) pairing. The channel rides the signed claims\n * so the probe presents itself on the same channel a real delivery from this scope would.\n */\nconst WEBHOOK_CONFIG_VARIANTS = [\n {\n resourceType: CoreResourceType.ORGANIZATION_WEBHOOK_CONFIG,\n scopeType: AuthScopeType.ORGANIZATION,\n channel: CoreM2MNotificationChannel.WEBHOOK_ORGANIZATION,\n },\n {\n resourceType: CoreResourceType.APPLICATION_WEBHOOK_CONFIG,\n scopeType: AuthScopeType.APPLICATION,\n channel: CoreM2MNotificationChannel.WEBHOOK_APPLICATION,\n },\n] as const;\n\n/**\n * Probe budget: at most this many attempts per endpoint per window.\n *\n * Scoped per ENDPOINT rather than per admin: the resource being protected is the customer's\n * listener, which does not care which of our admins is iterating on it. The allowance is\n * loose enough for the real workflow (tweak a URL, retest) and tight enough that the\n * operation cannot be used to generate sustained traffic at a third party.\n */\nconst PROBE_RATE_LIMIT_WINDOW_SECONDS = 60;\nconst PROBE_RATE_LIMIT_MAX_PER_WINDOW = 5;\n\n/** Host-only projection for the audit trail — see the audit schema for why the path is withheld. */\nfunction extractHost(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return 'unparseable';\n }\n}\n\n/**\n * Map a transport result onto the reported verdict.\n *\n * Deliberately NOT `classifyResponseStatus`: that function answers a delivery-retry question\n * (\"should we send this again?\"), where 429 and 503 are `retry`. A probe answers a\n * reachability question, where 429 and 503 both mean the endpoint is very much reachable and\n * chose to refuse. Reusing the retry classifier here would report a live, throttling endpoint\n * as though nothing had been learned about it.\n */\nexport function resolveProbeOutcome(responseStatus: number | undefined): WebhookEndpointProbeOutcome {\n if (responseStatus === undefined) return WebhookEndpointProbeOutcome.UNREACHABLE;\n return responseStatus >= 200 && responseStatus < 300\n ? WebhookEndpointProbeOutcome.ACCEPTED\n : WebhookEndpointProbeOutcome.REJECTED;\n}\n\nexport function createWebhookConfigTestEndpointFactories(): ResourceCustomServiceImplementationFactory[] {\n return WEBHOOK_CONFIG_VARIANTS.map(({ resourceType, scopeType, channel }): ResourceCustomServiceImplementationFactory => {\n return (_resourcesRegistryService, container: Container) => {\n return createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: resourceType,\n operationIdentifier: WebhookConfig_Operations.TEST_ENDPOINT,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n requestDtoSchema: WebhookConfig_TestEndpointRequestDto,\n handlers: {\n replaceCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { endpointId } = input as { endpointId: string };\n\n const scopeId = scopeType === AuthScopeType.ORGANIZATION\n ? executionContext.organizationId\n : executionContext.applicationId;\n if (!scopeId) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: `Webhook endpoint test requires a ${scopeType}-scoped execution context.` },\n });\n }\n\n // ── Rate limit ────────────────────────────────────────────\n // Fails CLOSED when the limiter is unavailable. This operation is the one\n // admin surface that makes the platform open a connection to an\n // operator-supplied URL; running it unmetered because Redis is down is\n // exactly the window an abuse path would want. An honest 4xx/5xx beats\n // silently unbounded egress.\n const redis = container.get<RedisService>(SAAS_SERVICE_TYPES.RedisService);\n // Non-production relaxation of the probe ceiling (shared seam — see\n // `rate-limit-environment-relaxation.backend.utils`). Five probes per minute is\n // a production egress guard; iterating on a webhook endpoint locally legitimately\n // exceeds it in seconds. The live-traffic warning in the message below still holds\n // in dev — the relaxation raises the ceiling, it does not make the probe cheap.\n const appConfigService = container.get<AppConfigurationService>(SAAS_SERVICE_TYPES.AppConfigService);\n const effectiveProbeMaxPerWindow = relaxAbuseThrottleMaxForEnvironment(\n PROBE_RATE_LIMIT_MAX_PER_WINDOW,\n appConfigService.applicationEnv,\n );\n const attemptsInWindow = await redis.incrementRateLimit(\n `webhook_endpoint_test:${scopeType}:${scopeId}:${endpointId}`,\n PROBE_RATE_LIMIT_WINDOW_SECONDS,\n );\n if (attemptsInWindow > effectiveProbeMaxPerWindow) {\n throw utils.errorBuilder.buildError(ErrorType.RATE_LIMIT, executionContext, {\n customMessageReference: ErrorCustomMessageReference.RATE_LIMIT,\n context: {\n message: `Endpoint tests are limited to ${effectiveProbeMaxPerWindow} per ${PROBE_RATE_LIMIT_WINDOW_SECONDS}s per endpoint; each one sends live traffic to the destination.`,\n endpointId,\n retryAfterSeconds: PROBE_RATE_LIMIT_WINDOW_SECONDS,\n },\n });\n }\n\n // ── Resolve the endpoint (scope-confined) ─────────────────\n // `readAsSystem` is the sanctioned privileged path and the resource opts into\n // it (`systemAccessPolicy: { read: ALLOWED }`). The caller has already passed\n // the org-admin / app-super-admin gate on this operation; the system read only\n // avoids re-deriving row visibility, and the filter pins the caller's own scope.\n if (!utils.systemAccessService) {\n throw utils.errorBuilder.buildError(ErrorType.CONFIGURATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.CONFIGURATION,\n context: { message: 'System access service is unavailable; cannot resolve the webhook endpoint to test.' },\n });\n }\n const scopeFieldName = scopeType === AuthScopeType.ORGANIZATION ? 'organizationId' : 'applicationId';\n const config = await utils.systemAccessService.readAsSystem<WebhookConfigBase>(\n resourceType,\n { [scopeFieldName]: scopeId },\n { scopeContext: { [scopeFieldName]: scopeId } },\n );\n if (!config) {\n throw utils.errorBuilder.buildError(ErrorType.NOT_FOUND, executionContext, {\n customMessageReference: ErrorCustomMessageReference.NOT_FOUND,\n context: { message: 'No webhook configuration exists for this scope.' },\n });\n }\n\n const endpoint: WebhookEndpoint | undefined = (config.endpoints ?? []).find((e) => e.id === endpointId);\n if (!endpoint) {\n throw utils.errorBuilder.buildError(ErrorType.NOT_FOUND, executionContext, {\n customMessageReference: ErrorCustomMessageReference.NOT_FOUND,\n context: { message: 'No endpoint with this id exists on the webhook configuration.', endpointId },\n });\n }\n if (!endpoint.url) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: 'The stored endpoint has no URL, so no meaningful test can be sent.', endpointId },\n });\n }\n // A DISABLED endpoint is still probed on purpose: \"validate before enabling\" is\n // the primary workflow this operation exists for, and refusing here would force\n // an admin to enable an unverified URL in order to verify it.\n\n // ── Build + sign the synthetic delivery ───────────────────\n const attemptedAt = new Date();\n const signatureJti = randomUUID();\n const body = JSON.stringify({\n synthetic: true,\n message: 'Wildo webhook connectivity test. This is not a real event; do not process it as one.',\n endpointId,\n scope: { type: scopeType, id: scopeId },\n issuedAt: attemptedAt.toISOString(),\n });\n const bodyHash = createHash('sha256').update(body).digest('hex');\n\n const jwtService = container.get<JwtBackendService>(SAAS_SERVICE_TYPES.JwtBackendService);\n let signature: string;\n try {\n signature = await jwtService.sign(\n {\n jti: signatureJti,\n bodyHash,\n bodyHashAlg: M2M_WEBHOOK_BODY_HASH_ALGORITHM,\n eventChannel: channel,\n resourceIdentifier: String(resourceType),\n operationIdentifier: String(WebhookConfig_Operations.TEST_ENDPOINT),\n // Present ONLY on probes. Lets a consumer that wants to hard-refuse\n // synthetic traffic do so on the signed envelope rather than on body text.\n synthetic: true,\n },\n JwtPrivateKeys.APPLICATION_WEBHOOK,\n );\n } catch (error) {\n // Signing failure is ours, not the endpoint's. Reporting it as UNREACHABLE\n // would send an admin to debug a customer endpoint over a missing local key.\n const failureReason = `JWT signing failed: ${describeCaughtError(error)}`;\n utils.logger.error('Webhook endpoint test could not be signed; nothing was sent', {\n scopeType, scopeId, endpointId, error,\n });\n const notSent = {\n endpointId,\n url: endpoint.url,\n outcome: WebhookEndpointProbeOutcome.NOT_SENT,\n failureReason,\n durationMs: 0,\n signatureJti,\n attemptedAt,\n };\n await recordProbeAudit(container, executionContext, {\n scopeType, scopeId, endpointId, url: endpoint.url,\n outcome: WebhookEndpointProbeOutcome.NOT_SENT,\n durationMs: 0,\n signatureJti,\n });\n return notSent;\n }\n\n // ── Send ──────────────────────────────────────────────────\n const result = await sendSignedWebhookRequest({ url: endpoint.url, body, signature });\n const outcome = resolveProbeOutcome(result.responseStatus);\n\n utils.logger.info('Webhook endpoint test dispatched', {\n scopeType, scopeId, endpointId,\n destinationHost: extractHost(endpoint.url),\n outcome,\n responseStatus: result.responseStatus,\n durationMs: result.durationMs,\n signatureJti,\n });\n\n await recordProbeAudit(container, executionContext, {\n scopeType, scopeId, endpointId, url: endpoint.url,\n outcome,\n responseStatus: result.responseStatus,\n durationMs: result.durationMs,\n signatureJti,\n });\n\n // Matches `WebhookConfig_TestEndpointResponseDto`.\n return {\n endpointId,\n url: endpoint.url,\n outcome,\n responseStatus: result.responseStatus,\n responseBodyTruncated: result.responseBodyTruncated,\n failureReason: result.networkError,\n durationMs: result.durationMs,\n signatureJti,\n attemptedAt,\n };\n },\n },\n });\n };\n });\n}\n\n/**\n * Record the probe on the audit trail.\n *\n * Emitted for EVERY attempt, not only failures: the security signal is the pattern of\n * outbound probing (who, which hosts, how often), which only reads correctly if successes\n * are present too.\n *\n * Uses the generic `logEvent` rather than a dedicated `log*` method so the audit service's\n * public surface does not grow — partial `AuditLogsBackendService` mocks across the test\n * suite would otherwise start failing on a method they do not stub.\n *\n * Best-effort by construction: `logEvent` swallows its own failures, and an audit-store\n * outage must not convert a completed probe into an error the admin cannot act on.\n *\n * assurance-control: WILDO.INTEGRATION.OUTBOUND_ACTIVITY_AUDIT — attributable outbound connection\n * initiated from an administrative surface.\n */\nasync function recordProbeAudit(\n container: Container,\n executionContext: ExecutionContext<any>,\n data: {\n scopeType: AuthScopeType;\n scopeId: string;\n endpointId: string;\n url: string;\n outcome: WebhookEndpointProbeOutcome;\n responseStatus?: number;\n durationMs: number;\n signatureJti: string;\n },\n): Promise<void> {\n const auditLogs = container.get<AuditLogsBackendService>(SAAS_SERVICE_TYPES.AuditLogsService);\n const isOrgScope = data.scopeType === AuthScopeType.ORGANIZATION;\n const actorUserId = executionContext.initiatorIds?.userId;\n\n const eventData: AuditableEvent_Webhook_EndpointTestDispatchedEventData = {\n eventType: CoreAuditableEventType.WEBHOOK_ENDPOINT_TEST_DISPATCHED,\n organizationId: isOrgScope ? data.scopeId : undefined,\n applicationId: isOrgScope ? undefined : data.scopeId,\n // The operation is role-gated to a human admin, so an absent actor id means the\n // execution context was not shaped as expected. Record the gap rather than papering\n // over it — an unattributable egress probe is itself the thing worth noticing.\n dispatchedBy: actorUserId ?? 'unattributed',\n endpointId: data.endpointId,\n destinationHost: extractHost(data.url),\n outcome: data.outcome,\n responseStatus: data.responseStatus,\n durationMs: data.durationMs,\n signatureJti: data.signatureJti,\n };\n\n await auditLogs.logEvent(\n {\n userId: actorUserId,\n // Scope FK as event DATA. Per-org SIEM routing is resolved by the audit service from\n // the authenticated request context passed below, never from this field.\n organizationId: isOrgScope ? data.scopeId : undefined,\n applicationId: isOrgScope ? undefined : data.scopeId,\n // Matches the operation's declared `riskLevel` — outbound traffic to an operator-supplied\n // URL, gated behind an admin role.\n riskLevel: ResourceOperationRiskLevel.MEDIUM,\n eventType: CoreAuditableEventType.WEBHOOK_ENDPOINT_TEST_DISPATCHED,\n eventData: eventData as Record<string, any>,\n },\n executionContext,\n );\n}\n"]}
1
+ {"version":3,"file":"webhook-config-test-endpoint.custom-impl.backend.service.js","sourceRoot":"","sources":["../../../../../../../src/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Webhook Config TEST_ENDPOINT — REPLACE_CORE_OPERATIONS factory.\n *\n * Makes `webhookConfig.testEndpoint` (org + app variants) do the thing it is named after:\n * fire one signed synthetic delivery at a single stored endpoint and report what came back.\n *\n * Before this implementation the operation was declared `resourceOperationLike: READ` with\n * no handler, so the generic core read answered 200 with the config row. An admin pressing\n * \"test\" on an endpoint whose URL had rotted was told it worked. A connectivity probe that\n * cannot fail is worse than no probe — it converts an unknown into a false assurance — so\n * every failure mode is now a distinct, reported outcome.\n *\n * Design commitments:\n *\n * - **Same transport as real deliveries.** The POST goes through\n * {@link sendSignedWebhookRequest}, shared verbatim with the delivery worker. A probe\n * that reached the endpoint by a different route would attest to that route, not to the\n * delivery path the admin actually cares about.\n * - **Signed like a real delivery.** Same key (`JwtPrivateKeys.APPLICATION_WEBHOOK`), same\n * claim shape, same `X-Webhook-Signature` header, so the consumer's verification code is\n * genuinely exercised rather than bypassed.\n * - **Unmistakably synthetic.** The claims carry `synthetic: true` and the body is a\n * self-describing test envelope. We are POSTing to a customer's production listener; a\n * probe indistinguishable from a real event would invite consumers to act on a fake one.\n * Unknown claims are ignored by existing consumers, so this adds no breaking change.\n * - **No delivery-log row.** Per the operation contract, test traffic stays out of the user\n * event log. The audit trail below is where a probe is recorded.\n * - **A dead endpoint is a 200.** Transport failure at the customer's side is a successful\n * probe carrying `outcome: UNREACHABLE`. HTTP errors are reserved for faults in the\n * request itself — unknown `endpointId`, absent config, rate limit exceeded.\n *\n * Scope resolution mirrors the sibling delivery-log impls: the ORG variant reads\n * `executionContext.organizationId`, the APP variant `applicationId`. The endpoint is then\n * selected by `endpointId` *within that scope's config only*, so a caller cannot aim the\n * probe at another tenant's endpoint — or at an arbitrary URL of their own choosing.\n *\n * @see ../m2m-webhook-signed-request.backend.utils.ts — the shared transport.\n * @see m2m-webhook-delivery-log.custom-impl.backend.service.ts — sibling REPLACE impls.\n */\n\nimport { createHash, randomUUID } from 'node:crypto';\nimport {\n AuthScopeType,\n CoreAuditableEventType,\n CoreM2MNotificationChannel,\n CoreResourceType,\n ErrorCustomMessageReference,\n ErrorType,\n ResourceOperationRiskLevel,\n ResourceOperationVariantType,\n WebhookConfig_Operations,\n WebhookConfig_TestEndpointRequestDto,\n WebhookEndpointProbeOutcome,\n webhookEndpointDestinationHost,\n webhookEndpointTransportIsPlaintext,\n type AuditableEvent_Webhook_EndpointTestDispatchedEventData,\n type WebhookConfigBase,\n type WebhookEndpoint,\n M2M_WEBHOOK_DELIVERY_CONTRACT,\n} from '@wildo-ai/saas-models';\nimport type { Container } from 'inversify';\nimport {\n createResourceCustomServiceImplementation,\n type ResourceCustomServiceImplementationFactory,\n} from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation.factory.backend';\nimport type { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';\nimport type { RedisService } from '~wildo-backend-lib/databases/services/redis.service';\nimport { describeCaughtError } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport { relaxAbuseThrottleMaxForEnvironment } from '~wildo-backend-lib/errors/utils/rate-limit-environment-relaxation.backend.utils';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport { JwtPrivateKeys } from '~wildo-backend-lib/security/authentications/models/jwt.backend.schemas';\nimport type { JwtBackendService } from '~wildo-backend-lib/security/jwt/services/jwt.backend.service';\nimport { M2M_WEBHOOK_BODY_HASH_ALGORITHM, sendSignedWebhookRequest } from '../m2m-webhook-signed-request.backend.utils';\n\n/**\n * Variant → (scope type, notification channel) pairing. The channel rides the signed claims\n * so the probe presents itself on the same channel a real delivery from this scope would.\n */\nconst WEBHOOK_CONFIG_VARIANTS = [\n {\n resourceType: CoreResourceType.ORGANIZATION_WEBHOOK_CONFIG,\n scopeType: AuthScopeType.ORGANIZATION,\n channel: CoreM2MNotificationChannel.WEBHOOK_ORGANIZATION,\n },\n {\n resourceType: CoreResourceType.APPLICATION_WEBHOOK_CONFIG,\n scopeType: AuthScopeType.APPLICATION,\n channel: CoreM2MNotificationChannel.WEBHOOK_APPLICATION,\n },\n] as const;\n\n/**\n * Probe budget: at most this many attempts per endpoint per window.\n *\n * Scoped per ENDPOINT rather than per admin: the resource being protected is the customer's\n * listener, which does not care which of our admins is iterating on it. The allowance is\n * loose enough for the real workflow (tweak a URL, retest) and tight enough that the\n * operation cannot be used to generate sustained traffic at a third party.\n */\nconst PROBE_RATE_LIMIT_WINDOW_SECONDS = 60;\nconst PROBE_RATE_LIMIT_MAX_PER_WINDOW = 5;\n\n\n/**\n * Map a transport result onto the reported verdict.\n *\n * Deliberately NOT `classifyResponseStatus`: that function answers a delivery-retry question\n * (\"should we send this again?\"), where 429 and 503 are `retry`. A probe answers a\n * reachability question, where 429 and 503 both mean the endpoint is very much reachable and\n * chose to refuse. Reusing the retry classifier here would report a live, throttling endpoint\n * as though nothing had been learned about it.\n */\nexport function resolveProbeOutcome(responseStatus: number | undefined): WebhookEndpointProbeOutcome {\n if (responseStatus === undefined) return WebhookEndpointProbeOutcome.UNREACHABLE;\n return responseStatus >= 200 && responseStatus < 300\n ? WebhookEndpointProbeOutcome.ACCEPTED\n : WebhookEndpointProbeOutcome.REJECTED;\n}\n\nexport function createWebhookConfigTestEndpointFactories(): ResourceCustomServiceImplementationFactory[] {\n return WEBHOOK_CONFIG_VARIANTS.map(({ resourceType, scopeType, channel }): ResourceCustomServiceImplementationFactory => {\n return (_resourcesRegistryService, container: Container) => {\n return createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: resourceType,\n operationIdentifier: WebhookConfig_Operations.TEST_ENDPOINT,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n requestDtoSchema: WebhookConfig_TestEndpointRequestDto,\n handlers: {\n replaceCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { endpointId } = input as { endpointId: string };\n\n const scopeId = scopeType === AuthScopeType.ORGANIZATION\n ? executionContext.organizationId\n : executionContext.applicationId;\n if (!scopeId) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: `Webhook endpoint test requires a ${scopeType}-scoped execution context.` },\n });\n }\n\n // ── Rate limit ────────────────────────────────────────────\n // Fails CLOSED when the limiter is unavailable. This operation is the one\n // admin surface that makes the platform open a connection to an\n // operator-supplied URL; running it unmetered because Redis is down is\n // exactly the window an abuse path would want. An honest 4xx/5xx beats\n // silently unbounded egress.\n const redis = container.get<RedisService>(SAAS_SERVICE_TYPES.RedisService);\n // Non-production relaxation of the probe ceiling (shared seam — see\n // `rate-limit-environment-relaxation.backend.utils`). Five probes per minute is\n // a production egress guard; iterating on a webhook endpoint locally legitimately\n // exceeds it in seconds. The live-traffic warning in the message below still holds\n // in dev — the relaxation raises the ceiling, it does not make the probe cheap.\n const appConfigService = container.get<AppConfigurationService>(SAAS_SERVICE_TYPES.AppConfigService);\n const effectiveProbeMaxPerWindow = relaxAbuseThrottleMaxForEnvironment(\n PROBE_RATE_LIMIT_MAX_PER_WINDOW,\n appConfigService.applicationEnv,\n );\n const attemptsInWindow = await redis.incrementRateLimit(\n `webhook_endpoint_test:${scopeType}:${scopeId}:${endpointId}`,\n PROBE_RATE_LIMIT_WINDOW_SECONDS,\n );\n if (attemptsInWindow > effectiveProbeMaxPerWindow) {\n throw utils.errorBuilder.buildError(ErrorType.RATE_LIMIT, executionContext, {\n customMessageReference: ErrorCustomMessageReference.RATE_LIMIT,\n context: {\n message: `Endpoint tests are limited to ${effectiveProbeMaxPerWindow} per ${PROBE_RATE_LIMIT_WINDOW_SECONDS}s per endpoint; each one sends live traffic to the destination.`,\n endpointId,\n retryAfterSeconds: PROBE_RATE_LIMIT_WINDOW_SECONDS,\n },\n });\n }\n\n // ── Resolve the endpoint (scope-confined) ─────────────────\n // `readAsSystem` is the sanctioned privileged path and the resource opts into\n // it (`systemAccessPolicy: { read: ALLOWED }`). The caller has already passed\n // the org-admin / app-super-admin gate on this operation; the system read only\n // avoids re-deriving row visibility, and the filter pins the caller's own scope.\n if (!utils.systemAccessService) {\n throw utils.errorBuilder.buildError(ErrorType.CONFIGURATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.CONFIGURATION,\n context: { message: 'System access service is unavailable; cannot resolve the webhook endpoint to test.' },\n });\n }\n const scopeFieldName = scopeType === AuthScopeType.ORGANIZATION ? 'organizationId' : 'applicationId';\n const config = await utils.systemAccessService.readAsSystem<WebhookConfigBase>(\n resourceType,\n { [scopeFieldName]: scopeId },\n { scopeContext: { [scopeFieldName]: scopeId } },\n );\n if (!config) {\n throw utils.errorBuilder.buildError(ErrorType.NOT_FOUND, executionContext, {\n customMessageReference: ErrorCustomMessageReference.NOT_FOUND,\n context: { message: 'No webhook configuration exists for this scope.' },\n });\n }\n\n const endpoint: WebhookEndpoint | undefined = (config.endpoints ?? []).find((e) => e.id === endpointId);\n if (!endpoint) {\n throw utils.errorBuilder.buildError(ErrorType.NOT_FOUND, executionContext, {\n customMessageReference: ErrorCustomMessageReference.NOT_FOUND,\n context: { message: 'No endpoint with this id exists on the webhook configuration.', endpointId },\n });\n }\n if (!endpoint.url) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.VALIDATION,\n context: { message: 'The stored endpoint has no URL, so no meaningful test can be sent.', endpointId },\n });\n }\n // A DISABLED endpoint is still probed on purpose: \"validate before enabling\" is\n // the primary workflow this operation exists for, and refusing here would force\n // an admin to enable an unverified URL in order to verify it.\n\n // ── Build + sign the synthetic delivery ───────────────────\n const attemptedAt = new Date();\n const signatureJti = randomUUID();\n const body = JSON.stringify({\n synthetic: true,\n message: 'Wildo webhook connectivity test. This is not a real event; do not process it as one.',\n endpointId,\n scope: { type: scopeType, id: scopeId },\n issuedAt: attemptedAt.toISOString(),\n });\n const bodyHash = createHash('sha256').update(body).digest('hex');\n\n const jwtService = container.get<JwtBackendService>(SAAS_SERVICE_TYPES.JwtBackendService);\n let signature: string;\n try {\n signature = await jwtService.sign(\n {\n // Claim names come from the published receiver contract, exactly as the\n // delivery worker signs them; a probe must be verifiable by the same receiver code.\n [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.deliveryId]: signatureJti,\n [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.bodyHash]: bodyHash,\n [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.bodyHashAlgorithm]: M2M_WEBHOOK_BODY_HASH_ALGORITHM,\n [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.eventChannel]: channel,\n [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.resourceIdentifier]: String(resourceType),\n [M2M_WEBHOOK_DELIVERY_CONTRACT.signatureClaims.operationIdentifier]: String(WebhookConfig_Operations.TEST_ENDPOINT),\n // Present ONLY on probes. Lets a consumer that wants to hard-refuse\n // synthetic traffic do so on the signed envelope rather than on body text.\n synthetic: true,\n },\n JwtPrivateKeys.APPLICATION_WEBHOOK,\n );\n } catch (error) {\n // Signing failure is ours, not the endpoint's. Reporting it as UNREACHABLE\n // would send an admin to debug a customer endpoint over a missing local key.\n const failureReason = `JWT signing failed: ${describeCaughtError(error)}`;\n utils.logger.error('Webhook endpoint test could not be signed; nothing was sent', {\n scopeType, scopeId, endpointId, error,\n });\n const notSent = {\n endpointId,\n url: endpoint.url,\n // Reported even though nothing left the platform: the scheme is a property of the\n // STORED destination, not of this attempt, so an admin fixing a signing fault is\n // still told what the endpoint will cost them once it works (#492).\n transportIsPlaintext: webhookEndpointTransportIsPlaintext(endpoint.url),\n outcome: WebhookEndpointProbeOutcome.NOT_SENT,\n failureReason,\n durationMs: 0,\n signatureJti,\n attemptedAt,\n };\n await recordProbeAudit(container, executionContext, {\n scopeType, scopeId, endpointId, url: endpoint.url,\n outcome: WebhookEndpointProbeOutcome.NOT_SENT,\n durationMs: 0,\n signatureJti,\n });\n return notSent;\n }\n\n // ── Send ──────────────────────────────────────────────────\n const result = await sendSignedWebhookRequest({ url: endpoint.url, body, signature });\n const outcome = resolveProbeOutcome(result.responseStatus);\n const transportIsPlaintext = webhookEndpointTransportIsPlaintext(endpoint.url);\n\n utils.logger.info('Webhook endpoint test dispatched', {\n scopeType, scopeId, endpointId,\n destinationHost: webhookEndpointDestinationHost(endpoint.url),\n // A probe is the moment an operator is looking at ONE endpoint, so it is also the\n // cheapest moment to notice the signature JWT is going out in the clear (#492).\n transportIsPlaintext,\n outcome,\n responseStatus: result.responseStatus,\n durationMs: result.durationMs,\n signatureJti,\n });\n\n await recordProbeAudit(container, executionContext, {\n scopeType, scopeId, endpointId, url: endpoint.url,\n outcome,\n responseStatus: result.responseStatus,\n durationMs: result.durationMs,\n signatureJti,\n });\n\n // Matches `WebhookConfig_TestEndpointResponseDto`.\n return {\n endpointId,\n url: endpoint.url,\n transportIsPlaintext,\n outcome,\n responseStatus: result.responseStatus,\n responseBodyTruncated: result.responseBodyTruncated,\n failureReason: result.networkError,\n durationMs: result.durationMs,\n signatureJti,\n attemptedAt,\n };\n },\n },\n });\n };\n });\n}\n\n/**\n * Record the probe on the audit trail.\n *\n * Emitted for EVERY attempt, not only failures: the security signal is the pattern of\n * outbound probing (who, which hosts, how often), which only reads correctly if successes\n * are present too.\n *\n * Uses the generic `logEvent` rather than a dedicated `log*` method so the audit service's\n * public surface does not grow — partial `AuditLogsBackendService` mocks across the test\n * suite would otherwise start failing on a method they do not stub.\n *\n * Best-effort by construction: `logEvent` swallows its own failures, and an audit-store\n * outage must not convert a completed probe into an error the admin cannot act on.\n *\n * assurance-control: WILDO.INTEGRATION.OUTBOUND_ACTIVITY_AUDIT — attributable outbound connection\n * initiated from an administrative surface.\n */\nasync function recordProbeAudit(\n container: Container,\n executionContext: ExecutionContext<any>,\n data: {\n scopeType: AuthScopeType;\n scopeId: string;\n endpointId: string;\n url: string;\n outcome: WebhookEndpointProbeOutcome;\n responseStatus?: number;\n durationMs: number;\n signatureJti: string;\n },\n): Promise<void> {\n const auditLogs = container.get<AuditLogsBackendService>(SAAS_SERVICE_TYPES.AuditLogsService);\n const isOrgScope = data.scopeType === AuthScopeType.ORGANIZATION;\n const actorUserId = executionContext.initiatorIds?.userId;\n\n const eventData: AuditableEvent_Webhook_EndpointTestDispatchedEventData = {\n eventType: CoreAuditableEventType.WEBHOOK_ENDPOINT_TEST_DISPATCHED,\n organizationId: isOrgScope ? data.scopeId : undefined,\n applicationId: isOrgScope ? undefined : data.scopeId,\n // The operation is role-gated to a human admin, so an absent actor id means the\n // execution context was not shaped as expected. Record the gap rather than papering\n // over it — an unattributable egress probe is itself the thing worth noticing.\n dispatchedBy: actorUserId ?? 'unattributed',\n endpointId: data.endpointId,\n destinationHost: webhookEndpointDestinationHost(data.url),\n outcome: data.outcome,\n responseStatus: data.responseStatus,\n durationMs: data.durationMs,\n signatureJti: data.signatureJti,\n };\n\n await auditLogs.logEvent(\n {\n userId: actorUserId,\n // Scope FK as event DATA. Per-org SIEM routing is resolved by the audit service from\n // the authenticated request context passed below, never from this field.\n organizationId: isOrgScope ? data.scopeId : undefined,\n applicationId: isOrgScope ? undefined : data.scopeId,\n // Matches the operation's declared `riskLevel` — outbound traffic to an operator-supplied\n // URL, gated behind an admin role.\n riskLevel: ResourceOperationRiskLevel.MEDIUM,\n eventType: CoreAuditableEventType.WEBHOOK_ENDPOINT_TEST_DISPATCHED,\n eventData: eventData as Record<string, any>,\n },\n executionContext,\n );\n}\n"]}
@@ -45,6 +45,22 @@ export declare class WebhookHandlerBackendService {
45
45
  * Called at startup by capability modules (e.g., billing module).
46
46
  */
47
47
  registerAdapter(providerRef: string, endpointKey: string, adapter: WebhookCapabilityAdapter): void;
48
+ /**
49
+ * Whether a capability adapter is registered for `providerRef:endpointKey`.
50
+ *
51
+ * Read-only mount-time predicate for {@link WebhookAutoControllerBackendService}:
52
+ * without an adapter, `processWebhook` throws `INTERNAL` at the very top of the
53
+ * pipeline (`No webhook adapter registered for ...`), which the controller answers
54
+ * as a 500 — i.e. an instruction to the VENDOR to retry an event that can never be
55
+ * processed, because nothing about a retry supplies the missing registration. The
56
+ * auto-controller therefore asks this BEFORE mounting a route, and withholds the
57
+ * route instead of mounting one that can only fail.
58
+ *
59
+ * Deliberately not exposing the adapter itself: the caller needs an admission
60
+ * decision, not the verify/parse surface, and handing out the adapter would let a
61
+ * consumer route around `processWebhook`'s signature/idempotency pipeline.
62
+ */
63
+ hasAdapter(providerRef: string, endpointKey: string): boolean;
48
64
  /**
49
65
  * Register a custom scope resolver to override declarative scope resolution.
50
66
  * This is an escape hatch for complex cases where Hook_EndpointScopeBinding is insufficient.
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-handler.backend.service.d.ts","sourceRoot":"","sources":["../../../../../../src/notifications/webhooks/services/webhook-handler.backend.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webhook-handler.backend.service.d.ts","sourceRoot":"","sources":["../../../../../../src/notifications/webhooks/services/webhook-handler.backend.service.ts"],"names":[],"mappings":"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"}
@@ -78,6 +78,24 @@ let WebhookHandlerBackendService = class WebhookHandlerBackendService {
78
78
  this.adapters.set(key, adapter);
79
79
  this.logDebug(`Registered webhook adapter for ${key}`);
80
80
  }
81
+ /**
82
+ * Whether a capability adapter is registered for `providerRef:endpointKey`.
83
+ *
84
+ * Read-only mount-time predicate for {@link WebhookAutoControllerBackendService}:
85
+ * without an adapter, `processWebhook` throws `INTERNAL` at the very top of the
86
+ * pipeline (`No webhook adapter registered for ...`), which the controller answers
87
+ * as a 500 — i.e. an instruction to the VENDOR to retry an event that can never be
88
+ * processed, because nothing about a retry supplies the missing registration. The
89
+ * auto-controller therefore asks this BEFORE mounting a route, and withholds the
90
+ * route instead of mounting one that can only fail.
91
+ *
92
+ * Deliberately not exposing the adapter itself: the caller needs an admission
93
+ * decision, not the verify/parse surface, and handing out the adapter would let a
94
+ * consumer route around `processWebhook`'s signature/idempotency pipeline.
95
+ */
96
+ hasAdapter(providerRef, endpointKey) {
97
+ return this.adapters.has(`${providerRef}:${endpointKey}`);
98
+ }
81
99
  /**
82
100
  * Register a custom scope resolver to override declarative scope resolution.
83
101
  * This is an escape hatch for complex cases where Hook_EndpointScopeBinding is insufficient.
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-handler.backend.service.js","sourceRoot":"","sources":["../../../../../../src/notifications/webhooks/services/webhook-handler.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;;;;;;;;;;;;;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EACL,sCAAsC,GAQvC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAEtG,OAAO,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AAWpF,wDAAwD;AACxD,YAAY;AACZ,wDAAwD;AAExD,wCAAwC;AACxC,MAAM,+BAA+B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACrD,MAAM,sBAAsB,GAAG,UAAU,CAAC;AAE1C,wDAAwD;AACxD,UAAU;AACV,wDAAwD;AAGjD,IAAM,4BAA4B,GAAlC,MAAM,4BAA4B;IAWe;IACM;IACO;IACkB;IACH;IACF;IAChB;IACQ;IAhBvD,QAAQ,CAA+D;IAExF,6DAA6D;IACrD,QAAQ,GAAG,IAAI,GAAG,EAAoC,CAAC;IAE/D,gFAAgF;IACxE,eAAe,GAAG,IAAI,GAAG,EAAsC,CAAC;IAExE,YACsD,MAAqB,EACf,YAA0B,EACnB,YAAwC,EACtB,uBAA8D,EACjE,oBAA+D,EACjE,yBAAkE,EAClF,gBAAyC,EACjC,iBAAkD;QAPpE,WAAM,GAAN,MAAM,CAAe;QACf,iBAAY,GAAZ,YAAY,CAAc;QACnB,iBAAY,GAAZ,YAAY,CAA4B;QACtB,4BAAuB,GAAvB,uBAAuB,CAAuC;QACjE,yBAAoB,GAApB,oBAAoB,CAA2C;QACjE,8BAAyB,GAAzB,yBAAyB,CAAyC;QAClF,qBAAgB,GAAhB,gBAAgB,CAAyB;QACjC,sBAAiB,GAAjB,iBAAiB,CAAiC;QAExH,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,+DAA+D;IAC/D,eAAe;IACf,+DAA+D;IAE/D;;;OAGG;IACH,eAAe,CAAC,WAAmB,EAAE,WAAmB,EAAE,OAAiC;QACzF,MAAM,GAAG,GAAG,GAAG,WAAW,IAAI,WAAW,EAAE,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,IAAI,CAAC,QAAQ,CAAC,kCAAkC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;IAED;;;OAGG;IACH,2BAA2B,CAAC,QAAoC;QAC9D,MAAM,GAAG,GAAG,GAAG,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC9D,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,wCAAwC,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,+DAA+D;IAC/D,gBAAgB;IAChB,+DAA+D;IAE/D;;;;;;OAMG;IACH,KAAK,CAAC,cAAc,CAAC,MAMpB;QACC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QACxE,MAAM,UAAU,GAAG,GAAG,WAAW,IAAI,WAAW,EAAE,CAAC;QACnD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAE9C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAChC,SAAS,CAAC,QAAQ,EAClB,SAAS,EACT,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,qCAAqC,UAAU,EAAE,EAAE,EAAE,CAC5E,CAAC;QACJ,CAAC;QAED,mDAAmD;QACnD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAEzE,6CAA6C;QAC7C,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC3E,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;YAChF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAChC,SAAS,CAAC,aAAa,EACvB,SAAS,EACT,EAAE,sBAAsB,EAAE,2BAA2B,CAAC,yBAAyB,EAAE,CAClF,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAAa,EAAE,SAAS,KAAK,SAAS,CAAC,aAAa;gBAAE,MAAM,KAAK,CAAC;YACvE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,EAAE,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;YACzH,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAChC,SAAS,CAAC,aAAa,EACvB,SAAS,EACT,EAAE,sBAAsB,EAAE,2BAA2B,CAAC,yBAAyB,EAAE,CAClF,CAAC;QACJ,CAAC;QAED,mEAAmE;QACnE,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,mDAAmD;YACnD,IAAI,CAAC,QAAQ,CAAC,mDAAmD,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;YACjG,OAAO,IAAI,CAAC;QACd,CAAC;QACD,2BAA2B;QAC3B,WAAW,CAAC,WAAW,GAAG,WAAW,CAAC;QACtC,IACE,QAAQ,CAAC,UAAU,EAAE,MAAM;eACxB,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,iBAAiB,CAAC,EAC/D,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,6DAA6D,EAAE;gBAC3E,WAAW;gBACX,WAAW;gBACX,SAAS,EAAE,WAAW,CAAC,iBAAiB;aACzC,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,yEAAyE;QACzE,yEAAyE;QACzE,yEAAyE;QACzE,IAAI,cAAkC,CAAC;QACvC,IAAI,kBAAkB,GAAG,KAAK,CAAC;QAC/B,IAAI,CAAC;YACH,cAAc,GAAG,GAAG,sBAAsB,GAAG,WAAW,IAAI,WAAW,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACjG,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,cAAc,CAAC,CAAC;YACvE,IAAI,WAAW,KAAK,WAAW,EAAE,CAAC;gBAChC,IAAI,CAAC,QAAQ,CAAC,2CAA2C,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC7F,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,WAAW,KAAK,aAAa,EAAE,CAAC;gBAClC,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAChC,SAAS,CAAC,QAAQ,EAClB,SAAS,EACT,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,6CAA6C,WAAW,CAAC,OAAO,EAAE,EAAE,EAAE,CAC7F,CAAC;YACJ,CAAC;YACD,kBAAkB,GAAG,IAAI,CAAC;QAC5B,CAAC;QAAC,OAAO,UAAU,EAAE,CAAC;YACpB,IAAK,UAAkB,EAAE,SAAS,KAAK,SAAS,CAAC,QAAQ;gBAAE,MAAM,UAAU,CAAC;YAC5E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kEAAkE,EAAE;gBACpF,KAAK,EAAG,UAAoB,CAAC,OAAO;aACrC,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAChC,SAAS,CAAC,QAAQ,EAClB,SAAS,EACT,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,iDAAiD,EAAE,EAAE,CAC5E,CAAC;QACJ,CAAC;QAED,IAAI,gBAAuC,CAAC;QAC5C,IAAI,aAAyC,CAAC;QAC9C,IAAI,CAAC;YACH,2CAA2C;YAC3C,aAAa,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;YAEzF,8CAA8C;YAC9C,gBAAgB,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,wBAAwB,CAC5E,aAAa,EACb,WAAW,CACZ,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,kBAAkB,EAAE,CAAC;gBACvB,MAAM,IAAI,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAC;YACjD,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE;YAC1C,WAAW;YACX,WAAW;YACX,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,SAAS,EAAE,WAAW,CAAC,SAAS;YAChC,aAAa,EAAE;gBACb,cAAc,EAAE,aAAa,CAAC,cAAc;gBAC5C,MAAM,EAAE,aAAa,CAAC,MAAM;aAC7B;SACF,CAAC,CAAC;QAEH,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;IAC3D,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,cAAsB;QAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CACzC;;;;;;;OAOC,EACD,CAAC,QAAQ,CAAC,EACV,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAChC,CAAC;QAEF,IAAI,MAAM,KAAK,aAAa,IAAI,MAAM,KAAK,WAAW;YAAE,OAAO,WAAW,CAAC;QAC3E,IAAI,MAAM,KAAK,eAAe,IAAI,MAAM,KAAK,aAAa;YAAE,OAAO,aAAa,CAAC;QACjF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,cAAkC;QAC3D,IAAI,CAAC,cAAc;YAAE,OAAO;QAC5B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAC1B,oEAAoE,EACpE,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,EAC5C,CAAC,WAAW,EAAE,MAAM,CAAC,+BAA+B,CAAC,CAAC,CACvD,CAAC;QACJ,CAAC;QAAC,OAAO,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sDAAsD,EAAE;gBACxE,KAAK,EAAG,UAAoB,CAAC,OAAO;aACrC,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAChC,SAAS,CAAC,QAAQ,EAClB,SAAS,EACT,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,sDAAsD,EAAE,EAAE,CACjF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,cAAkC;QAC1D,IAAI,CAAC,cAAc;YAAE,OAAO;QAC5B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mDAAmD,EAAE;gBACrE,KAAK,EAAG,UAAoB,CAAC,OAAO;aACrC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,+BAA+B;IAC/B,+DAA+D;IAE/D;;;;;;OAMG;IACK,KAAK,CAAC,YAAY,CACxB,WAAmB,EACnB,WAAmB,EACnB,QAAuB,EACvB,WAAqC;QAErC,6CAA6C;QAC7C,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,WAAW,IAAI,WAAW,EAAE,CAAC,CAAC;QACjF,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,cAAc,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC;QAC1D,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC;QAEtC,uCAAuC;QACvC,IAAI,cAAc,IAAI,OAAO,IAAI,OAAO,CAAC,YAAY,KAAK,aAAa,EAAE,CAAC;YACxE,OAAO,EAAE,aAAa,EAAE,CAAC;QAC3B,CAAC;QAED,wEAAwE;QACxE,IAAI,uBAAuB,IAAI,OAAO,IAAI,OAAO,CAAC,qBAAqB,EAAE,QAAQ,CAAC,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACjH,IAAI,CAAC,QAAQ,CAAC,mDAAmD,EAAE;gBACjE,SAAS,EAAE,WAAW,CAAC,iBAAiB;aACzC,CAAC,CAAC;YACH,OAAO,EAAE,aAAa,EAAE,CAAC;QAC3B,CAAC;QAED,2BAA2B;QAC3B,mFAAmF;QACnF,IAAI,MAAM,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACxD,OAAO,IAAI,CAAC,uBAAuB,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;QAC3E,CAAC;QAED,4BAA4B;QAC5B,mFAAmF;QACnF,MAAM,aAAa,GAAG,OAA6E,CAAC;QAEpG,0DAA0D;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,UAAU,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;QAClG,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAChC,SAAS,CAAC,QAAQ,EAClB,SAAS,EACT;gBACE,OAAO,EAAE;oBACP,OAAO,EAAE,sDAAsD,aAAa,CAAC,kBAAkB,cAAc,WAAW,CAAC,OAAO,EAAE;iBACnI;aACF,CACF,CAAC;QACJ,CAAC;QAED,+CAA+C;QAC/C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,gCAAgC,EAAE,CAAC;QAC1F,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,CAAC,aAAa,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC;QAC7F,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gDAAgD,EAAE;gBACjE,kBAAkB,EAAE,aAAa,CAAC,kBAAkB;gBACpD,OAAO,EAAE,WAAW,CAAC,OAAO;aAC7B,CAAC,CAAC;YACH,OAAO,EAAE,aAAa,EAAE,CAAC;QAC3B,CAAC;QAED,IAAI,QAAa,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,QAAQ,CACvC,EAAE,kBAAkB,EAAE,aAAa,CAAC,kBAAkB,EAAE,mBAAmB,EAAE,qBAAqB,CAAC,IAAI,EAAE,EACzG,WAAW,EACX,EAAE,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CACzC,CAAC;YACF,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAC3D,CAAC;QAAC,OAAO,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yCAAyC,EAAE;gBAC1D,kBAAkB,EAAE,aAAa,CAAC,kBAAkB;gBACpD,WAAW,EAAE,aAAa,CAAC,WAAW;gBACtC,OAAO;gBACP,OAAO,EAAE,WAAW,CAAC,OAAO;gBAC5B,KAAK,EAAG,WAAqB,CAAC,OAAO;aACtC,CAAC,CAAC;YACH,OAAO,EAAE,aAAa,EAAE,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8CAA8C,EAAE;gBAC/D,kBAAkB,EAAE,aAAa,CAAC,kBAAkB;gBACpD,WAAW,EAAE,aAAa,CAAC,WAAW;gBACtC,OAAO;gBACP,OAAO,EAAE,WAAW,CAAC,OAAO;aAC7B,CAAC,CAAC;YACH,OAAO,EAAE,aAAa,EAAE,CAAC;QAC3B,CAAC;QAED,0BAA0B;QAC1B,MAAM,kBAAkB,GAAG,aAAa,CAAC,kBAAkB,IAAI,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAClH,MAAM,gBAAgB,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAAC;QAEtD,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,6DAA6D,EAAE;gBAC9E,kBAAkB;gBAClB,kBAAkB,EAAE,aAAa,CAAC,kBAAkB;gBACpD,OAAO,EAAE,WAAW,CAAC,OAAO;aAC7B,CAAC,CAAC;YACH,OAAO,EAAE,aAAa,EAAE,CAAC;QAC3B,CAAC;QAED,sBAAsB;QACtB,MAAM,KAAK,GAA+B;YACxC,aAAa;YACb,gBAAgB,EAAE,EAAE,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE;SAC3D,CAAC;QACF,QAAQ,aAAa,CAAC,YAAY,EAAE,CAAC;YACnC,KAAK,eAAe;gBAClB,KAAK,CAAC,cAAc,GAAG,gBAAgB,CAAC;gBACxC,MAAM;YACR,KAAK,WAAW;gBACd,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC;gBAChC,MAAM;QACV,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,uBAAuB,CACnC,OAAoE,EACpE,WAAqC,EACrC,aAAqB;QAErB,4FAA4F;QAC5F,MAAM,oBAAoB,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,WAAW,CAAC,iBAAiB,CAAC,EAAE,kBAAkB;eACvG,OAAO,CAAC,kBAAkB,CAAC;QAEhC,oCAAoC;QACpC,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;QAC1F,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAChC,SAAS,CAAC,QAAQ,EAClB,SAAS,EACT;gBACE,OAAO,EAAE;oBACP,OAAO,EAAE,kEAAkE,oBAAoB,cAAc,WAAW,CAAC,OAAO,EAAE;iBACnI;aACF,CACF,CAAC;QACJ,CAAC;QAED,+FAA+F;QAC/F,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,gCAAgC,EAAE,CAAC;QAC1F,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,oBAAoB,CAC9D,OAAO,CAAC,QAAQ,EAChB,OAAO,CAAC,WAAW,EACnB,WAAW,EACX,WAAW,CACZ,CAAC;QAEF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+DAA+D,EAAE;gBAChF,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,WAAW;gBACX,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;gBACrC,OAAO,EAAE,WAAW,CAAC,OAAO;aAC7B,CAAC,CAAC;YACH,OAAO,EAAE,aAAa,EAAE,CAAC;QAC3B,CAAC;QAED,qDAAqD;QACrD,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;QACvE,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yEAAyE,EAAE;gBAC1F,qBAAqB,EAAE,MAAM,CAAC,qBAAqB;gBACnD,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,OAAO,EAAE,WAAW,CAAC,OAAO;aAC7B,CAAC,CAAC;YACH,OAAO,EAAE,aAAa,EAAE,CAAC;QAC3B,CAAC;QAED,2DAA2D;QAC3D,MAAM,KAAK,GAA+B;YACxC,aAAa;YACb,gBAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,WAAW,EAAE;SACzD,CAAC;QACF,QAAQ,MAAM,CAAC,qBAAqB,EAAE,CAAC;YACrC,KAAK,gBAAgB;gBACnB,KAAK,CAAC,cAAc,GAAG,gBAAgB,CAAC;gBACxC,MAAM;YACR,KAAK,QAAQ;gBACX,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC;gBAChC,MAAM;YACR;gBACE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uEAAuE,EAAE;oBACxF,qBAAqB,EAAE,MAAM,CAAC,qBAAqB;oBACnD,YAAY,EAAE,MAAM,CAAC,YAAY;oBACjC,OAAO,EAAE,WAAW,CAAC,OAAO;iBAC7B,CAAC,CAAC;gBACH,MAAM;QACV,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,4BAA4B,EAAE;YAC1C,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,qBAAqB,EAAE,MAAM,CAAC,qBAAqB;YACnD,gBAAgB;SACjB,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC;IACf,CAAC;IAED,+DAA+D;IAC/D,UAAU;IACV,+DAA+D;IAE/D,mEAAmE;IAC3D,kBAAkB,CAAC,OAAgB,EAAE,OAAe;QAC1D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAU,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;gBAC7D,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,IAAK,GAA+B,EAAE,CAAC;oBAC9E,OAAQ,GAA+B,CAAC,GAAG,CAAC,CAAC;gBAC/C,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC,EAAE,OAAO,CAAC,CAAC;YACZ,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,+EAA+E;IACvE,KAAK,CAAC,oBAAoB,CAAC,WAAmB,EAAE,WAAmB;QACzE,MAAM,MAAM,GAAG,IAAI,CAAC,yBAAyB,CAAC,wBAAwB,CACpE,WAAW,EACX,sCAAsC,CAAC,kBAAkB,CACP,CAAC;QAErD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kEAAkE,WAAW,EAAE,CAAC,CAAC;YAClG,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC;QAC/C,MAAM,SAAS,GAAG,SAAS;YACzB,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,iBAAiB,CAAC,WAAW,EAAE,sCAAsC,CAAC,kBAAkB,EAAE,SAAS,CAAC;YACrI,CAAC,CAAC,SAAS,CAAC;QACd,OAAO,MAAM,CAAC,eAAe,EAAE,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC,aAAa,IAAI,SAAS,IAAI,EAAE,CAAC;IAC1F,CAAC;IAED,sDAAsD;IAC9C,iBAAiB,CAAC,YAAoB;QAC5C,QAAQ,YAAY,EAAE,CAAC;YACrB,KAAK,eAAe,CAAC,CAAC,OAAO,gBAAgB,CAAC;YAC9C,KAAK,WAAW,CAAC,CAAC,OAAO,QAAQ,CAAC;YAClC,OAAO,CAAC,CAAC,OAAO,gBAAgB,CAAC;QACnC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,WAAmB,EAAE,WAAmB,EAAE,OAAe;QAC9E,MAAM,GAAG,GAAG,GAAG,sBAAsB,GAAG,WAAW,IAAI,WAAW,IAAI,OAAO,EAAE,CAAC;QAChF,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,GAAG,EAAE,CAAC,CAAC;IAC7D,CAAC;CACF,CAAA;AAngBY,4BAA4B;IADxC,UAAU,EAAE;IAYR,WAAA,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAA;IACjC,WAAA,MAAM,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAA;IACvC,WAAA,MAAM,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,CAAA;IAC9C,WAAA,MAAM,CAAC,kBAAkB,CAAC,qCAAqC,CAAC,CAAA;IAChE,WAAA,MAAM,CAAC,kBAAkB,CAAC,kCAAkC,CAAC,CAAA;IAC7D,WAAA,MAAM,CAAC,kBAAkB,CAAC,gCAAgC,CAAC,CAAA;IAC3D,WAAA,MAAM,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAA;IAC3C,WAAA,MAAM,CAAC,kBAAkB,CAAC,wBAAwB,CAAC,CAAA;;GAlB3C,4BAA4B,CAmgBxC","sourcesContent":["/**\n * Webhook Handler Backend Service\n *\n * Generic pipeline that processes incoming webhook events through:\n * 1. Signature verification (via capability adapter)\n * 2. Event parsing (via capability adapter)\n * 3. Idempotency check (Redis)\n * 4. Declarative scope resolution (via Hook_EndpointScopeBinding config)\n * 5. WEBHOOK_CALLBACK ExecutionContext creation\n *\n * The pipeline is provider-agnostic. Provider-specific logic is injected via:\n * - WebhookCapabilityAdapter (verify + parse)\n * - Hook_EndpointScopeBinding configuration (declarative scope resolution)\n * - Hook_ScopeResolverStrategy (optional escape hatch)\n *\n * @see hook-protocol-webhook-callback.md\n */\n\nimport { injectable, inject } from 'inversify';\nimport {\n ExternalProvider_ExchangeProtocol_Kind,\n type Hook_Endpoint,\n type Hook_EndpointScopeBinding,\n type HookInitiatorProvider_Configuration,\n type StandardHook_ParsedEvent,\n type StandardHook_ResolvedScope,\n type WebhookCapabilityAdapter,\n type Hook_ScopeResolverStrategy,\n} from '@wildo-ai/external-connectors-models';\nimport { ErrorType, CoreResourceOperation, ErrorCustomMessageReference } 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 { RedisService } from '~wildo-backend-lib/databases/services/redis.service';\nimport type { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';\nimport type { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport type { ExternalProvidersRegistryBackendService } from '~wildo-backend-lib/external-providers/services/external-providers-registry.backend.service';\nimport type { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport type { PolymorphicLookupBackendService } from './polymorphic-lookup.backend.service';\n\n// =====================================================\n// Constants\n// =====================================================\n\n/** Default idempotency TTL: 24 hours */\nconst DEFAULT_IDEMPOTENCY_TTL_SECONDS = 24 * 60 * 60;\nconst IDEMPOTENCY_KEY_PREFIX = 'webhook:';\n\n// =====================================================\n// Service\n// =====================================================\n\n@injectable()\nexport class WebhookHandlerBackendService {\n\n private readonly logDebug: (message: string, context?: Record<string, unknown>) => void;\n\n /** Capability adapters keyed by \"providerRef:endpointKey\" */\n private adapters = new Map<string, WebhookCapabilityAdapter>();\n\n /** Custom scope resolvers (escape hatch), keyed by \"providerRef:endpointKey\" */\n private customResolvers = new Map<string, Hook_ScopeResolverStrategy>();\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.RedisService) private readonly redisService: RedisService,\n @inject(SAAS_SERVICE_TYPES.ErrorBuilderService) private readonly errorBuilder: ErrorBuilderBackendService,\n @inject(SAAS_SERVICE_TYPES.ExecutionContextCreatorBackendService) private readonly executionContextCreator: ExecutionContextCreatorBackendService,\n @inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService) private readonly repositoriesRegistry: RepositoriesRegistryHandlerBackendService,\n @inject(SAAS_SERVICE_TYPES.ExternalProvidersRegistryService) private readonly externalProvidersRegistry: ExternalProvidersRegistryBackendService,\n @inject(SAAS_SERVICE_TYPES.AppConfigService) private readonly appConfigService: AppConfigurationService,\n @inject(SAAS_SERVICE_TYPES.PolymorphicLookupService) private readonly polymorphicLookup: PolymorphicLookupBackendService,\n ) {\n this.logDebug = this.logger.debugByType('WebhookHandler');\n this.logger.setDebugTypeLogging('WebhookHandler', false);\n }\n\n // ════════════════════════════════════════════════════════════\n // Registration\n // ════════════════════════════════════════════════════════════\n\n /**\n * Register a capability adapter for a specific provider endpoint.\n * Called at startup by capability modules (e.g., billing module).\n */\n registerAdapter(providerRef: string, endpointKey: string, adapter: WebhookCapabilityAdapter): void {\n const key = `${providerRef}:${endpointKey}`;\n this.adapters.set(key, adapter);\n this.logDebug(`Registered webhook adapter for ${key}`);\n }\n\n /**\n * Register a custom scope resolver to override declarative scope resolution.\n * This is an escape hatch for complex cases where Hook_EndpointScopeBinding is insufficient.\n */\n registerCustomScopeResolver(resolver: Hook_ScopeResolverStrategy): void {\n const key = `${resolver.providerRef}:${resolver.endpointKey}`;\n this.customResolvers.set(key, resolver);\n this.logDebug(`Registered custom scope resolver for ${key}`);\n }\n\n // ════════════════════════════════════════════════════════════\n // Main Pipeline\n // ════════════════════════════════════════════════════════════\n\n /**\n * Process a raw webhook through the full pipeline.\n * Called by WebhookAutoControllerBackendService's auto-registered routes.\n *\n * Returns null if the event was already processed (idempotent) or unparseable (acknowledged).\n * Throws on signature failure, scope extraction failure, or handler errors.\n */\n async processWebhook(params: {\n providerRef: string;\n endpointKey: string;\n endpoint: Hook_Endpoint;\n rawBody: string | Buffer;\n headers: Record<string, string>;\n }): Promise<{ executionContext: ExecutionContext<any>; parsedEvent: StandardHook_ParsedEvent; idempotencyKey?: string } | null> {\n const { providerRef, endpointKey, endpoint, rawBody, headers } = params;\n const adapterKey = `${providerRef}:${endpointKey}`;\n const adapter = this.adapters.get(adapterKey);\n\n if (!adapter) {\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n { context: { message: `No webhook adapter registered for ${adapterKey}` } }\n );\n }\n\n // 1. Resolve webhook secret from app configuration\n const secret = await this.resolveWebhookSecret(providerRef, endpointKey);\n\n // 2. Verify signature via capability adapter\n const signatureHeader = headers[endpoint.signatureConfig.headerName] ?? '';\n try {\n const isValid = await adapter.verifySignature(rawBody, signatureHeader, secret);\n if (!isValid) {\n throw this.errorBuilder.buildError(\n ErrorType.AUTHORIZATION,\n undefined,\n { customMessageReference: ErrorCustomMessageReference.WEBHOOK_SIGNATURE_INVALID }\n );\n }\n } catch (error) {\n if ((error as any)?.errorType === ErrorType.AUTHORIZATION) throw error;\n this.logger.error('Webhook signature verification error', { error: (error as Error).message, providerRef, endpointKey });\n throw this.errorBuilder.buildError(\n ErrorType.AUTHORIZATION,\n undefined,\n { customMessageReference: ErrorCustomMessageReference.WEBHOOK_SIGNATURE_INVALID }\n );\n }\n\n // 3. Parse event via capability adapter → StandardHook_ParsedEvent\n const parsedEvent = adapter.parseEvent(rawBody, headers);\n if (!parsedEvent) {\n // Unknown event type — acknowledge to stop retries\n this.logDebug('Unparseable/unknown webhook event — acknowledging', { providerRef, endpointKey });\n return null;\n }\n // Enrich with endpoint key\n parsedEvent.endpointKey = endpointKey;\n if (\n endpoint.eventTypes?.length\n && !endpoint.eventTypes.includes(parsedEvent.providerEventType)\n ) {\n this.logDebug('Webhook event type not declared on endpoint — acknowledging', {\n providerRef,\n endpointKey,\n eventType: parsedEvent.providerEventType,\n });\n return null;\n }\n\n // 4. Idempotency check (Redis). Completion is recorded by the controller\n // only after the capability handler succeeds, otherwise provider retries\n // would be acknowledged as duplicates after a failed processing attempt.\n let idempotencyKey: string | undefined;\n let claimedIdempotency = false;\n try {\n idempotencyKey = `${IDEMPOTENCY_KEY_PREFIX}${providerRef}:${endpointKey}:${parsedEvent.eventId}`;\n const claimStatus = await this.claimWebhookIdempotency(idempotencyKey);\n if (claimStatus === 'completed') {\n this.logDebug('Duplicate webhook event — idempotent skip', { eventId: parsedEvent.eventId });\n return null;\n }\n if (claimStatus === 'in_progress') {\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n { context: { message: `Webhook event is already being processed: ${parsedEvent.eventId}` } },\n );\n }\n claimedIdempotency = true;\n } catch (redisError) {\n if ((redisError as any)?.errorType === ErrorType.INTERNAL) throw redisError;\n this.logger.error('Redis unavailable for webhook idempotency check — failing closed', {\n error: (redisError as Error).message,\n });\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n { context: { message: 'Redis unavailable for webhook idempotency check' } },\n );\n }\n\n let executionContext: ExecutionContext<any>;\n let resolvedScope: StandardHook_ResolvedScope;\n try {\n // 5. Resolve scope (declarative or custom)\n resolvedScope = await this.resolveScope(providerRef, endpointKey, endpoint, parsedEvent);\n\n // 6. Create WEBHOOK_CALLBACK ExecutionContext\n executionContext = await this.executionContextCreator.createForWebhookCallback(\n resolvedScope,\n parsedEvent,\n );\n } catch (error) {\n if (claimedIdempotency) {\n await this.releaseWebhookClaim(idempotencyKey);\n }\n throw error;\n }\n\n this.logger.info('Webhook event processed', {\n providerRef,\n endpointKey,\n eventId: parsedEvent.eventId,\n eventType: parsedEvent.eventType,\n resolvedScope: {\n organizationId: resolvedScope.organizationId,\n userId: resolvedScope.userId,\n },\n });\n\n return { executionContext, parsedEvent, idempotencyKey };\n }\n\n private async claimWebhookIdempotency(idempotencyKey: string): Promise<'claimed' | 'in_progress' | 'completed'> {\n const redisKey = this.redisService.buildKey(idempotencyKey);\n const result = await this.redisService.eval(\n `\n local existing = redis.call('GET', KEYS[1])\n if existing == false then\n redis.call('SET', KEYS[1], ARGV[1], 'EX', ARGV[2])\n return 'claimed'\n end\n return existing\n `,\n [redisKey],\n ['in_progress', String(5 * 60)],\n );\n\n if (result === '\"completed\"' || result === 'completed') return 'completed';\n if (result === '\"in_progress\"' || result === 'in_progress') return 'in_progress';\n return 'claimed';\n }\n\n async markWebhookProcessed(idempotencyKey: string | undefined): Promise<void> {\n if (!idempotencyKey) return;\n try {\n await this.redisService.eval(\n \"redis.call('SET', KEYS[1], ARGV[1], 'EX', ARGV[2]); return ARGV[1]\",\n [this.redisService.buildKey(idempotencyKey)],\n ['completed', String(DEFAULT_IDEMPOTENCY_TTL_SECONDS)],\n );\n } catch (redisError) {\n this.logger.error('Redis unavailable for webhook idempotency completion', {\n error: (redisError as Error).message,\n });\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n { context: { message: 'Redis unavailable for webhook idempotency completion' } },\n );\n }\n }\n\n async releaseWebhookClaim(idempotencyKey: string | undefined): Promise<void> {\n if (!idempotencyKey) return;\n try {\n await this.redisService.del(this.redisService.buildKey(idempotencyKey));\n } catch (redisError) {\n this.logger.error('Redis unavailable for webhook idempotency release', {\n error: (redisError as Error).message,\n });\n }\n }\n\n // ════════════════════════════════════════════════════════════\n // Declarative Scope Resolution\n // ════════════════════════════════════════════════════════════\n\n /**\n * Resolve the engine scope from a webhook event.\n *\n * Priority:\n * 1. Custom resolver (escape hatch) if registered for this endpoint\n * 2. Declarative resolution via Hook_EndpointScopeBinding config\n */\n private async resolveScope(\n providerRef: string,\n endpointKey: string,\n endpoint: Hook_Endpoint,\n parsedEvent: StandardHook_ParsedEvent\n ): Promise<StandardHook_ResolvedScope> {\n // Check custom resolver first (escape hatch)\n const customResolver = this.customResolvers.get(`${providerRef}:${endpointKey}`);\n if (customResolver) {\n return customResolver.resolveScope(parsedEvent);\n }\n\n const applicationId = this.appConfigService.applicationId;\n const binding = endpoint.scopeBinding;\n\n // APPLICATION scope — no lookup needed\n if ('primaryScope' in binding && binding.primaryScope === 'APPLICATION') {\n return { applicationId };\n }\n\n // Check scope-exempt events (e.g., product.updated → APPLICATION scope)\n if ('scopeExemptEventTypes' in binding && binding.scopeExemptEventTypes?.includes(parsedEvent.providerEventType)) {\n this.logDebug('Scope-exempt event type — using APPLICATION scope', {\n eventType: parsedEvent.providerEventType,\n });\n return { applicationId };\n }\n\n // ─── Polymorphic mode ───\n // Queries N variant collections and resolves scope from whichever variant matches.\n if ('mode' in binding && binding.mode === 'polymorphic') {\n return this.resolvePolymorphicScope(binding, parsedEvent, applicationId);\n }\n\n // ─── Single-scope mode ───\n // After APPLICATION and polymorphic early returns, narrow to single-scope binding.\n const singleBinding = binding as Extract<Hook_EndpointScopeBinding, { lookupResourceType: string }>;\n\n // Extract scope ID from payload using configured dot-path\n const scopeId = this.extractFromPayload(parsedEvent.rawPayload, singleBinding.payloadScopeIdPath);\n if (!scopeId) {\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n {\n context: {\n message: `Webhook scope resolution failed: no value at path '${singleBinding.payloadScopeIdPath}' in event ${parsedEvent.eventId}`,\n },\n }\n );\n }\n\n // Lookup resource to find the scope entity ID.\n const internalCtx = await this.executionContextCreator.createForInternalSystemOperation();\n const repository = this.repositoriesRegistry.getRepository(singleBinding.lookupResourceType);\n if (!repository) {\n this.logger.warn('Webhook scope resolution: repository not found', {\n lookupResourceType: singleBinding.lookupResourceType,\n eventId: parsedEvent.eventId,\n });\n return { applicationId };\n }\n\n let resource: any;\n try {\n const results = await repository.doByPath(\n { resourceIdentifier: singleBinding.lookupResourceType, operationIdentifier: CoreResourceOperation.LIST },\n internalCtx,\n { [singleBinding.lookupField]: scopeId },\n );\n resource = Array.isArray(results) ? results[0] : results;\n } catch (lookupError) {\n this.logger.warn('Webhook scope resolution: lookup failed', {\n lookupResourceType: singleBinding.lookupResourceType,\n lookupField: singleBinding.lookupField,\n scopeId,\n eventId: parsedEvent.eventId,\n error: (lookupError as Error).message,\n });\n return { applicationId };\n }\n\n if (!resource) {\n this.logger.warn('Webhook scope resolution: resource not found', {\n lookupResourceType: singleBinding.lookupResourceType,\n lookupField: singleBinding.lookupField,\n scopeId,\n eventId: parsedEvent.eventId,\n });\n return { applicationId };\n }\n\n // Extract scope entity ID\n const scopeEntityIdField = singleBinding.scopeEntityIdField ?? this.defaultScopeField(singleBinding.primaryScope);\n const resolvedEntityId = resource[scopeEntityIdField];\n\n if (!resolvedEntityId) {\n this.logger.warn('Webhook scope resolution: entity ID field empty on resource', {\n scopeEntityIdField,\n lookupResourceType: singleBinding.lookupResourceType,\n eventId: parsedEvent.eventId,\n });\n return { applicationId };\n }\n\n // Map to engine scope\n const scope: StandardHook_ResolvedScope = {\n applicationId,\n providerScopeIds: { [singleBinding.lookupField]: scopeId },\n };\n switch (singleBinding.primaryScope) {\n case 'ORGANIZATIONS':\n scope.organizationId = resolvedEntityId;\n break;\n case 'USER_SELF':\n scope.userId = resolvedEntityId;\n break;\n }\n\n return scope;\n }\n\n /**\n * Resolve scope using polymorphic lookup — queries N variant collections.\n * Delegates to PolymorphicLookupBackendService for the multi-collection query,\n * then maps the result to the engine scope.\n */\n private async resolvePolymorphicScope(\n binding: Extract<Hook_EndpointScopeBinding, { mode: 'polymorphic' }>,\n parsedEvent: StandardHook_ParsedEvent,\n applicationId: string,\n ): Promise<StandardHook_ResolvedScope> {\n // Resolve the payload path — check per-event-type override first, then fall back to default\n const effectiveScopeIdPath = binding.eventTypeOverrides?.[parsedEvent.providerEventType]?.payloadScopeIdPath\n ?? binding.payloadScopeIdPath;\n\n // Extract lookup value from payload\n const lookupValue = this.extractFromPayload(parsedEvent.rawPayload, effectiveScopeIdPath);\n if (!lookupValue) {\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n {\n context: {\n message: `Webhook polymorphic scope resolution failed: no value at path '${effectiveScopeIdPath}' in event ${parsedEvent.eventId}`,\n },\n }\n );\n }\n\n // Query across all variant collections (pass the internal context to avoid redundant creation)\n const internalCtx = await this.executionContextCreator.createForInternalSystemOperation();\n const result = await this.polymorphicLookup.lookupAcrossVariants(\n binding.variants,\n binding.lookupField,\n lookupValue,\n internalCtx,\n );\n\n if (!result) {\n this.logger.warn('Webhook polymorphic scope resolution: no match in any variant', {\n lookupField: binding.lookupField,\n lookupValue,\n variantCount: binding.variants.length,\n eventId: parsedEvent.eventId,\n });\n return { applicationId };\n }\n\n // Read the scope entity ID from the matched document\n const resolvedEntityId = result.document[result.parentFieldIdentifier];\n if (!resolvedEntityId) {\n this.logger.warn('Webhook polymorphic scope resolution: entity ID field empty on document', {\n parentFieldIdentifier: result.parentFieldIdentifier,\n resourceType: result.resourceType,\n eventId: parsedEvent.eventId,\n });\n return { applicationId };\n }\n\n // Map to engine scope based on the parent field identifier\n const scope: StandardHook_ResolvedScope = {\n applicationId,\n providerScopeIds: { [binding.lookupField]: lookupValue },\n };\n switch (result.parentFieldIdentifier) {\n case 'organizationId':\n scope.organizationId = resolvedEntityId;\n break;\n case 'userId':\n scope.userId = resolvedEntityId;\n break;\n default:\n this.logger.warn('Webhook polymorphic scope resolution: unknown parent field identifier', {\n parentFieldIdentifier: result.parentFieldIdentifier,\n resourceType: result.resourceType,\n eventId: parsedEvent.eventId,\n });\n break;\n }\n\n this.logDebug('Polymorphic scope resolved', {\n resourceType: result.resourceType,\n parentFieldIdentifier: result.parentFieldIdentifier,\n resolvedEntityId,\n });\n\n return scope;\n }\n\n // ════════════════════════════════════════════════════════════\n // Helpers\n // ════════════════════════════════════════════════════════════\n\n /** Extract a value from a nested object using dot-notation path */\n private extractFromPayload(payload: unknown, dotPath: string): string | null {\n try {\n const result = dotPath.split('.').reduce<unknown>((obj, key) => {\n if (obj && typeof obj === 'object' && key in (obj as Record<string, unknown>)) {\n return (obj as Record<string, unknown>)[key];\n }\n return undefined;\n }, payload);\n return typeof result === 'string' ? result : result != null ? String(result) : null;\n } catch {\n return null;\n }\n }\n\n /** Resolve webhook secret from app configuration (per-endpoint or fallback) */\n private async resolveWebhookSecret(providerRef: string, endpointKey: string): Promise<string> {\n const config = this.externalProvidersRegistry.getProviderConfiguration(\n providerRef,\n ExternalProvider_ExchangeProtocol_Kind.WEBHOOK_ORIGINATOR,\n ) as HookInitiatorProvider_Configuration | undefined;\n\n if (!config) {\n this.logger.warn(`No WEBHOOK_ORIGINATOR runtime configuration found for provider ${providerRef}`);\n return '';\n }\n\n const secretRef = config.authConfig?.secretRef;\n const envSecret = secretRef\n ? this.externalProvidersRegistry.getProviderSecret(providerRef, ExternalProvider_ExchangeProtocol_Kind.WEBHOOK_ORIGINATOR, secretRef)\n : undefined;\n return config.endpointSecrets?.[endpointKey] ?? config.webhookSecret ?? envSecret ?? '';\n }\n\n /** Default scope field name based on primary scope */\n private defaultScopeField(primaryScope: string): string {\n switch (primaryScope) {\n case 'ORGANIZATIONS': return 'organizationId';\n case 'USER_SELF': return 'userId';\n default: return 'organizationId';\n }\n }\n\n /**\n * Admin method: clear idempotency for forced reprocessing.\n * Use during debugging or when an event needs to be reprocessed.\n */\n async clearIdempotency(providerRef: string, endpointKey: string, eventId: string): Promise<void> {\n const key = `${IDEMPOTENCY_KEY_PREFIX}${providerRef}:${endpointKey}:${eventId}`;\n await this.redisService.del(this.redisService.buildKey(key));\n this.logger.info(`Cleared webhook idempotency for ${key}`);\n }\n}\n"]}
1
+ {"version":3,"file":"webhook-handler.backend.service.js","sourceRoot":"","sources":["../../../../../../src/notifications/webhooks/services/webhook-handler.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Webhook Handler Backend Service\n *\n * Generic pipeline that processes incoming webhook events through:\n * 1. Signature verification (via capability adapter)\n * 2. Event parsing (via capability adapter)\n * 3. Idempotency check (Redis)\n * 4. Declarative scope resolution (via Hook_EndpointScopeBinding config)\n * 5. WEBHOOK_CALLBACK ExecutionContext creation\n *\n * The pipeline is provider-agnostic. Provider-specific logic is injected via:\n * - WebhookCapabilityAdapter (verify + parse)\n * - Hook_EndpointScopeBinding configuration (declarative scope resolution)\n * - Hook_ScopeResolverStrategy (optional escape hatch)\n *\n * @see hook-protocol-webhook-callback.md\n */\n\nimport { injectable, inject } from 'inversify';\nimport {\n ExternalProvider_ExchangeProtocol_Kind,\n type Hook_Endpoint,\n type Hook_EndpointScopeBinding,\n type HookInitiatorProvider_Configuration,\n type StandardHook_ParsedEvent,\n type StandardHook_ResolvedScope,\n type WebhookCapabilityAdapter,\n type Hook_ScopeResolverStrategy,\n} from '@wildo-ai/external-connectors-models';\nimport { ErrorType, CoreResourceOperation, ErrorCustomMessageReference } 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 { RedisService } from '~wildo-backend-lib/databases/services/redis.service';\nimport type { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';\nimport type { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport type { ExternalProvidersRegistryBackendService } from '~wildo-backend-lib/external-providers/services/external-providers-registry.backend.service';\nimport type { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport type { PolymorphicLookupBackendService } from './polymorphic-lookup.backend.service';\n\n// =====================================================\n// Constants\n// =====================================================\n\n/** Default idempotency TTL: 24 hours */\nconst DEFAULT_IDEMPOTENCY_TTL_SECONDS = 24 * 60 * 60;\nconst IDEMPOTENCY_KEY_PREFIX = 'webhook:';\n\n// =====================================================\n// Service\n// =====================================================\n\n@injectable()\nexport class WebhookHandlerBackendService {\n\n private readonly logDebug: (message: string, context?: Record<string, unknown>) => void;\n\n /** Capability adapters keyed by \"providerRef:endpointKey\" */\n private adapters = new Map<string, WebhookCapabilityAdapter>();\n\n /** Custom scope resolvers (escape hatch), keyed by \"providerRef:endpointKey\" */\n private customResolvers = new Map<string, Hook_ScopeResolverStrategy>();\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.RedisService) private readonly redisService: RedisService,\n @inject(SAAS_SERVICE_TYPES.ErrorBuilderService) private readonly errorBuilder: ErrorBuilderBackendService,\n @inject(SAAS_SERVICE_TYPES.ExecutionContextCreatorBackendService) private readonly executionContextCreator: ExecutionContextCreatorBackendService,\n @inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService) private readonly repositoriesRegistry: RepositoriesRegistryHandlerBackendService,\n @inject(SAAS_SERVICE_TYPES.ExternalProvidersRegistryService) private readonly externalProvidersRegistry: ExternalProvidersRegistryBackendService,\n @inject(SAAS_SERVICE_TYPES.AppConfigService) private readonly appConfigService: AppConfigurationService,\n @inject(SAAS_SERVICE_TYPES.PolymorphicLookupService) private readonly polymorphicLookup: PolymorphicLookupBackendService,\n ) {\n this.logDebug = this.logger.debugByType('WebhookHandler');\n this.logger.setDebugTypeLogging('WebhookHandler', false);\n }\n\n // ════════════════════════════════════════════════════════════\n // Registration\n // ════════════════════════════════════════════════════════════\n\n /**\n * Register a capability adapter for a specific provider endpoint.\n * Called at startup by capability modules (e.g., billing module).\n */\n registerAdapter(providerRef: string, endpointKey: string, adapter: WebhookCapabilityAdapter): void {\n const key = `${providerRef}:${endpointKey}`;\n this.adapters.set(key, adapter);\n this.logDebug(`Registered webhook adapter for ${key}`);\n }\n\n /**\n * Whether a capability adapter is registered for `providerRef:endpointKey`.\n *\n * Read-only mount-time predicate for {@link WebhookAutoControllerBackendService}:\n * without an adapter, `processWebhook` throws `INTERNAL` at the very top of the\n * pipeline (`No webhook adapter registered for ...`), which the controller answers\n * as a 500 — i.e. an instruction to the VENDOR to retry an event that can never be\n * processed, because nothing about a retry supplies the missing registration. The\n * auto-controller therefore asks this BEFORE mounting a route, and withholds the\n * route instead of mounting one that can only fail.\n *\n * Deliberately not exposing the adapter itself: the caller needs an admission\n * decision, not the verify/parse surface, and handing out the adapter would let a\n * consumer route around `processWebhook`'s signature/idempotency pipeline.\n */\n hasAdapter(providerRef: string, endpointKey: string): boolean {\n return this.adapters.has(`${providerRef}:${endpointKey}`);\n }\n\n /**\n * Register a custom scope resolver to override declarative scope resolution.\n * This is an escape hatch for complex cases where Hook_EndpointScopeBinding is insufficient.\n */\n registerCustomScopeResolver(resolver: Hook_ScopeResolverStrategy): void {\n const key = `${resolver.providerRef}:${resolver.endpointKey}`;\n this.customResolvers.set(key, resolver);\n this.logDebug(`Registered custom scope resolver for ${key}`);\n }\n\n // ════════════════════════════════════════════════════════════\n // Main Pipeline\n // ════════════════════════════════════════════════════════════\n\n /**\n * Process a raw webhook through the full pipeline.\n * Called by WebhookAutoControllerBackendService's auto-registered routes.\n *\n * Returns null if the event was already processed (idempotent) or unparseable (acknowledged).\n * Throws on signature failure, scope extraction failure, or handler errors.\n */\n async processWebhook(params: {\n providerRef: string;\n endpointKey: string;\n endpoint: Hook_Endpoint;\n rawBody: string | Buffer;\n headers: Record<string, string>;\n }): Promise<{ executionContext: ExecutionContext<any>; parsedEvent: StandardHook_ParsedEvent; idempotencyKey?: string } | null> {\n const { providerRef, endpointKey, endpoint, rawBody, headers } = params;\n const adapterKey = `${providerRef}:${endpointKey}`;\n const adapter = this.adapters.get(adapterKey);\n\n if (!adapter) {\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n { context: { message: `No webhook adapter registered for ${adapterKey}` } }\n );\n }\n\n // 1. Resolve webhook secret from app configuration\n const secret = await this.resolveWebhookSecret(providerRef, endpointKey);\n\n // 2. Verify signature via capability adapter\n const signatureHeader = headers[endpoint.signatureConfig.headerName] ?? '';\n try {\n const isValid = await adapter.verifySignature(rawBody, signatureHeader, secret);\n if (!isValid) {\n throw this.errorBuilder.buildError(\n ErrorType.AUTHORIZATION,\n undefined,\n { customMessageReference: ErrorCustomMessageReference.WEBHOOK_SIGNATURE_INVALID }\n );\n }\n } catch (error) {\n if ((error as any)?.errorType === ErrorType.AUTHORIZATION) throw error;\n this.logger.error('Webhook signature verification error', { error: (error as Error).message, providerRef, endpointKey });\n throw this.errorBuilder.buildError(\n ErrorType.AUTHORIZATION,\n undefined,\n { customMessageReference: ErrorCustomMessageReference.WEBHOOK_SIGNATURE_INVALID }\n );\n }\n\n // 3. Parse event via capability adapter → StandardHook_ParsedEvent\n const parsedEvent = adapter.parseEvent(rawBody, headers);\n if (!parsedEvent) {\n // Unknown event type — acknowledge to stop retries\n this.logDebug('Unparseable/unknown webhook event — acknowledging', { providerRef, endpointKey });\n return null;\n }\n // Enrich with endpoint key\n parsedEvent.endpointKey = endpointKey;\n if (\n endpoint.eventTypes?.length\n && !endpoint.eventTypes.includes(parsedEvent.providerEventType)\n ) {\n this.logDebug('Webhook event type not declared on endpoint — acknowledging', {\n providerRef,\n endpointKey,\n eventType: parsedEvent.providerEventType,\n });\n return null;\n }\n\n // 4. Idempotency check (Redis). Completion is recorded by the controller\n // only after the capability handler succeeds, otherwise provider retries\n // would be acknowledged as duplicates after a failed processing attempt.\n let idempotencyKey: string | undefined;\n let claimedIdempotency = false;\n try {\n idempotencyKey = `${IDEMPOTENCY_KEY_PREFIX}${providerRef}:${endpointKey}:${parsedEvent.eventId}`;\n const claimStatus = await this.claimWebhookIdempotency(idempotencyKey);\n if (claimStatus === 'completed') {\n this.logDebug('Duplicate webhook event — idempotent skip', { eventId: parsedEvent.eventId });\n return null;\n }\n if (claimStatus === 'in_progress') {\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n { context: { message: `Webhook event is already being processed: ${parsedEvent.eventId}` } },\n );\n }\n claimedIdempotency = true;\n } catch (redisError) {\n if ((redisError as any)?.errorType === ErrorType.INTERNAL) throw redisError;\n this.logger.error('Redis unavailable for webhook idempotency check — failing closed', {\n error: (redisError as Error).message,\n });\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n { context: { message: 'Redis unavailable for webhook idempotency check' } },\n );\n }\n\n let executionContext: ExecutionContext<any>;\n let resolvedScope: StandardHook_ResolvedScope;\n try {\n // 5. Resolve scope (declarative or custom)\n resolvedScope = await this.resolveScope(providerRef, endpointKey, endpoint, parsedEvent);\n\n // 6. Create WEBHOOK_CALLBACK ExecutionContext\n executionContext = await this.executionContextCreator.createForWebhookCallback(\n resolvedScope,\n parsedEvent,\n );\n } catch (error) {\n if (claimedIdempotency) {\n await this.releaseWebhookClaim(idempotencyKey);\n }\n throw error;\n }\n\n this.logger.info('Webhook event processed', {\n providerRef,\n endpointKey,\n eventId: parsedEvent.eventId,\n eventType: parsedEvent.eventType,\n resolvedScope: {\n organizationId: resolvedScope.organizationId,\n userId: resolvedScope.userId,\n },\n });\n\n return { executionContext, parsedEvent, idempotencyKey };\n }\n\n private async claimWebhookIdempotency(idempotencyKey: string): Promise<'claimed' | 'in_progress' | 'completed'> {\n const redisKey = this.redisService.buildKey(idempotencyKey);\n const result = await this.redisService.eval(\n `\n local existing = redis.call('GET', KEYS[1])\n if existing == false then\n redis.call('SET', KEYS[1], ARGV[1], 'EX', ARGV[2])\n return 'claimed'\n end\n return existing\n `,\n [redisKey],\n ['in_progress', String(5 * 60)],\n );\n\n if (result === '\"completed\"' || result === 'completed') return 'completed';\n if (result === '\"in_progress\"' || result === 'in_progress') return 'in_progress';\n return 'claimed';\n }\n\n async markWebhookProcessed(idempotencyKey: string | undefined): Promise<void> {\n if (!idempotencyKey) return;\n try {\n await this.redisService.eval(\n \"redis.call('SET', KEYS[1], ARGV[1], 'EX', ARGV[2]); return ARGV[1]\",\n [this.redisService.buildKey(idempotencyKey)],\n ['completed', String(DEFAULT_IDEMPOTENCY_TTL_SECONDS)],\n );\n } catch (redisError) {\n this.logger.error('Redis unavailable for webhook idempotency completion', {\n error: (redisError as Error).message,\n });\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n { context: { message: 'Redis unavailable for webhook idempotency completion' } },\n );\n }\n }\n\n async releaseWebhookClaim(idempotencyKey: string | undefined): Promise<void> {\n if (!idempotencyKey) return;\n try {\n await this.redisService.del(this.redisService.buildKey(idempotencyKey));\n } catch (redisError) {\n this.logger.error('Redis unavailable for webhook idempotency release', {\n error: (redisError as Error).message,\n });\n }\n }\n\n // ════════════════════════════════════════════════════════════\n // Declarative Scope Resolution\n // ════════════════════════════════════════════════════════════\n\n /**\n * Resolve the engine scope from a webhook event.\n *\n * Priority:\n * 1. Custom resolver (escape hatch) if registered for this endpoint\n * 2. Declarative resolution via Hook_EndpointScopeBinding config\n */\n private async resolveScope(\n providerRef: string,\n endpointKey: string,\n endpoint: Hook_Endpoint,\n parsedEvent: StandardHook_ParsedEvent\n ): Promise<StandardHook_ResolvedScope> {\n // Check custom resolver first (escape hatch)\n const customResolver = this.customResolvers.get(`${providerRef}:${endpointKey}`);\n if (customResolver) {\n return customResolver.resolveScope(parsedEvent);\n }\n\n const applicationId = this.appConfigService.applicationId;\n const binding = endpoint.scopeBinding;\n\n // APPLICATION scope — no lookup needed\n if ('primaryScope' in binding && binding.primaryScope === 'APPLICATION') {\n return { applicationId };\n }\n\n // Check scope-exempt events (e.g., product.updated → APPLICATION scope)\n if ('scopeExemptEventTypes' in binding && binding.scopeExemptEventTypes?.includes(parsedEvent.providerEventType)) {\n this.logDebug('Scope-exempt event type — using APPLICATION scope', {\n eventType: parsedEvent.providerEventType,\n });\n return { applicationId };\n }\n\n // ─── Polymorphic mode ───\n // Queries N variant collections and resolves scope from whichever variant matches.\n if ('mode' in binding && binding.mode === 'polymorphic') {\n return this.resolvePolymorphicScope(binding, parsedEvent, applicationId);\n }\n\n // ─── Single-scope mode ───\n // After APPLICATION and polymorphic early returns, narrow to single-scope binding.\n const singleBinding = binding as Extract<Hook_EndpointScopeBinding, { lookupResourceType: string }>;\n\n // Extract scope ID from payload using configured dot-path\n const scopeId = this.extractFromPayload(parsedEvent.rawPayload, singleBinding.payloadScopeIdPath);\n if (!scopeId) {\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n {\n context: {\n message: `Webhook scope resolution failed: no value at path '${singleBinding.payloadScopeIdPath}' in event ${parsedEvent.eventId}`,\n },\n }\n );\n }\n\n // Lookup resource to find the scope entity ID.\n const internalCtx = await this.executionContextCreator.createForInternalSystemOperation();\n const repository = this.repositoriesRegistry.getRepository(singleBinding.lookupResourceType);\n if (!repository) {\n this.logger.warn('Webhook scope resolution: repository not found', {\n lookupResourceType: singleBinding.lookupResourceType,\n eventId: parsedEvent.eventId,\n });\n return { applicationId };\n }\n\n let resource: any;\n try {\n const results = await repository.doByPath(\n { resourceIdentifier: singleBinding.lookupResourceType, operationIdentifier: CoreResourceOperation.LIST },\n internalCtx,\n { [singleBinding.lookupField]: scopeId },\n );\n resource = Array.isArray(results) ? results[0] : results;\n } catch (lookupError) {\n this.logger.warn('Webhook scope resolution: lookup failed', {\n lookupResourceType: singleBinding.lookupResourceType,\n lookupField: singleBinding.lookupField,\n scopeId,\n eventId: parsedEvent.eventId,\n error: (lookupError as Error).message,\n });\n return { applicationId };\n }\n\n if (!resource) {\n this.logger.warn('Webhook scope resolution: resource not found', {\n lookupResourceType: singleBinding.lookupResourceType,\n lookupField: singleBinding.lookupField,\n scopeId,\n eventId: parsedEvent.eventId,\n });\n return { applicationId };\n }\n\n // Extract scope entity ID\n const scopeEntityIdField = singleBinding.scopeEntityIdField ?? this.defaultScopeField(singleBinding.primaryScope);\n const resolvedEntityId = resource[scopeEntityIdField];\n\n if (!resolvedEntityId) {\n this.logger.warn('Webhook scope resolution: entity ID field empty on resource', {\n scopeEntityIdField,\n lookupResourceType: singleBinding.lookupResourceType,\n eventId: parsedEvent.eventId,\n });\n return { applicationId };\n }\n\n // Map to engine scope\n const scope: StandardHook_ResolvedScope = {\n applicationId,\n providerScopeIds: { [singleBinding.lookupField]: scopeId },\n };\n switch (singleBinding.primaryScope) {\n case 'ORGANIZATIONS':\n scope.organizationId = resolvedEntityId;\n break;\n case 'USER_SELF':\n scope.userId = resolvedEntityId;\n break;\n }\n\n return scope;\n }\n\n /**\n * Resolve scope using polymorphic lookup — queries N variant collections.\n * Delegates to PolymorphicLookupBackendService for the multi-collection query,\n * then maps the result to the engine scope.\n */\n private async resolvePolymorphicScope(\n binding: Extract<Hook_EndpointScopeBinding, { mode: 'polymorphic' }>,\n parsedEvent: StandardHook_ParsedEvent,\n applicationId: string,\n ): Promise<StandardHook_ResolvedScope> {\n // Resolve the payload path — check per-event-type override first, then fall back to default\n const effectiveScopeIdPath = binding.eventTypeOverrides?.[parsedEvent.providerEventType]?.payloadScopeIdPath\n ?? binding.payloadScopeIdPath;\n\n // Extract lookup value from payload\n const lookupValue = this.extractFromPayload(parsedEvent.rawPayload, effectiveScopeIdPath);\n if (!lookupValue) {\n throw this.errorBuilder.buildError(\n ErrorType.INTERNAL,\n undefined,\n {\n context: {\n message: `Webhook polymorphic scope resolution failed: no value at path '${effectiveScopeIdPath}' in event ${parsedEvent.eventId}`,\n },\n }\n );\n }\n\n // Query across all variant collections (pass the internal context to avoid redundant creation)\n const internalCtx = await this.executionContextCreator.createForInternalSystemOperation();\n const result = await this.polymorphicLookup.lookupAcrossVariants(\n binding.variants,\n binding.lookupField,\n lookupValue,\n internalCtx,\n );\n\n if (!result) {\n this.logger.warn('Webhook polymorphic scope resolution: no match in any variant', {\n lookupField: binding.lookupField,\n lookupValue,\n variantCount: binding.variants.length,\n eventId: parsedEvent.eventId,\n });\n return { applicationId };\n }\n\n // Read the scope entity ID from the matched document\n const resolvedEntityId = result.document[result.parentFieldIdentifier];\n if (!resolvedEntityId) {\n this.logger.warn('Webhook polymorphic scope resolution: entity ID field empty on document', {\n parentFieldIdentifier: result.parentFieldIdentifier,\n resourceType: result.resourceType,\n eventId: parsedEvent.eventId,\n });\n return { applicationId };\n }\n\n // Map to engine scope based on the parent field identifier\n const scope: StandardHook_ResolvedScope = {\n applicationId,\n providerScopeIds: { [binding.lookupField]: lookupValue },\n };\n switch (result.parentFieldIdentifier) {\n case 'organizationId':\n scope.organizationId = resolvedEntityId;\n break;\n case 'userId':\n scope.userId = resolvedEntityId;\n break;\n default:\n this.logger.warn('Webhook polymorphic scope resolution: unknown parent field identifier', {\n parentFieldIdentifier: result.parentFieldIdentifier,\n resourceType: result.resourceType,\n eventId: parsedEvent.eventId,\n });\n break;\n }\n\n this.logDebug('Polymorphic scope resolved', {\n resourceType: result.resourceType,\n parentFieldIdentifier: result.parentFieldIdentifier,\n resolvedEntityId,\n });\n\n return scope;\n }\n\n // ════════════════════════════════════════════════════════════\n // Helpers\n // ════════════════════════════════════════════════════════════\n\n /** Extract a value from a nested object using dot-notation path */\n private extractFromPayload(payload: unknown, dotPath: string): string | null {\n try {\n const result = dotPath.split('.').reduce<unknown>((obj, key) => {\n if (obj && typeof obj === 'object' && key in (obj as Record<string, unknown>)) {\n return (obj as Record<string, unknown>)[key];\n }\n return undefined;\n }, payload);\n return typeof result === 'string' ? result : result != null ? String(result) : null;\n } catch {\n return null;\n }\n }\n\n /** Resolve webhook secret from app configuration (per-endpoint or fallback) */\n private async resolveWebhookSecret(providerRef: string, endpointKey: string): Promise<string> {\n const config = this.externalProvidersRegistry.getProviderConfiguration(\n providerRef,\n ExternalProvider_ExchangeProtocol_Kind.WEBHOOK_ORIGINATOR,\n ) as HookInitiatorProvider_Configuration | undefined;\n\n if (!config) {\n this.logger.warn(`No WEBHOOK_ORIGINATOR runtime configuration found for provider ${providerRef}`);\n return '';\n }\n\n const secretRef = config.authConfig?.secretRef;\n const envSecret = secretRef\n ? this.externalProvidersRegistry.getProviderSecret(providerRef, ExternalProvider_ExchangeProtocol_Kind.WEBHOOK_ORIGINATOR, secretRef)\n : undefined;\n return config.endpointSecrets?.[endpointKey] ?? config.webhookSecret ?? envSecret ?? '';\n }\n\n /** Default scope field name based on primary scope */\n private defaultScopeField(primaryScope: string): string {\n switch (primaryScope) {\n case 'ORGANIZATIONS': return 'organizationId';\n case 'USER_SELF': return 'userId';\n default: return 'organizationId';\n }\n }\n\n /**\n * Admin method: clear idempotency for forced reprocessing.\n * Use during debugging or when an event needs to be reprocessed.\n */\n async clearIdempotency(providerRef: string, endpointKey: string, eventId: string): Promise<void> {\n const key = `${IDEMPOTENCY_KEY_PREFIX}${providerRef}:${endpointKey}:${eventId}`;\n await this.redisService.del(this.redisService.buildKey(key));\n this.logger.info(`Cleared webhook idempotency for ${key}`);\n }\n}\n"]}
@@ -2,8 +2,8 @@
2
2
  * Organization Purge Batch — the DESTRUCTIVE half of tenant teardown (WS-A).
3
3
  *
4
4
  * Tenant deletion is two phases. `request_deletion` marks a tenant: it writes `status: DELETED`,
5
- * `deletedAt` and `purgeScheduledAt`, reconciles every affected user's global `userTypes` and
6
- * invalidates their tokens — so the tenant is authorization-dead immediately while every row it
5
+ * `deletionRequestedAt` and `purgeScheduledAt`, reconciles every affected user's global `userTypes`
6
+ * and invalidates their tokens — so the tenant is authorization-dead immediately while every row it
7
7
  * owns is still present and restorable. This batch is the second phase: once a tenant's
8
8
  * `purgeScheduledAt` deadline has passed, it destroys it.
9
9
  *