@wildo-ai/saas-backend-lib 1.1.2 → 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 (853) 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.map +1 -1
  20. package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.js +27 -6
  21. package/dist/esm/base-classes/services/controllers/controller-resource.backend.service.js.map +1 -1
  22. package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.d.ts +124 -13
  23. package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.d.ts.map +1 -1
  24. package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.js +207 -21
  25. package/dist/esm/base-classes/services/repositories/http-api/http-api-provider-access.backend.js.map +1 -1
  26. package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.d.ts +60 -8
  27. package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.d.ts.map +1 -1
  28. package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.js +174 -26
  29. package/dist/esm/base-classes/services/repositories/http-api/http-api-read-client.backend.js.map +1 -1
  30. package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.d.ts +47 -4
  31. package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.d.ts.map +1 -1
  32. package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.js +96 -29
  33. package/dist/esm/base-classes/services/repositories/http-api/http-api-resource-repository.backend.service.js.map +1 -1
  34. package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.d.ts +55 -0
  35. package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.d.ts.map +1 -0
  36. package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.js +114 -0
  37. package/dist/esm/base-classes/services/repositories/http-api/http-api-rest-operation-reference.backend.js.map +1 -0
  38. package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.d.ts +89 -14
  39. package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.d.ts.map +1 -1
  40. package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.js +84 -11
  41. package/dist/esm/base-classes/services/repositories/http-api/http-api-transport.backend.js.map +1 -1
  42. package/dist/esm/base-classes/services/repositories/infrastructure-tier-contract.backend.d.ts.map +1 -1
  43. package/dist/esm/base-classes/services/repositories/infrastructure-tier-contract.backend.js +9 -1
  44. package/dist/esm/base-classes/services/repositories/infrastructure-tier-contract.backend.js.map +1 -1
  45. package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.d.ts +49 -0
  46. package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.d.ts.map +1 -1
  47. package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.js +171 -18
  48. package/dist/esm/base-classes/services/repositories/postgresql-resource-repository.backend.service.js.map +1 -1
  49. package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.d.ts.map +1 -1
  50. package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.js +23 -3
  51. package/dist/esm/base-classes/services/repositories/repositories-registry-handler.backend.service.js.map +1 -1
  52. package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.d.ts.map +1 -1
  53. package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.js +20 -0
  54. package/dist/esm/base-classes/services/repositories/repository-resource.backend.service.js.map +1 -1
  55. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.d.ts +22 -0
  56. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.d.ts.map +1 -1
  57. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-base.backend.service.js.map +1 -1
  58. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts.map +1 -1
  59. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js +4 -1
  60. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js.map +1 -1
  61. package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.d.ts +11 -0
  62. package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.d.ts.map +1 -1
  63. package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.js +39 -5
  64. package/dist/esm/base-classes/services/services/resource-status-transition.definitions.backend.js.map +1 -1
  65. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts +181 -2
  66. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts.map +1 -1
  67. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js +529 -41
  68. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js.map +1 -1
  69. package/dist/esm/base-classes/services/services/system-access.backend.service.d.ts +36 -3
  70. package/dist/esm/base-classes/services/services/system-access.backend.service.d.ts.map +1 -1
  71. package/dist/esm/base-classes/services/services/system-access.backend.service.js +70 -8
  72. package/dist/esm/base-classes/services/services/system-access.backend.service.js.map +1 -1
  73. package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.d.ts +28 -0
  74. package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.d.ts.map +1 -0
  75. package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.js +90 -0
  76. package/dist/esm/billing/batches/billing-reconciliation.batch.backend.service.js.map +1 -0
  77. package/dist/esm/billing/batches/usage-flush.batch.backend.service.d.ts +44 -0
  78. package/dist/esm/billing/batches/usage-flush.batch.backend.service.d.ts.map +1 -0
  79. package/dist/esm/billing/batches/usage-flush.batch.backend.service.js +99 -0
  80. package/dist/esm/billing/batches/usage-flush.batch.backend.service.js.map +1 -0
  81. package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.d.ts +91 -0
  82. package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.d.ts.map +1 -0
  83. package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.js +152 -0
  84. package/dist/esm/billing/models/billing-provider-event-settlement.backend.schemas.js.map +1 -0
  85. package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.d.ts +186 -0
  86. package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.d.ts.map +1 -0
  87. package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.js +474 -0
  88. package/dist/esm/billing/services/back-office/billing-reconciliation.backend.service.js.map +1 -0
  89. package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.d.ts +100 -0
  90. package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.d.ts.map +1 -1
  91. package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.js +209 -6
  92. package/dist/esm/billing/services/back-office/product-catalog-sync.backend.service.js.map +1 -1
  93. package/dist/esm/billing/services/back-office/usage-metering.backend.service.d.ts +200 -4
  94. package/dist/esm/billing/services/back-office/usage-metering.backend.service.d.ts.map +1 -1
  95. package/dist/esm/billing/services/back-office/usage-metering.backend.service.js +593 -64
  96. package/dist/esm/billing/services/back-office/usage-metering.backend.service.js.map +1 -1
  97. package/dist/esm/billing/services/billing-adapter-registry.backend.d.ts +36 -0
  98. package/dist/esm/billing/services/billing-adapter-registry.backend.d.ts.map +1 -0
  99. package/dist/esm/billing/services/billing-adapter-registry.backend.js +83 -0
  100. package/dist/esm/billing/services/billing-adapter-registry.backend.js.map +1 -0
  101. package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.d.ts +9 -0
  102. package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.d.ts.map +1 -1
  103. package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.js +11 -1
  104. package/dist/esm/billing/services/billing-checkout-metadata.backend.utils.js.map +1 -1
  105. package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.d.ts.map +1 -1
  106. package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.js +48 -7
  107. package/dist/esm/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.js.map +1 -1
  108. package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.d.ts +38 -1
  109. package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.d.ts.map +1 -1
  110. package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.js +67 -2
  111. package/dist/esm/billing/services/custom-impl/billing-custom-impl-utils.backend.js.map +1 -1
  112. package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.d.ts +30 -1
  113. package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.d.ts.map +1 -1
  114. package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.js +43 -1
  115. package/dist/esm/billing/services/custom-impl/billing-custom-implementations.backend.js.map +1 -1
  116. package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.d.ts +11 -3
  117. package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.d.ts.map +1 -1
  118. package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.js +30 -16
  119. package/dist/esm/billing/services/custom-impl/promotion.custom-ops.custom-impl.backend.service.js.map +1 -1
  120. package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.d.ts.map +1 -1
  121. package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.js +104 -25
  122. package/dist/esm/billing/services/custom-impl/subscription.mutations.custom-impl.backend.service.js.map +1 -1
  123. package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.d.ts +18 -1
  124. package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.d.ts.map +1 -1
  125. package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.js +106 -2
  126. package/dist/esm/billing/services/stripe-standard-billing-provider.backend.service.js.map +1 -1
  127. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.d.ts +52 -0
  128. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.d.ts.map +1 -0
  129. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js +74 -0
  130. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js.map +1 -0
  131. package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.d.ts +104 -11
  132. package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.d.ts.map +1 -1
  133. package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.js +260 -26
  134. package/dist/esm/billing/services/webhooks/billing-webhook-event-router.backend.service.js.map +1 -1
  135. package/dist/esm/billing/testing/mock-billing-provider.d.ts +30 -1
  136. package/dist/esm/billing/testing/mock-billing-provider.d.ts.map +1 -1
  137. package/dist/esm/billing/testing/mock-billing-provider.js +25 -0
  138. package/dist/esm/billing/testing/mock-billing-provider.js.map +1 -1
  139. package/dist/esm/compliance/audit-trails/batches/audit-logs-archive.batch.backend.service.js +11 -4
  140. package/dist/esm/compliance/audit-trails/batches/audit-logs-archive.batch.backend.service.js.map +1 -1
  141. package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.d.ts +225 -13
  142. package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.d.ts.map +1 -1
  143. package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.js +340 -62
  144. package/dist/esm/compliance/audit-trails/services/audit-event-dispatcher.backend.service.js.map +1 -1
  145. package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.d.ts +244 -7
  146. package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.d.ts.map +1 -1
  147. package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.js +386 -5
  148. package/dist/esm/compliance/audit-trails/services/audit-logs.backend.service.js.map +1 -1
  149. package/dist/esm/compliance/audit-trails/services/composite-audit-log-sink.backend.d.ts.map +1 -1
  150. package/dist/esm/compliance/audit-trails/services/composite-audit-log-sink.backend.js +7 -1
  151. package/dist/esm/compliance/audit-trails/services/composite-audit-log-sink.backend.js.map +1 -1
  152. package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.d.ts +6 -2
  153. package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.d.ts.map +1 -1
  154. package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.js +31 -9
  155. package/dist/esm/compliance/audit-trails/services/siem-export-config-cache-invalidation.custom-impl.backend.service.js.map +1 -1
  156. package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.d.ts +42 -0
  157. package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.d.ts.map +1 -1
  158. package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.js +57 -1
  159. package/dist/esm/compliance/audit-trails/services/siem-webhook-delivery.backend.service.js.map +1 -1
  160. package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.d.ts +110 -0
  161. package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.d.ts.map +1 -0
  162. package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.js +192 -0
  163. package/dist/esm/compliance/audit-trails/services/utils/leased-value-cache.backend.utils.js.map +1 -0
  164. package/dist/esm/compliance/audit-trails/services/utils/ocsf-activity-mapping.backend.utils.d.ts.map +1 -1
  165. package/dist/esm/compliance/audit-trails/services/utils/ocsf-activity-mapping.backend.utils.js +31 -0
  166. package/dist/esm/compliance/audit-trails/services/utils/ocsf-activity-mapping.backend.utils.js.map +1 -1
  167. package/dist/esm/config/bootstrap/application-runtime-profile.backend.d.ts +5 -0
  168. package/dist/esm/config/bootstrap/application-runtime-profile.backend.d.ts.map +1 -1
  169. package/dist/esm/config/bootstrap/application-runtime-profile.backend.js +6 -0
  170. package/dist/esm/config/bootstrap/application-runtime-profile.backend.js.map +1 -1
  171. package/dist/esm/config/models/app-config.backend.schemas.d.ts +142 -46
  172. package/dist/esm/config/models/app-config.backend.schemas.d.ts.map +1 -1
  173. package/dist/esm/config/models/app-config.backend.schemas.js +121 -12
  174. package/dist/esm/config/models/app-config.backend.schemas.js.map +1 -1
  175. package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.d.ts +38 -15
  176. package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.d.ts.map +1 -1
  177. package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.js +17 -2
  178. package/dist/esm/config/models/provider-runtime-artifact.backend.schemas.js.map +1 -1
  179. package/dist/esm/config/services/app-configuration-loader.backend.service.d.ts +0 -1
  180. package/dist/esm/config/services/app-configuration-loader.backend.service.d.ts.map +1 -1
  181. package/dist/esm/config/services/app-configuration-loader.backend.service.js +68 -76
  182. package/dist/esm/config/services/app-configuration-loader.backend.service.js.map +1 -1
  183. package/dist/esm/config/services/app-configuration.backend.service.d.ts.map +1 -1
  184. package/dist/esm/config/services/app-configuration.backend.service.js +23 -1
  185. package/dist/esm/config/services/app-configuration.backend.service.js.map +1 -1
  186. package/dist/esm/config/services/app-configuration.backend.utils.d.ts +33 -0
  187. package/dist/esm/config/services/app-configuration.backend.utils.d.ts.map +1 -1
  188. package/dist/esm/config/services/app-configuration.backend.utils.js +39 -1
  189. package/dist/esm/config/services/app-configuration.backend.utils.js.map +1 -1
  190. package/dist/esm/config/services/application-startup-config-validator.backend.service.d.ts +25 -0
  191. package/dist/esm/config/services/application-startup-config-validator.backend.service.d.ts.map +1 -1
  192. package/dist/esm/config/services/application-startup-config-validator.backend.service.js +41 -1
  193. package/dist/esm/config/services/application-startup-config-validator.backend.service.js.map +1 -1
  194. package/dist/esm/databases/services/postgresql-schema-plan-diff.backend.d.ts.map +1 -1
  195. package/dist/esm/databases/services/postgresql-schema-plan-diff.backend.js +48 -0
  196. package/dist/esm/databases/services/postgresql-schema-plan-diff.backend.js.map +1 -1
  197. package/dist/esm/errors/services/error-builder.backend.service.d.ts +13 -1
  198. package/dist/esm/errors/services/error-builder.backend.service.d.ts.map +1 -1
  199. package/dist/esm/errors/services/error-builder.backend.service.js +13 -1
  200. package/dist/esm/errors/services/error-builder.backend.service.js.map +1 -1
  201. package/dist/esm/errors/services/error-handler.backend.service.d.ts +70 -7
  202. package/dist/esm/errors/services/error-handler.backend.service.d.ts.map +1 -1
  203. package/dist/esm/errors/services/error-handler.backend.service.js +129 -8
  204. package/dist/esm/errors/services/error-handler.backend.service.js.map +1 -1
  205. package/dist/esm/errors/services/rate-limit.backend.service.d.ts +66 -0
  206. package/dist/esm/errors/services/rate-limit.backend.service.d.ts.map +1 -1
  207. package/dist/esm/errors/services/rate-limit.backend.service.js +102 -25
  208. package/dist/esm/errors/services/rate-limit.backend.service.js.map +1 -1
  209. package/dist/esm/errors/utils/error-log-level-classification.backend.utils.d.ts +5 -0
  210. package/dist/esm/errors/utils/error-log-level-classification.backend.utils.d.ts.map +1 -1
  211. package/dist/esm/errors/utils/error-log-level-classification.backend.utils.js +25 -0
  212. package/dist/esm/errors/utils/error-log-level-classification.backend.utils.js.map +1 -1
  213. package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.d.ts +33 -0
  214. package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.d.ts.map +1 -1
  215. package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.js +40 -0
  216. package/dist/esm/errors/utils/rate-limit-environment-relaxation.backend.utils.js.map +1 -1
  217. package/dist/esm/external-data/external-data-pipeline-run.backend.service.d.ts +59 -2
  218. package/dist/esm/external-data/external-data-pipeline-run.backend.service.d.ts.map +1 -1
  219. package/dist/esm/external-data/external-data-pipeline-run.backend.service.js +52 -17
  220. package/dist/esm/external-data/external-data-pipeline-run.backend.service.js.map +1 -1
  221. package/dist/esm/external-providers/models/provider-selection-resolution-evidence.backend.definitions.d.ts +4 -2
  222. package/dist/esm/external-providers/models/provider-selection-resolution-evidence.backend.definitions.d.ts.map +1 -1
  223. package/dist/esm/external-providers/models/provider-selection-resolution-evidence.backend.definitions.js.map +1 -1
  224. package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.d.ts +256 -0
  225. package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.d.ts.map +1 -0
  226. package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.js +333 -0
  227. package/dist/esm/external-providers/operations/provider-operation-executor.backend.service.js.map +1 -0
  228. package/dist/esm/external-providers/operations/provider-operation-request.backend.d.ts +56 -0
  229. package/dist/esm/external-providers/operations/provider-operation-request.backend.d.ts.map +1 -0
  230. package/dist/esm/external-providers/operations/provider-operation-request.backend.js +211 -0
  231. package/dist/esm/external-providers/operations/provider-operation-request.backend.js.map +1 -0
  232. package/dist/esm/external-providers/operations/provider-request-signing.backend.d.ts +45 -0
  233. package/dist/esm/external-providers/operations/provider-request-signing.backend.d.ts.map +1 -0
  234. package/dist/esm/external-providers/operations/provider-request-signing.backend.js +216 -0
  235. package/dist/esm/external-providers/operations/provider-request-signing.backend.js.map +1 -0
  236. package/dist/esm/external-providers/operations/provider-rest-call-client.backend.d.ts +56 -0
  237. package/dist/esm/external-providers/operations/provider-rest-call-client.backend.d.ts.map +1 -0
  238. package/dist/esm/external-providers/operations/provider-rest-call-client.backend.js +78 -0
  239. package/dist/esm/external-providers/operations/provider-rest-call-client.backend.js.map +1 -0
  240. package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.d.ts +1 -1
  241. package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.d.ts.map +1 -1
  242. package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.js +2 -2
  243. package/dist/esm/external-providers/services/__tests__/mock-external-providers-registry.service.js.map +1 -1
  244. package/dist/esm/external-providers/services/backend-provider-loader.backend.service.d.ts +89 -0
  245. package/dist/esm/external-providers/services/backend-provider-loader.backend.service.d.ts.map +1 -0
  246. package/dist/esm/external-providers/services/backend-provider-loader.backend.service.js +164 -0
  247. package/dist/esm/external-providers/services/backend-provider-loader.backend.service.js.map +1 -0
  248. package/dist/esm/external-providers/services/backend-provider-registry.backend.service.d.ts +26 -27
  249. package/dist/esm/external-providers/services/backend-provider-registry.backend.service.d.ts.map +1 -1
  250. package/dist/esm/external-providers/services/backend-provider-registry.backend.service.js +50 -64
  251. package/dist/esm/external-providers/services/backend-provider-registry.backend.service.js.map +1 -1
  252. package/dist/esm/external-providers/services/document-extraction.backend.service.d.ts.map +1 -1
  253. package/dist/esm/external-providers/services/document-extraction.backend.service.js +3 -3
  254. package/dist/esm/external-providers/services/document-extraction.backend.service.js.map +1 -1
  255. package/dist/esm/external-providers/services/embeddings.backend.service.d.ts.map +1 -1
  256. package/dist/esm/external-providers/services/embeddings.backend.service.js +4 -4
  257. package/dist/esm/external-providers/services/embeddings.backend.service.js.map +1 -1
  258. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +292 -7
  259. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -1
  260. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +533 -45
  261. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
  262. package/dist/esm/external-providers/services/frontend-bootstrap.backend.service.d.ts.map +1 -1
  263. package/dist/esm/external-providers/services/frontend-bootstrap.backend.service.js +25 -2
  264. package/dist/esm/external-providers/services/frontend-bootstrap.backend.service.js.map +1 -1
  265. package/dist/esm/files/controllers/file.controller.d.ts.map +1 -1
  266. package/dist/esm/files/controllers/file.controller.js +21 -13
  267. package/dist/esm/files/controllers/file.controller.js.map +1 -1
  268. package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.d.ts.map +1 -1
  269. package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.js +39 -15
  270. package/dist/esm/files/handlers/resource-file-upload-handler.backend.service.js.map +1 -1
  271. package/dist/esm/files/services/file-scanning.backend.service.d.ts +94 -9
  272. package/dist/esm/files/services/file-scanning.backend.service.d.ts.map +1 -1
  273. package/dist/esm/files/services/file-scanning.backend.service.js +197 -17
  274. package/dist/esm/files/services/file-scanning.backend.service.js.map +1 -1
  275. package/dist/esm/files/services/file-text-extraction.backend.service.d.ts +60 -1
  276. package/dist/esm/files/services/file-text-extraction.backend.service.d.ts.map +1 -1
  277. package/dist/esm/files/services/file-text-extraction.backend.service.js +167 -8
  278. package/dist/esm/files/services/file-text-extraction.backend.service.js.map +1 -1
  279. package/dist/esm/files/services/file-upload-grant.backend.service.d.ts +53 -2
  280. package/dist/esm/files/services/file-upload-grant.backend.service.d.ts.map +1 -1
  281. package/dist/esm/files/services/file-upload-grant.backend.service.js +127 -3
  282. package/dist/esm/files/services/file-upload-grant.backend.service.js.map +1 -1
  283. package/dist/esm/files/services/files.backend.service.d.ts +68 -0
  284. package/dist/esm/files/services/files.backend.service.d.ts.map +1 -1
  285. package/dist/esm/files/services/files.backend.service.js +175 -5
  286. package/dist/esm/files/services/files.backend.service.js.map +1 -1
  287. package/dist/esm/files/storage/application-storage-key.backend.utils.d.ts +109 -0
  288. package/dist/esm/files/storage/application-storage-key.backend.utils.d.ts.map +1 -0
  289. package/dist/esm/files/storage/application-storage-key.backend.utils.js +123 -0
  290. package/dist/esm/files/storage/application-storage-key.backend.utils.js.map +1 -0
  291. package/dist/esm/files/storage/file-storage-provider.types.d.ts +16 -10
  292. package/dist/esm/files/storage/file-storage-provider.types.d.ts.map +1 -1
  293. package/dist/esm/files/storage/file-storage-provider.types.js.map +1 -1
  294. package/dist/esm/files/storage/local-directory-storage-provider.backend.service.d.ts +67 -8
  295. package/dist/esm/files/storage/local-directory-storage-provider.backend.service.d.ts.map +1 -1
  296. package/dist/esm/files/storage/local-directory-storage-provider.backend.service.js +101 -28
  297. package/dist/esm/files/storage/local-directory-storage-provider.backend.service.js.map +1 -1
  298. package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.d.ts.map +1 -1
  299. package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.js +8 -55
  300. package/dist/esm/files/storage/wildo-managed-storage-provider.backend.service.js.map +1 -1
  301. package/dist/esm/files/utils/file-field-schema-path.backend.utils.d.ts.map +1 -1
  302. package/dist/esm/files/utils/file-field-schema-path.backend.utils.js +20 -0
  303. package/dist/esm/files/utils/file-field-schema-path.backend.utils.js.map +1 -1
  304. package/dist/esm/files/utils/office-document-text-extraction.backend.utils.d.ts +86 -0
  305. package/dist/esm/files/utils/office-document-text-extraction.backend.utils.d.ts.map +1 -0
  306. package/dist/esm/files/utils/office-document-text-extraction.backend.utils.js +288 -0
  307. package/dist/esm/files/utils/office-document-text-extraction.backend.utils.js.map +1 -0
  308. package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.d.ts +15 -0
  309. package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.d.ts.map +1 -1
  310. package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.js +76 -5
  311. package/dist/esm/flows-actors/a2a/batches/a2a-abandoned-task-sweep.batch.backend.service.js.map +1 -1
  312. package/dist/esm/flows-actors/a2a/controllers/a2a.controller.d.ts.map +1 -1
  313. package/dist/esm/flows-actors/a2a/controllers/a2a.controller.js +6 -1
  314. package/dist/esm/flows-actors/a2a/controllers/a2a.controller.js.map +1 -1
  315. package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.d.ts +60 -0
  316. package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.d.ts.map +1 -1
  317. package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.js +63 -0
  318. package/dist/esm/flows-actors/a2a/models/a2a.backend.schemas.js.map +1 -1
  319. package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.d.ts +74 -0
  320. package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.d.ts.map +1 -1
  321. package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.js +196 -40
  322. package/dist/esm/flows-actors/a2a/services/a2a-task-cancellation.backend.service.js.map +1 -1
  323. package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.d.ts +7 -1
  324. package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.d.ts.map +1 -1
  325. package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.js +53 -1
  326. package/dist/esm/flows-actors/a2a/services/a2a-task.backend.service.js.map +1 -1
  327. package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.d.ts +18 -0
  328. package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.d.ts.map +1 -1
  329. package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.js +18 -0
  330. package/dist/esm/flows-actors/a2a/services/a2a-token-budget.backend.service.js.map +1 -1
  331. package/dist/esm/flows-actors/a2a/services/a2a.backend.service.d.ts +12 -7
  332. package/dist/esm/flows-actors/a2a/services/a2a.backend.service.d.ts.map +1 -1
  333. package/dist/esm/flows-actors/a2a/services/a2a.backend.service.js.map +1 -1
  334. package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.d.ts +0 -13
  335. package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.d.ts.map +1 -1
  336. package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.js +14 -22
  337. package/dist/esm/flows-actors/models/agent-catalogs.backend.definitions.js.map +1 -1
  338. package/dist/esm/flows-actors/models/core-facets.backend.definitions.d.ts +8 -3
  339. package/dist/esm/flows-actors/models/core-facets.backend.definitions.d.ts.map +1 -1
  340. package/dist/esm/flows-actors/models/core-facets.backend.definitions.js +25 -15
  341. package/dist/esm/flows-actors/models/core-facets.backend.definitions.js.map +1 -1
  342. package/dist/esm/flows-actors/models/flows-actors.backend.schemas.d.ts +13 -1
  343. package/dist/esm/flows-actors/models/flows-actors.backend.schemas.d.ts.map +1 -1
  344. package/dist/esm/flows-actors/models/flows-actors.backend.schemas.js.map +1 -1
  345. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts +88 -8
  346. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts.map +1 -1
  347. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js +333 -31
  348. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js.map +1 -1
  349. package/dist/esm/flows-actors/models/market-generation.actors-system.backend.definitions.d.ts.map +1 -1
  350. package/dist/esm/flows-actors/models/market-generation.actors-system.backend.definitions.js +4 -2
  351. package/dist/esm/flows-actors/models/market-generation.actors-system.backend.definitions.js.map +1 -1
  352. package/dist/esm/flows-actors/models/mcp-client.backend.definitions.d.ts +113 -0
  353. package/dist/esm/flows-actors/models/mcp-client.backend.definitions.d.ts.map +1 -0
  354. package/dist/esm/flows-actors/models/mcp-client.backend.definitions.js +62 -0
  355. package/dist/esm/flows-actors/models/mcp-client.backend.definitions.js.map +1 -0
  356. package/dist/esm/flows-actors/services/actors-system.backend.service.d.ts.map +1 -1
  357. package/dist/esm/flows-actors/services/actors-system.backend.service.js +0 -2
  358. package/dist/esm/flows-actors/services/actors-system.backend.service.js.map +1 -1
  359. package/dist/esm/flows-actors/services/agents.backend.service.d.ts +28 -1
  360. package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
  361. package/dist/esm/flows-actors/services/agents.backend.service.js +204 -18
  362. package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
  363. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts +5 -1
  364. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts.map +1 -1
  365. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js +79 -16
  366. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js.map +1 -1
  367. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts +34 -5
  368. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts.map +1 -1
  369. package/dist/esm/flows-actors/services/flows-actors-registry.service.js +154 -20
  370. package/dist/esm/flows-actors/services/flows-actors-registry.service.js.map +1 -1
  371. package/dist/esm/flows-actors/services/flows.backend.services.d.ts.map +1 -1
  372. package/dist/esm/flows-actors/services/flows.backend.services.js +27 -23
  373. package/dist/esm/flows-actors/services/flows.backend.services.js.map +1 -1
  374. package/dist/esm/flows-actors/services/llm-observability-agent-call-trace-sink.backend.d.ts.map +1 -1
  375. package/dist/esm/flows-actors/services/llm-observability-agent-call-trace-sink.backend.js +7 -1
  376. package/dist/esm/flows-actors/services/llm-observability-agent-call-trace-sink.backend.js.map +1 -1
  377. package/dist/esm/flows-actors/services/mcp-client.backend.service.d.ts +90 -0
  378. package/dist/esm/flows-actors/services/mcp-client.backend.service.d.ts.map +1 -0
  379. package/dist/esm/flows-actors/services/mcp-client.backend.service.js +368 -0
  380. package/dist/esm/flows-actors/services/mcp-client.backend.service.js.map +1 -0
  381. package/dist/esm/flows-actors/services/prompt-compiler.backend.service.d.ts +9 -5
  382. package/dist/esm/flows-actors/services/prompt-compiler.backend.service.d.ts.map +1 -1
  383. package/dist/esm/flows-actors/services/prompt-compiler.backend.service.js +12 -17
  384. package/dist/esm/flows-actors/services/prompt-compiler.backend.service.js.map +1 -1
  385. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts.map +1 -1
  386. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js +8 -4
  387. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
  388. package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.d.ts +0 -207
  389. package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.d.ts.map +1 -1
  390. package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.js +8 -243
  391. package/dist/esm/flows-actors/utils/meta-workflow-canonical-json.backend.utils.js.map +1 -1
  392. package/dist/esm/flows-actors/utils/meta-workflow-structured-generation-plan.backend.utils.d.ts.map +1 -1
  393. package/dist/esm/flows-actors/utils/meta-workflow-structured-generation-plan.backend.utils.js.map +1 -1
  394. package/dist/esm/guidance/services/milestone-evaluator.backend.service.d.ts +9 -14
  395. package/dist/esm/guidance/services/milestone-evaluator.backend.service.d.ts.map +1 -1
  396. package/dist/esm/guidance/services/milestone-evaluator.backend.service.js +18 -89
  397. package/dist/esm/guidance/services/milestone-evaluator.backend.service.js.map +1 -1
  398. package/dist/esm/guidance/services/progression-state-store.backend.service.d.ts +86 -0
  399. package/dist/esm/guidance/services/progression-state-store.backend.service.d.ts.map +1 -0
  400. package/dist/esm/guidance/services/progression-state-store.backend.service.js +155 -0
  401. package/dist/esm/guidance/services/progression-state-store.backend.service.js.map +1 -0
  402. package/dist/esm/i18n/controllers/i18n-controller.backend.service.d.ts +10 -0
  403. package/dist/esm/i18n/controllers/i18n-controller.backend.service.d.ts.map +1 -1
  404. package/dist/esm/i18n/controllers/i18n-controller.backend.service.js +55 -5
  405. package/dist/esm/i18n/controllers/i18n-controller.backend.service.js.map +1 -1
  406. package/dist/esm/index.d.ts +11 -4
  407. package/dist/esm/index.d.ts.map +1 -1
  408. package/dist/esm/index.js +31 -4
  409. package/dist/esm/index.js.map +1 -1
  410. package/dist/esm/inject/models/container.d.ts.map +1 -1
  411. package/dist/esm/inject/models/container.js +78 -10
  412. package/dist/esm/inject/models/container.js.map +1 -1
  413. package/dist/esm/inject/models/service-types.d.ts +17 -3
  414. package/dist/esm/inject/models/service-types.d.ts.map +1 -1
  415. package/dist/esm/inject/models/service-types.js +19 -3
  416. package/dist/esm/inject/models/service-types.js.map +1 -1
  417. package/dist/esm/mcp/controllers/mcp.controller.d.ts.map +1 -1
  418. package/dist/esm/mcp/controllers/mcp.controller.js +20 -0
  419. package/dist/esm/mcp/controllers/mcp.controller.js.map +1 -1
  420. package/dist/esm/mcp/services/mcp-server.backend.service.d.ts +56 -1
  421. package/dist/esm/mcp/services/mcp-server.backend.service.d.ts.map +1 -1
  422. package/dist/esm/mcp/services/mcp-server.backend.service.js +107 -11
  423. package/dist/esm/mcp/services/mcp-server.backend.service.js.map +1 -1
  424. package/dist/esm/mcp/services/mcp-tool-adapter.backend.service.d.ts.map +1 -1
  425. package/dist/esm/mcp/services/mcp-tool-adapter.backend.service.js +22 -0
  426. package/dist/esm/mcp/services/mcp-tool-adapter.backend.service.js.map +1 -1
  427. package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.d.ts.map +1 -1
  428. package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.js +49 -4
  429. package/dist/esm/monitoring/analytics/controllers/analytics.backend.controller.js.map +1 -1
  430. package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.d.ts +66 -0
  431. package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.d.ts.map +1 -0
  432. package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.js +199 -0
  433. package/dist/esm/monitoring/analytics/services/value-moment-definition-registry.backend.service.js.map +1 -0
  434. package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.d.ts +149 -13
  435. package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.d.ts.map +1 -1
  436. package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.js +411 -19
  437. package/dist/esm/monitoring/analytics/services/value-moment-engine.backend.service.js.map +1 -1
  438. package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.d.ts +11 -2
  439. package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.d.ts.map +1 -1
  440. package/dist/esm/monitoring/analytics/services/value-moment-handler-registry.backend.service.js.map +1 -1
  441. package/dist/esm/monitoring/logger/models/logger.backend.schemas.d.ts +28 -9
  442. package/dist/esm/monitoring/logger/models/logger.backend.schemas.d.ts.map +1 -1
  443. package/dist/esm/monitoring/logger/models/logger.backend.schemas.js +30 -10
  444. package/dist/esm/monitoring/logger/models/logger.backend.schemas.js.map +1 -1
  445. package/dist/esm/monitoring/logger/services/logger.service.d.ts +12 -0
  446. package/dist/esm/monitoring/logger/services/logger.service.d.ts.map +1 -1
  447. package/dist/esm/monitoring/logger/services/logger.service.js +52 -11
  448. package/dist/esm/monitoring/logger/services/logger.service.js.map +1 -1
  449. package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.d.ts +62 -0
  450. package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.d.ts.map +1 -0
  451. package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.js +78 -0
  452. package/dist/esm/monitoring/logger/utils/log-severity-floor.backend.utils.js.map +1 -0
  453. package/dist/esm/monitoring/observability/audit-observation-emission.backend.d.ts +309 -0
  454. package/dist/esm/monitoring/observability/audit-observation-emission.backend.d.ts.map +1 -0
  455. package/dist/esm/monitoring/observability/audit-observation-emission.backend.js +385 -0
  456. package/dist/esm/monitoring/observability/audit-observation-emission.backend.js.map +1 -0
  457. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts +1 -0
  458. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts.map +1 -1
  459. package/dist/esm/monitoring/observability/models/observability.backend.schemas.js.map +1 -1
  460. package/dist/esm/monitoring/observability/services/metrics.service.d.ts +21 -0
  461. package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -1
  462. package/dist/esm/monitoring/observability/services/metrics.service.js +38 -0
  463. package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -1
  464. package/dist/esm/notifications/email/models/email-context-provider.interface.d.ts +0 -80
  465. package/dist/esm/notifications/email/models/email-context-provider.interface.d.ts.map +0 -1
  466. package/dist/esm/notifications/email/models/email-context-provider.interface.js +0 -25
  467. package/dist/esm/notifications/email/models/email-context-provider.interface.js.map +0 -1
  468. package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.d.ts +0 -49
  469. package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.d.ts.map +0 -1
  470. package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.js +0 -141
  471. package/dist/esm/notifications/email/services/email-context-provider-registry.backend.service.js.map +0 -1
  472. package/dist/esm/notifications/email/services/email-template-compiler.backend.service.d.ts +0 -37
  473. package/dist/esm/notifications/email/services/email-template-compiler.backend.service.d.ts.map +0 -1
  474. package/dist/esm/notifications/email/services/email-template-compiler.backend.service.js +0 -121
  475. package/dist/esm/notifications/email/services/email-template-compiler.backend.service.js.map +0 -1
  476. package/dist/esm/notifications/email/services/email-template-registry.backend.service.d.ts +66 -1
  477. package/dist/esm/notifications/email/services/email-template-registry.backend.service.d.ts.map +1 -1
  478. package/dist/esm/notifications/email/services/email-template-registry.backend.service.js +105 -10
  479. package/dist/esm/notifications/email/services/email-template-registry.backend.service.js.map +1 -1
  480. package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.d.ts +0 -58
  481. package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.d.ts.map +0 -1
  482. package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.js +0 -223
  483. package/dist/esm/notifications/email/services/email-template-sandbox.backend.service.js.map +0 -1
  484. package/dist/esm/notifications/email/services/email-template-validator.backend.service.d.ts.map +1 -1
  485. package/dist/esm/notifications/email/services/email-template-validator.backend.service.js +10 -1
  486. package/dist/esm/notifications/email/services/email-template-validator.backend.service.js.map +1 -1
  487. package/dist/esm/notifications/email/services/email.backend.service.d.ts +60 -4
  488. package/dist/esm/notifications/email/services/email.backend.service.d.ts.map +1 -1
  489. package/dist/esm/notifications/email/services/email.backend.service.js +145 -43
  490. package/dist/esm/notifications/email/services/email.backend.service.js.map +1 -1
  491. package/dist/esm/notifications/email/utils/color-conversion.utils.d.ts +0 -1
  492. package/dist/esm/notifications/email/utils/color-conversion.utils.d.ts.map +1 -1
  493. package/dist/esm/notifications/email/utils/color-conversion.utils.js.map +1 -1
  494. package/dist/esm/notifications/services/notification-badge.backend.service.d.ts +142 -21
  495. package/dist/esm/notifications/services/notification-badge.backend.service.d.ts.map +1 -1
  496. package/dist/esm/notifications/services/notification-badge.backend.service.js +283 -58
  497. package/dist/esm/notifications/services/notification-badge.backend.service.js.map +1 -1
  498. package/dist/esm/notifications/services/notifications-dispatcher.backend.service.d.ts +99 -13
  499. package/dist/esm/notifications/services/notifications-dispatcher.backend.service.d.ts.map +1 -1
  500. package/dist/esm/notifications/services/notifications-dispatcher.backend.service.js +422 -66
  501. package/dist/esm/notifications/services/notifications-dispatcher.backend.service.js.map +1 -1
  502. package/dist/esm/notifications/sms/services/sms.backend.service.d.ts +2 -2
  503. package/dist/esm/notifications/sms/services/sms.backend.service.d.ts.map +1 -1
  504. package/dist/esm/notifications/sms/services/sms.backend.service.js +5 -5
  505. package/dist/esm/notifications/sms/services/sms.backend.service.js.map +1 -1
  506. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts +117 -5
  507. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts.map +1 -1
  508. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js +164 -6
  509. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js.map +1 -1
  510. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.d.ts +0 -6
  511. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.d.ts.map +1 -1
  512. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.js +46 -1
  513. package/dist/esm/notifications/webhooks/outbound/batches/m2m-webhook-delivery.batch.backend.service.js.map +1 -1
  514. package/dist/esm/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.d.ts.map +1 -1
  515. package/dist/esm/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.js +16 -6
  516. package/dist/esm/notifications/webhooks/outbound/m2m-webhook-signed-request.backend.utils.js.map +1 -1
  517. package/dist/esm/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.d.ts.map +1 -1
  518. package/dist/esm/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.js +12 -12
  519. package/dist/esm/notifications/webhooks/outbound/services/webhook-config-test-endpoint.custom-impl.backend.service.js.map +1 -1
  520. package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.d.ts +16 -0
  521. package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.d.ts.map +1 -1
  522. package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.js +18 -0
  523. package/dist/esm/notifications/webhooks/services/webhook-handler.backend.service.js.map +1 -1
  524. package/dist/esm/organizations/batches/organization-purge.batch.backend.service.d.ts +2 -2
  525. package/dist/esm/organizations/batches/organization-purge.batch.backend.service.js +2 -2
  526. package/dist/esm/organizations/batches/organization-purge.batch.backend.service.js.map +1 -1
  527. package/dist/esm/organizations/services/organization-custom-implementation.backend.service.d.ts.map +1 -1
  528. package/dist/esm/organizations/services/organization-custom-implementation.backend.service.js +63 -2
  529. package/dist/esm/organizations/services/organization-custom-implementation.backend.service.js.map +1 -1
  530. package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.d.ts +66 -0
  531. package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.d.ts.map +1 -0
  532. package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.js +257 -0
  533. package/dist/esm/queue/adapters/in-memory-queue-adapter.backend.service.js.map +1 -0
  534. package/dist/esm/queue/adapters/queue-adapter.backend.binding.d.ts +12 -0
  535. package/dist/esm/queue/adapters/queue-adapter.backend.binding.d.ts.map +1 -0
  536. package/dist/esm/queue/adapters/queue-adapter.backend.binding.js +47 -0
  537. package/dist/esm/queue/adapters/queue-adapter.backend.binding.js.map +1 -0
  538. package/dist/esm/queue/adapters/queue-adapter.backend.interface.d.ts +87 -0
  539. package/dist/esm/queue/adapters/queue-adapter.backend.interface.d.ts.map +1 -0
  540. package/dist/esm/queue/adapters/queue-adapter.backend.interface.js +1 -0
  541. package/dist/esm/queue/adapters/queue-adapter.backend.interface.js.map +1 -0
  542. package/dist/esm/queue/adapters/queue-adapter.backend.options.d.ts +31 -0
  543. package/dist/esm/queue/adapters/queue-adapter.backend.options.d.ts.map +1 -0
  544. package/dist/esm/queue/adapters/queue-adapter.backend.options.js +13 -0
  545. package/dist/esm/queue/adapters/queue-adapter.backend.options.js.map +1 -0
  546. package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.d.ts +19 -25
  547. package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.d.ts.map +1 -1
  548. package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.js +33 -0
  549. package/dist/esm/queue/adapters/rabbitmq-adapter.backend.service.js.map +1 -1
  550. package/dist/esm/queue/domain-queue-consumer.backend.service.d.ts +2 -2
  551. package/dist/esm/queue/domain-queue-consumer.backend.service.d.ts.map +1 -1
  552. package/dist/esm/queue/domain-queue-consumer.backend.service.js +1 -4
  553. package/dist/esm/queue/domain-queue-consumer.backend.service.js.map +1 -1
  554. package/dist/esm/queue/job-consumer.backend.service.d.ts +2 -2
  555. package/dist/esm/queue/job-consumer.backend.service.d.ts.map +1 -1
  556. package/dist/esm/queue/job-consumer.backend.service.js +1 -4
  557. package/dist/esm/queue/job-consumer.backend.service.js.map +1 -1
  558. package/dist/esm/queue/job-executor.backend.service.d.ts +2 -2
  559. package/dist/esm/queue/job-executor.backend.service.d.ts.map +1 -1
  560. package/dist/esm/queue/job-executor.backend.service.js +1 -4
  561. package/dist/esm/queue/job-executor.backend.service.js.map +1 -1
  562. package/dist/esm/queue/queue-monitoring.backend.service.d.ts +8 -4
  563. package/dist/esm/queue/queue-monitoring.backend.service.d.ts.map +1 -1
  564. package/dist/esm/queue/queue-monitoring.backend.service.js +25 -17
  565. package/dist/esm/queue/queue-monitoring.backend.service.js.map +1 -1
  566. package/dist/esm/queue/queue-worker-initializer.backend.service.d.ts +16 -1
  567. package/dist/esm/queue/queue-worker-initializer.backend.service.d.ts.map +1 -1
  568. package/dist/esm/queue/queue-worker-initializer.backend.service.js +16 -1
  569. package/dist/esm/queue/queue-worker-initializer.backend.service.js.map +1 -1
  570. package/dist/esm/queue/queue.backend.service.d.ts +3 -3
  571. package/dist/esm/queue/queue.backend.service.d.ts.map +1 -1
  572. package/dist/esm/queue/queue.backend.service.js +26 -4
  573. package/dist/esm/queue/queue.backend.service.js.map +1 -1
  574. package/dist/esm/queue/worker-shutdown-manager.backend.service.d.ts +2 -2
  575. package/dist/esm/queue/worker-shutdown-manager.backend.service.d.ts.map +1 -1
  576. package/dist/esm/queue/worker-shutdown-manager.backend.service.js +18 -3
  577. package/dist/esm/queue/worker-shutdown-manager.backend.service.js.map +1 -1
  578. package/dist/esm/rag/utils/rag-chunking.backend.utils.d.ts +50 -25
  579. package/dist/esm/rag/utils/rag-chunking.backend.utils.d.ts.map +1 -1
  580. package/dist/esm/rag/utils/rag-chunking.backend.utils.js +147 -39
  581. package/dist/esm/rag/utils/rag-chunking.backend.utils.js.map +1 -1
  582. package/dist/esm/rag/utils/rag-context-assembly.backend.utils.d.ts +12 -3
  583. package/dist/esm/rag/utils/rag-context-assembly.backend.utils.d.ts.map +1 -1
  584. package/dist/esm/rag/utils/rag-context-assembly.backend.utils.js +12 -3
  585. package/dist/esm/rag/utils/rag-context-assembly.backend.utils.js.map +1 -1
  586. package/dist/esm/requests/service/websocket.service.d.ts +9 -0
  587. package/dist/esm/requests/service/websocket.service.d.ts.map +1 -1
  588. package/dist/esm/requests/service/websocket.service.js +32 -8
  589. package/dist/esm/requests/service/websocket.service.js.map +1 -1
  590. package/dist/esm/resources/models/custom-service-implementations.backend.definition.d.ts.map +1 -1
  591. package/dist/esm/resources/models/custom-service-implementations.backend.definition.js +14 -2
  592. package/dist/esm/resources/models/custom-service-implementations.backend.definition.js.map +1 -1
  593. package/dist/esm/resources/models/resources-operations.backend.definitions.d.ts.map +1 -1
  594. package/dist/esm/resources/models/resources-operations.backend.definitions.js +2 -0
  595. package/dist/esm/resources/models/resources-operations.backend.definitions.js.map +1 -1
  596. package/dist/esm/resources/models/resources-relationships.backend.definitions.d.ts.map +1 -1
  597. package/dist/esm/resources/models/resources-relationships.backend.definitions.js +14 -0
  598. package/dist/esm/resources/models/resources-relationships.backend.definitions.js.map +1 -1
  599. package/dist/esm/resources/models/resources-types.backend.schemas.d.ts +2 -1
  600. package/dist/esm/resources/models/resources-types.backend.schemas.d.ts.map +1 -1
  601. package/dist/esm/resources/models/resources-types.backend.schemas.js +8 -0
  602. package/dist/esm/resources/models/resources-types.backend.schemas.js.map +1 -1
  603. package/dist/esm/resources/services/resources-registry.backend.service.d.ts +60 -5
  604. package/dist/esm/resources/services/resources-registry.backend.service.d.ts.map +1 -1
  605. package/dist/esm/resources/services/resources-registry.backend.service.js +90 -6
  606. package/dist/esm/resources/services/resources-registry.backend.service.js.map +1 -1
  607. package/dist/esm/runtime/controllers/health-controller.backend.service.d.ts +36 -3
  608. package/dist/esm/runtime/controllers/health-controller.backend.service.d.ts.map +1 -1
  609. package/dist/esm/runtime/controllers/health-controller.backend.service.js +32 -10
  610. package/dist/esm/runtime/controllers/health-controller.backend.service.js.map +1 -1
  611. package/dist/esm/runtime/domain-module.backend.definitions.d.ts +24 -0
  612. package/dist/esm/runtime/domain-module.backend.definitions.d.ts.map +1 -1
  613. package/dist/esm/runtime/domain-module.backend.definitions.js +24 -0
  614. package/dist/esm/runtime/domain-module.backend.definitions.js.map +1 -1
  615. package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.d.ts +51 -0
  616. package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.d.ts.map +1 -1
  617. package/dist/esm/runtime/services/health-readiness-contributor.backend.interface.js.map +1 -1
  618. package/dist/esm/runtime/services/http-server.backend.service.d.ts +26 -0
  619. package/dist/esm/runtime/services/http-server.backend.service.d.ts.map +1 -1
  620. package/dist/esm/runtime/services/http-server.backend.service.js +181 -1
  621. package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -1
  622. package/dist/esm/runtime/services/start-application.backend.service.d.ts +19 -1
  623. package/dist/esm/runtime/services/start-application.backend.service.d.ts.map +1 -1
  624. package/dist/esm/runtime/services/start-application.backend.service.js +261 -77
  625. package/dist/esm/runtime/services/start-application.backend.service.js.map +1 -1
  626. package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.d.ts +15 -0
  627. package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.d.ts.map +1 -1
  628. package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.js +28 -0
  629. package/dist/esm/security/api-keys/api-keys.custom-impl.backend.service.js.map +1 -1
  630. package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.d.ts +5 -1
  631. package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.d.ts.map +1 -1
  632. package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.js +24 -4
  633. package/dist/esm/security/authentications/batches/anonymous-session-cleanup.batch.backend.service.js.map +1 -1
  634. package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.d.ts.map +1 -1
  635. package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.js +29 -4
  636. package/dist/esm/security/authentications/controllers/authentication-controller.backend.service.js.map +1 -1
  637. package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.d.ts +114 -0
  638. package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.d.ts.map +1 -1
  639. package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.js +354 -3
  640. package/dist/esm/security/authentications/controllers/oauth-provider-controller.backend.service.js.map +1 -1
  641. package/dist/esm/security/authentications/models/cimd.backend.schemas.d.ts +1 -0
  642. package/dist/esm/security/authentications/models/cimd.backend.schemas.d.ts.map +1 -1
  643. package/dist/esm/security/authentications/models/cimd.backend.schemas.js +22 -0
  644. package/dist/esm/security/authentications/models/cimd.backend.schemas.js.map +1 -1
  645. package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.d.ts +15 -0
  646. package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.d.ts.map +1 -1
  647. package/dist/esm/security/authentications/models/oauth2-connection.backend.schemas.js.map +1 -1
  648. package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.d.ts +0 -2
  649. package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.d.ts.map +1 -1
  650. package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.js +23 -14
  651. package/dist/esm/security/authentications/services/admin-config/auth-organization-configuration.service.js.map +1 -1
  652. package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.d.ts +0 -1
  653. package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.d.ts.map +1 -1
  654. package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.js +15 -12
  655. package/dist/esm/security/authentications/services/admin-config/domain-to-org-lookup.backend.service.js.map +1 -1
  656. package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.d.ts +113 -3
  657. package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.d.ts.map +1 -1
  658. package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.js +207 -30
  659. package/dist/esm/security/authentications/services/admin-config/domain-verification.backend.service.js.map +1 -1
  660. package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.d.ts +95 -2
  661. package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.d.ts.map +1 -1
  662. package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.js +153 -9
  663. package/dist/esm/security/authentications/services/admin-config/enterprise-user-provisioning.backend.service.js.map +1 -1
  664. package/dist/esm/security/authentications/services/anonymous-session.backend.service.d.ts +190 -0
  665. package/dist/esm/security/authentications/services/anonymous-session.backend.service.d.ts.map +1 -1
  666. package/dist/esm/security/authentications/services/anonymous-session.backend.service.js +377 -53
  667. package/dist/esm/security/authentications/services/anonymous-session.backend.service.js.map +1 -1
  668. package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.d.ts.map +1 -1
  669. package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.js +68 -1
  670. package/dist/esm/security/authentications/services/auth-methods/auth-method-management.backend.service.js.map +1 -1
  671. package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.d.ts +41 -0
  672. package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.d.ts.map +1 -1
  673. package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.js +202 -23
  674. package/dist/esm/security/authentications/services/auth-methods/auth-registration.backend.service.js.map +1 -1
  675. package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.d.ts.map +1 -1
  676. package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.js +42 -1
  677. package/dist/esm/security/authentications/services/auth-methods/oauth2-authentication.backend.service.js.map +1 -1
  678. package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.d.ts.map +1 -1
  679. package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.js +34 -4
  680. package/dist/esm/security/authentications/services/auth-methods/oauth2-connection-resolver.backend.service.js.map +1 -1
  681. package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.d.ts +29 -5
  682. package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.d.ts.map +1 -1
  683. package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.js +77 -5
  684. package/dist/esm/security/authentications/services/auth-methods/webauthn.backend.service.js.map +1 -1
  685. package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.d.ts +17 -1
  686. package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.d.ts.map +1 -1
  687. package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.js +49 -17
  688. package/dist/esm/security/authentications/services/auth-token-issuer.backend.service.js.map +1 -1
  689. package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.d.ts +43 -1
  690. package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.d.ts.map +1 -1
  691. package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.js +277 -97
  692. package/dist/esm/security/authentications/services/authentication-orchestrator.backend.service.js.map +1 -1
  693. package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.d.ts +28 -5
  694. package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.d.ts.map +1 -1
  695. package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.js +72 -12
  696. package/dist/esm/security/authentications/services/cimd-client-metadata.backend.service.js.map +1 -1
  697. package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.d.ts.map +1 -1
  698. package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.js +3 -0
  699. package/dist/esm/security/authentications/services/custom-impls/auth-custom-implementations.backend.js.map +1 -1
  700. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts +28 -0
  701. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts.map +1 -0
  702. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js +283 -0
  703. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js.map +1 -0
  704. package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.d.ts +4 -3
  705. package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.d.ts.map +1 -1
  706. package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.js +4 -3
  707. package/dist/esm/security/authentications/services/custom-impls/sso-config.custom-impl.backend.service.js.map +1 -1
  708. package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.d.ts +35 -0
  709. package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.d.ts.map +1 -1
  710. package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.js +111 -21
  711. package/dist/esm/security/authentications/services/oauth-provider-token.backend.service.js.map +1 -1
  712. package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.d.ts +14 -1
  713. package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.d.ts.map +1 -1
  714. package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.js +49 -8
  715. package/dist/esm/security/authentications/services/oidc-authorization-code.backend.service.js.map +1 -1
  716. package/dist/esm/security/authentications/services/utils/auth-policy-resolution.backend.utils.d.ts.map +1 -1
  717. package/dist/esm/security/authentications/services/utils/auth-policy-resolution.backend.utils.js +4 -0
  718. package/dist/esm/security/authentications/services/utils/auth-policy-resolution.backend.utils.js.map +1 -1
  719. package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.d.ts.map +1 -1
  720. package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.js +6 -0
  721. package/dist/esm/security/authentications/services/utils/auth-user-lookup.backend.service.js.map +1 -1
  722. package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.d.ts +37 -1
  723. package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.d.ts.map +1 -1
  724. package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.js +51 -0
  725. package/dist/esm/security/authentications/services/utils/external-turn-rate-limit.backend.utils.js.map +1 -1
  726. package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.d.ts +41 -0
  727. package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.d.ts.map +1 -1
  728. package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.js +45 -0
  729. package/dist/esm/security/authentications/utils/enterprise-sso-enforcement.backend.utils.js.map +1 -1
  730. package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.d.ts +116 -0
  731. package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.d.ts.map +1 -0
  732. package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.js +162 -0
  733. package/dist/esm/security/authorizations/cross-tenant-read-observation.backend.js.map +1 -0
  734. package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.d.ts +20 -20
  735. package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.d.ts.map +1 -1
  736. package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.js +27 -28
  737. package/dist/esm/security/authorizations/organization-owner-floor.backend.utils.js.map +1 -1
  738. package/dist/esm/security/authorizations/platform-access-grant-custom-implementation.backend.service.d.ts.map +1 -1
  739. package/dist/esm/security/authorizations/platform-access-grant-custom-implementation.backend.service.js +77 -3
  740. package/dist/esm/security/authorizations/platform-access-grant-custom-implementation.backend.service.js.map +1 -1
  741. package/dist/esm/security/authorizations/role-ceiling.backend.utils.d.ts +4 -0
  742. package/dist/esm/security/authorizations/role-ceiling.backend.utils.d.ts.map +1 -1
  743. package/dist/esm/security/authorizations/role-ceiling.backend.utils.js +4 -0
  744. package/dist/esm/security/authorizations/role-ceiling.backend.utils.js.map +1 -1
  745. package/dist/esm/security/authorizations/role-conferral.backend.utils.d.ts +93 -0
  746. package/dist/esm/security/authorizations/role-conferral.backend.utils.d.ts.map +1 -0
  747. package/dist/esm/security/authorizations/role-conferral.backend.utils.js +95 -0
  748. package/dist/esm/security/authorizations/role-conferral.backend.utils.js.map +1 -0
  749. package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.d.ts +124 -1
  750. package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.d.ts.map +1 -1
  751. package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.js +142 -5
  752. package/dist/esm/security/authorizations/scope-root-collection-confinement.backend.js.map +1 -1
  753. package/dist/esm/security/authorizations/services/authorizations.backend.service.d.ts +74 -8
  754. package/dist/esm/security/authorizations/services/authorizations.backend.service.d.ts.map +1 -1
  755. package/dist/esm/security/authorizations/services/authorizations.backend.service.js +175 -19
  756. package/dist/esm/security/authorizations/services/authorizations.backend.service.js.map +1 -1
  757. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts +6 -14
  758. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts.map +1 -1
  759. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js +13 -22
  760. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js.map +1 -1
  761. package/dist/esm/security/connected-accounts/connection-target-authorization.backend.d.ts +60 -0
  762. package/dist/esm/security/connected-accounts/connection-target-authorization.backend.d.ts.map +1 -0
  763. package/dist/esm/security/connected-accounts/connection-target-authorization.backend.js +79 -0
  764. package/dist/esm/security/connected-accounts/connection-target-authorization.backend.js.map +1 -0
  765. package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.d.ts +161 -0
  766. package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.d.ts.map +1 -0
  767. package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.js +512 -0
  768. package/dist/esm/security/connected-accounts/controllers/provider-connection.controller.backend.service.js.map +1 -0
  769. package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.d.ts +59 -0
  770. package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.d.ts.map +1 -0
  771. package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.js +22 -0
  772. package/dist/esm/security/connected-accounts/organization-provider-credential-resolver.port.js.map +1 -0
  773. package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.d.ts +44 -0
  774. package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.d.ts.map +1 -0
  775. package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.js +20 -0
  776. package/dist/esm/security/connected-accounts/provider-oauth2-refresher.port.js.map +1 -0
  777. package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.d.ts +191 -0
  778. package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.d.ts.map +1 -0
  779. package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.js +385 -0
  780. package/dist/esm/security/connected-accounts/services/organization-provider-credential-store.backend.service.js.map +1 -0
  781. package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.d.ts +41 -0
  782. package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.d.ts.map +1 -0
  783. package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.js +358 -0
  784. package/dist/esm/security/connected-accounts/services/organization-provider-credentials.custom-impl.backend.service.js.map +1 -0
  785. package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.d.ts +160 -0
  786. package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.d.ts.map +1 -0
  787. package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.js +266 -0
  788. package/dist/esm/security/connected-accounts/services/provider-oauth2-exchange.backend.js.map +1 -0
  789. package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.d.ts +111 -0
  790. package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.d.ts.map +1 -0
  791. package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.js +107 -0
  792. package/dist/esm/security/connected-accounts/services/provider-oauth2-pending-authorization.backend.service.js.map +1 -0
  793. package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.d.ts +54 -0
  794. package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.d.ts.map +1 -0
  795. package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.js +153 -0
  796. package/dist/esm/security/connected-accounts/services/provider-oauth2-refresher.backend.service.js.map +1 -0
  797. package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.d.ts +195 -0
  798. package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.d.ts.map +1 -0
  799. package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.js +387 -0
  800. package/dist/esm/security/connected-accounts/services/user-provider-credential-store.backend.service.js.map +1 -0
  801. package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.d.ts +45 -0
  802. package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.d.ts.map +1 -0
  803. package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.js +291 -0
  804. package/dist/esm/security/connected-accounts/services/user-provider-credentials.custom-impl.backend.service.js.map +1 -0
  805. package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.d.ts +62 -0
  806. package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.d.ts.map +1 -0
  807. package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.js +29 -0
  808. package/dist/esm/security/connected-accounts/user-provider-credential-resolver.port.js.map +1 -0
  809. package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.d.ts +127 -0
  810. package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.d.ts.map +1 -0
  811. package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.js +277 -0
  812. package/dist/esm/security/connected-accounts/utils/provider-credential-envelope.backend.utils.js.map +1 -0
  813. package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.d.ts +66 -0
  814. package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.d.ts.map +1 -0
  815. package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.js +75 -0
  816. package/dist/esm/security/connected-accounts/utils/stored-credential-value.backend.utils.js.map +1 -0
  817. package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.d.ts +21 -3
  818. package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.d.ts.map +1 -1
  819. package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.js +26 -16
  820. package/dist/esm/security/consumable-tokens/services/consumable-token.backend.service.js.map +1 -1
  821. package/dist/esm/security/credential-rotation-grace.backend.utils.d.ts +9 -4
  822. package/dist/esm/security/credential-rotation-grace.backend.utils.d.ts.map +1 -1
  823. package/dist/esm/security/credential-rotation-grace.backend.utils.js +9 -4
  824. package/dist/esm/security/credential-rotation-grace.backend.utils.js.map +1 -1
  825. package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.d.ts +26 -0
  826. package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.d.ts.map +1 -1
  827. package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.js +43 -0
  828. package/dist/esm/security/oauth-clients/oauth-client-generation.backend.utils.js.map +1 -1
  829. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts +8 -1
  830. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts.map +1 -1
  831. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js +49 -0
  832. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js.map +1 -1
  833. package/dist/esm/security/scim/controllers/scim.backend.controller.d.ts.map +1 -1
  834. package/dist/esm/security/scim/controllers/scim.backend.controller.js +17 -5
  835. package/dist/esm/security/scim/controllers/scim.backend.controller.js.map +1 -1
  836. package/dist/esm/security/scim/models/scim-protocol.backend.schemas.d.ts +67 -29
  837. package/dist/esm/security/scim/models/scim-protocol.backend.schemas.d.ts.map +1 -1
  838. package/dist/esm/security/scim/models/scim-protocol.backend.schemas.js +47 -25
  839. package/dist/esm/security/scim/models/scim-protocol.backend.schemas.js.map +1 -1
  840. package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.d.ts +10 -2
  841. package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.d.ts.map +1 -1
  842. package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.js +10 -2
  843. package/dist/esm/security/ssrf/outbound-target-guard.backend.utils.js.map +1 -1
  844. package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.d.ts +143 -0
  845. package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.d.ts.map +1 -0
  846. package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.js +258 -0
  847. package/dist/esm/security/ssrf/pinned-outbound-fetch.backend.utils.js.map +1 -0
  848. package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.d.ts +39 -0
  849. package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.d.ts.map +1 -0
  850. package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.js +159 -0
  851. package/dist/esm/users/services/user-read-retained.custom-impl.backend.service.js.map +1 -0
  852. package/dist/tsconfig.build.tsbuildinfo +1 -1
  853. package/package.json +11 -9
@@ -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 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/** 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 // 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 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":"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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 * 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":"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;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,WAAmB,EAAE,WAAmB;QACjD,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,WAAW,IAAI,WAAW,EAAE,CAAC,CAAC;IAC5D,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;AAthBY,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,CAshBxC","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
  *
@@ -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
  *
@@ -1 +1 @@
1
- {"version":3,"file":"organization-purge.batch.backend.service.js","sourceRoot":"","sources":["../../../../../src/organizations/batches/organization-purge.batch.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Organization Purge Batch — the DESTRUCTIVE half of tenant teardown (WS-A).\n *\n * Tenant deletion is two phases. `request_deletion` marks a tenant: it writes `status: DELETED`,\n * `deletedAt` and `purgeScheduledAt`, reconciles every affected user's global `userTypes` and\n * invalidates their tokens — so the tenant is authorization-dead immediately while every row it\n * owns is still present and restorable. This batch is the second phase: once a tenant's\n * `purgeScheduledAt` deadline has passed, it destroys it.\n *\n * ## Why this batch owns NO teardown logic\n *\n * It dispatches each due tenant through the ordinary `ORGANIZATIONS | DELETE` core operation and\n * lets the existing `onParentDelete` cascade do the work. That is the single most important\n * property of this file, and the thing not to \"optimize\" later:\n *\n * `dispatchLifecycleCascadeForRelationship` is the ONE dispatcher for every teardown edge, and it\n * already switches on `ChildLifecycleStrategy` — `DELETE` versus `IMPERSONALIZE_AND_RETAIN` — and\n * already skips edges whose author declared `onParentDelete.enabled: false` (which is how the\n * retained billing rows are expressed). A purge that deleted rows itself, however carefully, would\n * bypass that dispatch and hard-delete children a retention or compliance decision had explicitly\n * marked to keep, while reporting success. The composition with the retention/impersonalization\n * capability is therefore FREE here precisely because nothing is re-implemented.\n *\n * It also means the `ORGANIZATION_DELETED` audit event still emits from its existing POSTFIX hook\n * on the DELETE operation, so the GDPR Art. 17 evidence obligation needs no separate mechanism.\n *\n * ## Why per-tenant isolation rather than one transaction\n *\n * Each tenant is its own attempt inside its own try/catch. A cascade that spans mixed persistence\n * adapters throws `CONFIGURATION` by design (`buildRepositoryOptionsForResource` fails closed\n * rather than degrading to a non-atomic teardown), and a single tenant can fail for its own\n * reasons. Isolating attempts means one undeletable tenant is logged and skipped instead of\n * wedging the queue for every other tenant whose deadline has also passed — which is exactly the\n * lockout the fail-closed adapter guard would otherwise create for a whole application.\n *\n * Mirrors the failure posture of `files-cleanup`, the engine's existing soft-delete + purge batch.\n *\n * assurance-control: WILDO.DATA.SECURE_LIFECYCLE — scheduled destruction of data at the end of a\n * declared retention period, with evidence emitted per tenant destroyed.\n */\n\nimport { createCustomBatchExecutionService } from '~wildo-backend-lib/base-classes/services/batches/batches-cronjobs-custom-execution.service';\nimport {\n ENGINE_ORGANIZATION_PURGE_BATCH_MANIFEST,\n ORGANIZATION_PURGE_DEFAULT_CRON,\n} from '~wildo-backend-lib/base-classes/services/batches/engine-custom-batch-manifests';\nimport { projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport { z } from 'zod';\nimport {\n CoreResourceType,\n OrganizationStatus,\n TENANT_TEARDOWN_CONFIG_DEFAULTS,\n type Organization,\n type TenantTeardownConfig,\n} from '@wildo-ai/saas-models';\n\n/**\n * Scheduled runs send no input. The overrides exist for tests and for an operator who needs to\n * drain a backlog in one pass, and both are bounded by the same code path as the scheduled run.\n */\nconst OrganizationPurgeInputSchema = z.object({\n /** Overrides `TenantTeardownConfig.purgeBatchSize` for this run. */\n maxOrganizations: z.number().int().min(1).optional(),\n /**\n * Treat this instant as \"now\" when comparing against `purgeScheduledAt`.\n *\n * Test-only in practice. It can only ever be used to purge tenants whose deadline has ALREADY\n * passed relative to the supplied instant — it does not bypass the window for a tenant that is\n * still inside one, because the predicate is still a comparison against the deadline the mark\n * pinned.\n */\n now: z.coerce.date().optional(),\n});\n\nconst OrganizationPurgeOutputSchema = z.object({\n /** Tenants whose deadline had passed and that this run attempted. */\n dueOrganizations: z.number().int().min(0),\n /** Tenants destroyed successfully. */\n purged: z.number().int().min(0),\n /** Tenants that failed their own attempt and remain marked for a later run. */\n failed: z.number().int().min(0),\n durationMs: z.number().int().min(0),\n});\n\n/**\n * Organization purge batch factory.\n *\n * @param tenantTeardownConfig operator configuration, when the application declares it. Every field\n * has a default, so an application that declares nothing still purges on a working 30-day window —\n * the alternative (no schedule) would accumulate marked-but-never-destroyed tenants, which is the\n * failure a retention window exists to prevent.\n */\nexport function createOrganizationPurgeBatch(\n tenantTeardownConfig?: TenantTeardownConfig,\n): ReturnType<typeof createCustomBatchExecutionService> {\n return createCustomBatchExecutionService({\n input: OrganizationPurgeInputSchema,\n output: OrganizationPurgeOutputSchema,\n batchCronjob_Context: {\n kind: ENGINE_ORGANIZATION_PURGE_BATCH_MANIFEST.kind,\n resourceIdentifier: ENGINE_ORGANIZATION_PURGE_BATCH_MANIFEST.resourceIdentifier,\n operationIdentifier: ENGINE_ORGANIZATION_PURGE_BATCH_MANIFEST.operationIdentifier,\n cronJobExpression: tenantTeardownConfig?.purgeCronSchedule ?? ORGANIZATION_PURGE_DEFAULT_CRON,\n },\n doHandle: async (input, { servicesRegistry, repositoriesRegistry, logger, executionContext }) => {\n const startTime = Date.now();\n const now = input.now ?? new Date();\n const maxOrganizations = input.maxOrganizations\n ?? tenantTeardownConfig?.purgeBatchSize\n ?? TENANT_TEARDOWN_CONFIG_DEFAULTS.purgeBatchSize;\n\n const organizationsRepository = repositoriesRegistry.getRepository(CoreResourceType.ORGANIZATIONS);\n\n // `status: DELETED` is the hard gate and is deliberately not merely a hint. `purgeScheduledAt`\n // is cleared on restore, and a comparison against a cleared/absent value must never select a\n // row — pairing the deadline with the status means a restored tenant is excluded by the\n // status alone, whatever its timestamps say.\n const dueOrganizations = await organizationsRepository.list<Organization>(executionContext, {\n status: OrganizationStatus.DELETED,\n purgeScheduledAt: { $lt: now, $exists: true },\n }) as Organization[];\n\n const attempted = dueOrganizations.slice(0, maxOrganizations);\n if (dueOrganizations.length > attempted.length) {\n // Never silently truncate: an operator reading \"purged 50\" with no other signal would\n // reasonably conclude the queue is empty.\n logger.info('Organization purge run bounded by batch size — remaining tenants are purged by the next run', {\n due: dueOrganizations.length,\n attempting: attempted.length,\n maxOrganizations,\n });\n }\n\n let purged = 0;\n let failed = 0;\n\n for (const organization of attempted) {\n if (!organization?._id) continue;\n try {\n // The ordinary DELETE. Resolves to the route-less INTERNAL_CALL default variant, whose\n // POSTFIX emits `ORGANIZATION_DELETED` — the evidence of what was destroyed — and whose\n // core persistence runs the `onParentDelete` cascade for every child edge.\n await servicesRegistry.delete(\n CoreResourceType.ORGANIZATIONS,\n executionContext,\n organization._id,\n );\n purged++;\n } catch (error) {\n failed++;\n // ERROR, not WARN: a tenant whose retention window has expired and which cannot be\n // destroyed is a standing compliance exposure, not routine noise. It stays marked, so the\n // next run retries it — but a permanently failing tenant must be visible rather than\n // retried silently forever.\n logger.error('Failed to purge an organization whose retention window has elapsed', {\n organizationId: organization._id,\n purgeScheduledAt: organization.purgeScheduledAt,\n ...projectCaughtErrorLogFields(error),\n });\n }\n }\n\n const durationMs = Date.now() - startTime;\n logger.info('Organization purge batch completed', {\n dueOrganizations: attempted.length,\n purged,\n failed,\n durationMs,\n });\n\n return {\n dueOrganizations: attempted.length,\n purged,\n failed,\n durationMs,\n };\n },\n });\n}\n"]}
1
+ {"version":3,"file":"organization-purge.batch.backend.service.js","sourceRoot":"","sources":["../../../../../src/organizations/batches/organization-purge.batch.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Organization Purge Batch — the DESTRUCTIVE half of tenant teardown (WS-A).\n *\n * Tenant deletion is two phases. `request_deletion` marks a tenant: it writes `status: DELETED`,\n * `deletionRequestedAt` and `purgeScheduledAt`, reconciles every affected user's global `userTypes`\n * and invalidates their tokens — so the tenant is authorization-dead immediately while every row it\n * owns is still present and restorable. This batch is the second phase: once a tenant's\n * `purgeScheduledAt` deadline has passed, it destroys it.\n *\n * ## Why this batch owns NO teardown logic\n *\n * It dispatches each due tenant through the ordinary `ORGANIZATIONS | DELETE` core operation and\n * lets the existing `onParentDelete` cascade do the work. That is the single most important\n * property of this file, and the thing not to \"optimize\" later:\n *\n * `dispatchLifecycleCascadeForRelationship` is the ONE dispatcher for every teardown edge, and it\n * already switches on `ChildLifecycleStrategy` — `DELETE` versus `IMPERSONALIZE_AND_RETAIN` — and\n * already skips edges whose author declared `onParentDelete.enabled: false` (which is how the\n * retained billing rows are expressed). A purge that deleted rows itself, however carefully, would\n * bypass that dispatch and hard-delete children a retention or compliance decision had explicitly\n * marked to keep, while reporting success. The composition with the retention/impersonalization\n * capability is therefore FREE here precisely because nothing is re-implemented.\n *\n * It also means the `ORGANIZATION_DELETED` audit event still emits from its existing POSTFIX hook\n * on the DELETE operation, so the GDPR Art. 17 evidence obligation needs no separate mechanism.\n *\n * ## Why per-tenant isolation rather than one transaction\n *\n * Each tenant is its own attempt inside its own try/catch. A cascade that spans mixed persistence\n * adapters throws `CONFIGURATION` by design (`buildRepositoryOptionsForResource` fails closed\n * rather than degrading to a non-atomic teardown), and a single tenant can fail for its own\n * reasons. Isolating attempts means one undeletable tenant is logged and skipped instead of\n * wedging the queue for every other tenant whose deadline has also passed — which is exactly the\n * lockout the fail-closed adapter guard would otherwise create for a whole application.\n *\n * Mirrors the failure posture of `files-cleanup`, the engine's existing soft-delete + purge batch.\n *\n * assurance-control: WILDO.DATA.SECURE_LIFECYCLE — scheduled destruction of data at the end of a\n * declared retention period, with evidence emitted per tenant destroyed.\n */\n\nimport { createCustomBatchExecutionService } from '~wildo-backend-lib/base-classes/services/batches/batches-cronjobs-custom-execution.service';\nimport {\n ENGINE_ORGANIZATION_PURGE_BATCH_MANIFEST,\n ORGANIZATION_PURGE_DEFAULT_CRON,\n} from '~wildo-backend-lib/base-classes/services/batches/engine-custom-batch-manifests';\nimport { projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport { z } from 'zod';\nimport {\n CoreResourceType,\n OrganizationStatus,\n TENANT_TEARDOWN_CONFIG_DEFAULTS,\n type Organization,\n type TenantTeardownConfig,\n} from '@wildo-ai/saas-models';\n\n/**\n * Scheduled runs send no input. The overrides exist for tests and for an operator who needs to\n * drain a backlog in one pass, and both are bounded by the same code path as the scheduled run.\n */\nconst OrganizationPurgeInputSchema = z.object({\n /** Overrides `TenantTeardownConfig.purgeBatchSize` for this run. */\n maxOrganizations: z.number().int().min(1).optional(),\n /**\n * Treat this instant as \"now\" when comparing against `purgeScheduledAt`.\n *\n * Test-only in practice. It can only ever be used to purge tenants whose deadline has ALREADY\n * passed relative to the supplied instant — it does not bypass the window for a tenant that is\n * still inside one, because the predicate is still a comparison against the deadline the mark\n * pinned.\n */\n now: z.coerce.date().optional(),\n});\n\nconst OrganizationPurgeOutputSchema = z.object({\n /** Tenants whose deadline had passed and that this run attempted. */\n dueOrganizations: z.number().int().min(0),\n /** Tenants destroyed successfully. */\n purged: z.number().int().min(0),\n /** Tenants that failed their own attempt and remain marked for a later run. */\n failed: z.number().int().min(0),\n durationMs: z.number().int().min(0),\n});\n\n/**\n * Organization purge batch factory.\n *\n * @param tenantTeardownConfig operator configuration, when the application declares it. Every field\n * has a default, so an application that declares nothing still purges on a working 30-day window —\n * the alternative (no schedule) would accumulate marked-but-never-destroyed tenants, which is the\n * failure a retention window exists to prevent.\n */\nexport function createOrganizationPurgeBatch(\n tenantTeardownConfig?: TenantTeardownConfig,\n): ReturnType<typeof createCustomBatchExecutionService> {\n return createCustomBatchExecutionService({\n input: OrganizationPurgeInputSchema,\n output: OrganizationPurgeOutputSchema,\n batchCronjob_Context: {\n kind: ENGINE_ORGANIZATION_PURGE_BATCH_MANIFEST.kind,\n resourceIdentifier: ENGINE_ORGANIZATION_PURGE_BATCH_MANIFEST.resourceIdentifier,\n operationIdentifier: ENGINE_ORGANIZATION_PURGE_BATCH_MANIFEST.operationIdentifier,\n cronJobExpression: tenantTeardownConfig?.purgeCronSchedule ?? ORGANIZATION_PURGE_DEFAULT_CRON,\n },\n doHandle: async (input, { servicesRegistry, repositoriesRegistry, logger, executionContext }) => {\n const startTime = Date.now();\n const now = input.now ?? new Date();\n const maxOrganizations = input.maxOrganizations\n ?? tenantTeardownConfig?.purgeBatchSize\n ?? TENANT_TEARDOWN_CONFIG_DEFAULTS.purgeBatchSize;\n\n const organizationsRepository = repositoriesRegistry.getRepository(CoreResourceType.ORGANIZATIONS);\n\n // `status: DELETED` is the hard gate and is deliberately not merely a hint. `purgeScheduledAt`\n // is cleared on restore, and a comparison against a cleared/absent value must never select a\n // row — pairing the deadline with the status means a restored tenant is excluded by the\n // status alone, whatever its timestamps say.\n const dueOrganizations = await organizationsRepository.list<Organization>(executionContext, {\n status: OrganizationStatus.DELETED,\n purgeScheduledAt: { $lt: now, $exists: true },\n }) as Organization[];\n\n const attempted = dueOrganizations.slice(0, maxOrganizations);\n if (dueOrganizations.length > attempted.length) {\n // Never silently truncate: an operator reading \"purged 50\" with no other signal would\n // reasonably conclude the queue is empty.\n logger.info('Organization purge run bounded by batch size — remaining tenants are purged by the next run', {\n due: dueOrganizations.length,\n attempting: attempted.length,\n maxOrganizations,\n });\n }\n\n let purged = 0;\n let failed = 0;\n\n for (const organization of attempted) {\n if (!organization?._id) continue;\n try {\n // The ordinary DELETE. Resolves to the route-less INTERNAL_CALL default variant, whose\n // POSTFIX emits `ORGANIZATION_DELETED` — the evidence of what was destroyed — and whose\n // core persistence runs the `onParentDelete` cascade for every child edge.\n await servicesRegistry.delete(\n CoreResourceType.ORGANIZATIONS,\n executionContext,\n organization._id,\n );\n purged++;\n } catch (error) {\n failed++;\n // ERROR, not WARN: a tenant whose retention window has expired and which cannot be\n // destroyed is a standing compliance exposure, not routine noise. It stays marked, so the\n // next run retries it — but a permanently failing tenant must be visible rather than\n // retried silently forever.\n logger.error('Failed to purge an organization whose retention window has elapsed', {\n organizationId: organization._id,\n purgeScheduledAt: organization.purgeScheduledAt,\n ...projectCaughtErrorLogFields(error),\n });\n }\n }\n\n const durationMs = Date.now() - startTime;\n logger.info('Organization purge batch completed', {\n dueOrganizations: attempted.length,\n purged,\n failed,\n durationMs,\n });\n\n return {\n dueOrganizations: attempted.length,\n purged,\n failed,\n durationMs,\n };\n },\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"organization-custom-implementation.backend.service.d.ts","sourceRoot":"","sources":["../../../../../src/organizations/services/organization-custom-implementation.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiBH,OAAO,EAEL,KAAK,0CAA0C,EAChD,MAAM,4GAA4G,CAAC;AAsIpH,wBAAgB,iCAAiC,IAAI,0CAA0C,EAAE,CAMhG;AAsqBD;;;;;;;GAOG;AACH,wBAAgB,oCAAoC,IAAI,0CAA0C,EAAE,CAQnG"}
1
+ {"version":3,"file":"organization-custom-implementation.backend.service.d.ts","sourceRoot":"","sources":["../../../../../src/organizations/services/organization-custom-implementation.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkBH,OAAO,EAEL,KAAK,0CAA0C,EAChD,MAAM,4GAA4G,CAAC;AAsNpH,wBAAgB,iCAAiC,IAAI,0CAA0C,EAAE,CAMhG;AAsqBD;;;;;;;GAOG;AACH,wBAAgB,oCAAoC,IAAI,0CAA0C,EAAE,CAQnG"}
@@ -6,7 +6,7 @@
6
6
  * Rejects invalid types with VALIDATION error.
7
7
  */
8
8
  import { resolveAuditActorId } from '../../compliance/audit-trails/utils/audit-actor.backend.utils.js';
9
- import { CoreResourceOperation, CoreResourceType, ErrorType, ErrorCustomMessageReference, Organization_Lifecycle_Operations, OrganizationMemberStatus, OrganizationStatus, ResourceOperationVariantType, resolveOrganizationPurgeScheduledAt, } from '@wildo-ai/saas-models';
9
+ import { CORE_ORG_ROLES, CoreResourceOperation, CoreResourceType, ErrorType, ErrorCustomMessageReference, Organization_Lifecycle_Operations, OrganizationMemberStatus, OrganizationStatus, ResourceOperationVariantType, resolveOrganizationPurgeScheduledAt, } from '@wildo-ai/saas-models';
10
10
  import { createResourceCustomServiceImplementation, } from '../../base-classes/services/services/resource-operation-custom-implementation.factory.backend.js';
11
11
  import { registerTransactionPostCommitEffect } from '../../databases/models/transaction.shared.schemas.js';
12
12
  import { projectCaughtErrorLogFields } from '../../errors/utils/error-log-level-classification.backend.utils.js';
@@ -73,7 +73,28 @@ function validateOrganizationTypeForCreation(organizationTypes, type, errorBuild
73
73
  * implementation can never execute on that variant under any configuration.
74
74
  */
75
75
  function createOrganizationCreateFactory(variantType, variantKey) {
76
- const factory = (resourcesRegistryService) => {
76
+ /*
77
+ * Whether this path must ESTABLISH THE FOUNDING OWNER (#436).
78
+ *
79
+ * The default API_CALL is self-service tenant creation: an authenticated user creating their own
80
+ * organization. Its configuration has always said "ownership is established by the create flow,
81
+ * not a role", and until 2026-09-08 that was FALSE for this path — the prefix validated the type
82
+ * and the name, the core write created the row, and nothing made anyone a member. A successful
83
+ * self-service create produced a tenant with ZERO members and ZERO owners: precisely the stranded
84
+ * state the organization-owner floor exists to prevent, reached through the front door.
85
+ *
86
+ * The other two paths are deliberately excluded, for opposite reasons:
87
+ *
88
+ * - INTERNAL_CALL is registration, and `createOrgOnRegistration` already writes the owner
89
+ * membership. Adding one here would write it twice.
90
+ * - The `admin` variant is a PLATFORM operator creating a tenant for someone else. Making the
91
+ * operator its owner would place a platform administrator inside a customer tenant as a
92
+ * standing member — the exact shape zero-standing-privilege work removed. That tenant is
93
+ * ownerless on purpose, and `organizationMembers.grantOwnership` is the audited, justified
94
+ * door for naming its first owner. Do not "fix" this by extending the postfix to it.
95
+ */
96
+ const establishesFoundingOwner = variantType === ResourceOperationVariantType.API_CALL && variantKey === undefined;
97
+ const factory = (resourcesRegistryService, container) => {
77
98
  return createResourceCustomServiceImplementation({
78
99
  operationPath: {
79
100
  resourceIdentifier: CoreResourceType.ORGANIZATIONS,
@@ -100,6 +121,46 @@ function createOrganizationCreateFactory(variantType, variantKey) {
100
121
  }
101
122
  return input;
102
123
  },
124
+ ...(establishesFoundingOwner
125
+ ? {
126
+ postfixCoreOperations: async (_id, createdOrganization, executionContext, _operationPath, utils) => {
127
+ const organizationId = createdOrganization?._id;
128
+ const userId = executionContext.initiatorIds?.userId;
129
+ /*
130
+ * FAIL CLOSED — deliberately not wrapped in a catch.
131
+ *
132
+ * A create that answers 200 having produced a tenant nobody can administer is worse
133
+ * than one that fails: the caller retries a failure, and cannot even see the other.
134
+ * The membership write joins the caller's unit of work through `utils.serviceOptions`,
135
+ * so a failure here takes the organization row with it rather than leaving the
136
+ * stranded tenant this postfix exists to prevent.
137
+ */
138
+ if (!organizationId || !userId) {
139
+ throw utils.errorBuilder.buildError(ErrorType.INTERNAL, executionContext, {
140
+ customMessageReference: ErrorCustomMessageReference.INTERNAL,
141
+ context: {
142
+ // diagnostic (log-only)
143
+ message: 'Self-service organization create cannot establish a founding owner',
144
+ organizationId,
145
+ hasInitiatorUserId: Boolean(userId),
146
+ },
147
+ });
148
+ }
149
+ const organizationTypes = resourcesRegistryService.getOrganizationTypesConfig();
150
+ const type = createdOrganization?.type;
151
+ // The SAME resolution registration uses, so the two creation paths cannot disagree
152
+ // about which role owns a tenant of a given type.
153
+ const ownerRole = (type ? organizationTypes?.[type] : undefined)?.creationPolicy?.defaultOwnerRole
154
+ ?? CORE_ORG_ROLES.ORG_OWNER;
155
+ const systemAccess = container.get(SAAS_SERVICE_TYPES.SystemAccessService);
156
+ // Trusted write: the client-shaped CREATE DTO strips `userId` / `organizationId`,
157
+ // and `createAsSystem` re-attaches both after the strict parse — the same reason
158
+ // `createOrgOnRegistration` uses it for the identical row.
159
+ await systemAccess.createAsSystem(CoreResourceType.ORGANIZATION_MEMBERS, { userId, organizationId, roles: [ownerRole] }, utils.serviceOptions);
160
+ return createdOrganization;
161
+ },
162
+ }
163
+ : {}),
103
164
  },
104
165
  });
105
166
  };