@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":"usage-metering.backend.service.js","sourceRoot":"","sources":["../../../../../../src/billing/services/back-office/usage-metering.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Usage Metering Backend Service\n *\n * Tracks and reports usage for METERED products.\n * Usage is recorded locally (buffered) and periodically flushed to the billing provider.\n *\n * Flow:\n * 1. Operation hook calls recordUsage() after successful operation\n * 2. Usage records are stored in DB (reportedToProvider: false)\n * 3. Periodic flush (cron) aggregates and reports to provider\n * 4. Provider bills at the end of the billing period\n *\n * @see billing-and-features-system.md §9 (Usage & Consumption Tracking)\n */\n\nimport { injectable, inject } from 'inversify';\nimport {\n type UsageRecord,\n type BillingSubscriptionBase,\n type Product,\n UsageSourceType,\n ProductType,\n SubscriptionStatus,\n CoreResourceType,\n CoreResourceOperation,\n} from '@wildo-ai/saas-models';\nimport type { StandardBilling_Interface } from '@wildo-ai/external-connectors-models';\nimport { AbstractBillingBackendService } from '~wildo-backend-lib/billing/services/back-office/abstract-billing.backend.service';\nimport { type BillingResolvedVariants, BILLING_SCOPE_TO_VARIANTS } from '~wildo-backend-lib/billing/services/custom-impl/billing-custom-impl-utils.backend';\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 { ServicesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/services/services-registry-handler.backend.service';\nimport type { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\n\n// =====================================================\n// Types\n// =====================================================\n\nexport interface RecordUsageOptions {\n /** What generated this usage */\n source?: {\n type: UsageSourceType;\n resourceType?: string;\n operationIdentifier?: string;\n description?: string;\n };\n metadata?: Record<string, string>;\n}\n\nexport interface UsageFlushResult {\n totalRecords: number;\n reported: number;\n failed: number;\n errors: string[];\n}\n\n// =====================================================\n// Service\n// =====================================================\n\n@injectable()\nexport class UsageMeteringBackendService extends AbstractBillingBackendService {\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.ServicesRegistryHandlerService) servicesRegistry: ServicesRegistryHandlerBackendService,\n @inject(SAAS_SERVICE_TYPES.ExecutionContextCreatorBackendService) executionContextCreator: ExecutionContextCreatorBackendService,\n @inject(SAAS_SERVICE_TYPES.ResourceRegistryService) resourcesRegistry: ResourcesRegistryBackendService,\n @inject(SAAS_SERVICE_TYPES.ErrorBuilderService) errorBuilder: ErrorBuilderBackendService,\n @inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService) private readonly repositoriesRegistry: RepositoriesRegistryHandlerBackendService,\n ) {\n super(logger, servicesRegistry, executionContextCreator, resourcesRegistry, errorBuilder);\n }\n\n // ════════════════════════════════════════════════════════════\n // Initialization\n // ════════════════════════════════════════════════════════════\n\n public async initialize(provider: StandardBilling_Interface): Promise<void> {\n if (this.isInitialized) return;\n this.initializeProvider(provider);\n this.logDebug('Usage metering service initialized');\n }\n\n // ════════════════════════════════════════════════════════════\n // Public API\n // ════════════════════════════════════════════════════════════\n\n /**\n * Record a usage event for a billing account.\n * Stores locally — NOT reported to provider immediately.\n *\n * @param variants — resolved billing polymorphic variants for the target scope\n */\n public async recordUsage(\n variants: BillingResolvedVariants,\n billingAccountId: string,\n productKey: string,\n quantity: number,\n options?: RecordUsageOptions,\n ): Promise<void> {\n this.logDebug('Recording usage', { billingAccountId, productKey, quantity, scope: variants.scopeType });\n\n const hasSubscription = await this.hasActiveMeteredSubscription(variants, billingAccountId, productKey);\n if (!hasSubscription) {\n this.logger.warn('No active metered subscription found for usage recording', {\n billingAccountId,\n productKey,\n scope: variants.scopeType,\n });\n return;\n }\n\n const ctx = await this.internalCtx(variants.usageRecord as CoreResourceType, CoreResourceOperation.CREATE);\n await this.servicesRegistry.create(variants.usageRecord as CoreResourceType, ctx, {\n [variants.billingAccountFkField]: billingAccountId,\n productKey,\n quantity,\n timestamp: new Date(),\n source: options?.source,\n reportedToProvider: false,\n metadata: options?.metadata,\n });\n }\n\n /**\n * Get usage summary for a billing account.\n *\n * @param variants — resolved billing polymorphic variants for the target scope\n */\n public async getUsage(\n variants: BillingResolvedVariants,\n billingAccountId: string,\n productKey?: string,\n period?: { start: Date; end: Date },\n ): Promise<Record<string, number>> {\n const filters: Record<string, unknown> = {\n [variants.billingAccountFkField]: billingAccountId,\n ...(productKey && { productKey }),\n ...(period && {\n timestamp: {\n $gte: period.start,\n $lte: period.end,\n },\n }),\n };\n\n const ctx = await this.internalCtx(variants.usageRecord as CoreResourceType, CoreResourceOperation.LIST);\n const records = await this.servicesRegistry.list<UsageRecord>(variants.usageRecord as CoreResourceType, ctx, filters, { limit: 10000 }) as UsageRecord[];\n\n // Aggregate by product key\n const usage: Record<string, number> = {};\n for (const record of records) {\n usage[record.productKey] = (usage[record.productKey] ?? 0) + record.quantity;\n }\n\n return usage;\n }\n\n /**\n * Flush unreported usage records to the billing provider.\n * Called periodically by a cron job.\n *\n * Iterates all billing scopes, aggregates records by (billingAccountId, productKey)\n * per scope, then reports to the provider.\n */\n public async flushToProvider(): Promise<UsageFlushResult> {\n if (!this.billingProvider) {\n return { totalRecords: 0, reported: 0, failed: 0, errors: ['Provider not initialized'] };\n }\n\n this.logDebug('Starting usage flush to provider');\n\n const result: UsageFlushResult = {\n totalRecords: 0,\n reported: 0,\n failed: 0,\n errors: [],\n };\n\n // Process each billing scope independently — usage records live in per-scope collections\n for (const [scopeKey, scopeData] of Object.entries(BILLING_SCOPE_TO_VARIANTS)) {\n const variants: BillingResolvedVariants = { scopeKey, ...scopeData };\n try {\n await this.flushScopeToProvider(variants, result);\n } catch (error) {\n result.errors.push(`Flush error for scope ${variants.scopeType}: ${(error as Error).message}`);\n }\n }\n\n this.logDebug('Usage flush complete', { ...result });\n return result;\n }\n\n // ════════════════════════════════════════════════════════════\n // Private — Flush per scope\n // ════════════════════════════════════════════════════════════\n\n private async flushScopeToProvider(variants: BillingResolvedVariants, result: UsageFlushResult): Promise<void> {\n // List unreported records from this scope's usage record collection\n const listCtx = await this.internalCtx(variants.usageRecord as CoreResourceType, CoreResourceOperation.LIST);\n const records = await this.servicesRegistry.list<UsageRecord>(\n variants.usageRecord as CoreResourceType,\n listCtx,\n { reportedToProvider: false },\n { limit: 10000 },\n ) as UsageRecord[];\n\n result.totalRecords += records.length;\n\n if (records.length === 0) return;\n\n // Aggregate by (billingAccountFkField value, productKey)\n const billingAccountFk = variants.billingAccountFkField;\n const aggregateKey = (r: UsageRecord) => `${(r as any)[billingAccountFk]}::${r.productKey}`;\n const aggregated = new Map<string, { billingAccountId: string; productKey: string; quantity: number; recordIds: string[] }>();\n\n for (const record of records) {\n const key = aggregateKey(record);\n const existing = aggregated.get(key);\n if (existing) {\n existing.quantity += record.quantity;\n existing.recordIds.push(record._id);\n } else {\n aggregated.set(key, {\n billingAccountId: (record as any)[billingAccountFk],\n productKey: record.productKey,\n quantity: record.quantity,\n recordIds: [record._id],\n });\n }\n }\n\n // Report each aggregated group to provider via billing meter events\n for (const [, group] of aggregated) {\n try {\n // Resolve provider customer ID from billing account\n const providerCustomerId = await this.resolveProviderCustomerId(variants, group.billingAccountId);\n if (!providerCustomerId) {\n result.errors.push(`No provider customer ID for billing account ${group.billingAccountId} (scope: ${variants.scopeType})`);\n result.failed += group.recordIds.length;\n continue;\n }\n\n // The meterEventName is derived from the product key\n // Convention: product key IS the meter event name (configured when creating the meter in Stripe)\n await this.billingProvider!.reportUsage({\n meterEventName: group.productKey,\n providerCustomerId,\n value: group.quantity,\n });\n\n // Bulk-mark all records in this group as reported (single DB call).\n //\n // The `reportUsage` above ALREADY moved money — it is not retryable-for-free. The marking is\n // what stops the next sweep from re-reporting the same usage, because the sweep selects on\n // `reportedToProvider: false`. So a PARTIAL marking is a duplicate-charge condition: any record\n // that stayed unmarked will be picked up again and billed to the customer a second time.\n //\n // Honour `modifiedCount` rather than assuming success. Previously the return value was\n // discarded and `result.reported` was incremented by the full group size, which made a partial\n // marking both invisible and unfalsifiable — the operational counter reported success for\n // records that were about to be re-billed.\n const markedCount = await this.repositoriesRegistry.bulkUpdateForInfrastructure(\n variants.usageRecord,\n { _id: { $in: group.recordIds } },\n // The adapter-neutral guarded-mutation descriptor. This was `{ $set: … }` — raw MongoDB —\n // until `bulkUpdateForInfrastructure` became adapter-neutral; on a PostgreSQL-backed usage\n // record the old path threw before marking anything, which is the duplicate-charge\n // condition the block below exists to detect.\n { set: { reportedToProvider: true, reportedAt: new Date() } },\n );\n\n const unmarkedCount = group.recordIds.length - markedCount;\n if (unmarkedCount > 0) {\n // Loud + specific: usage is already reported to the provider, so this is NOT a \"retry me\"\n // error — re-running the sweep is precisely what would double-charge.\n result.errors.push(\n `DUPLICATE-CHARGE RISK — ${group.billingAccountId}/${group.productKey} (scope: ${variants.scopeType}): ` +\n `usage of ${group.quantity} was REPORTED to the provider, but only ${markedCount}/${group.recordIds.length} ` +\n `records could be marked as reported. The ${unmarkedCount} unmarked record(s) remain selectable by the next ` +\n `sweep and would be billed AGAIN. Investigate before the next run; mark them manually if the report succeeded.`,\n );\n result.failed += unmarkedCount;\n }\n\n result.reported += markedCount;\n } catch (error) {\n result.errors.push(`${group.billingAccountId}/${group.productKey} (scope: ${variants.scopeType}): ${(error as Error).message}`);\n result.failed += group.recordIds.length;\n }\n }\n }\n\n // ════════════════════════════════════════════════════════════\n // Private — Resolution\n // ════════════════════════════════════════════════════════════\n\n /**\n * Validate that the billing account has an active subscription containing\n * a metered product matching the given product key. Returns true as soon\n * as one matching item is found — the item identity is not needed because\n * the Billing Meter provider API routes usage by meterEventName + customer,\n * not by subscription item.\n */\n private async hasActiveMeteredSubscription(\n variants: BillingResolvedVariants,\n billingAccountId: string,\n productKey: string,\n ): Promise<boolean> {\n // Context construction stays OUTSIDE the guarded try: failing to resolve the\n // INTERNAL_CALL operation path is a wiring fault, never \"no metered subscription\".\n // Returning a masked `false` here silently stops metered usage from being\n // recorded — a billing-correctness failure, not a display one.\n const subsCtx = await this.internalCtx(variants.subscription as CoreResourceType, CoreResourceOperation.LIST);\n try {\n const subscriptions = await this.servicesRegistry.list<BillingSubscriptionBase>(variants.subscription as CoreResourceType, subsCtx, {\n [variants.billingAccountFkField]: billingAccountId,\n status: { $in: [SubscriptionStatus.ACTIVE, SubscriptionStatus.TRIALING] },\n }) as BillingSubscriptionBase[];\n\n for (const sub of subscriptions) {\n for (const item of sub.items) {\n const readCtx = await this.internalCtx(CoreResourceType.PRODUCTS, CoreResourceOperation.READ);\n try {\n const product = await this.servicesRegistry.read<Product>(CoreResourceType.PRODUCTS, readCtx, item.productId);\n if (product && product.key === productKey && product.type === ProductType.METERED) {\n return true;\n }\n } catch (error) {\n this.degradeOrRethrow(error, 'Failed to read product for metered item lookup', { productId: item.productId });\n continue;\n }\n }\n }\n } catch (error) {\n this.degradeOrRethrow(error, 'Failed to validate metered subscription', { billingAccountId, productKey });\n }\n return false;\n }\n\n private async resolveProviderCustomerId(variants: BillingResolvedVariants, billingAccountId: string): Promise<string | null> {\n const readCtx = await this.internalCtx(variants.billingAccount as CoreResourceType, CoreResourceOperation.READ);\n try {\n const billingAccount = await this.servicesRegistry.read<{ providerCustomerId?: string }>(\n variants.billingAccount as CoreResourceType, readCtx, billingAccountId,\n );\n return billingAccount?.providerCustomerId ?? null;\n } catch (error) {\n this.degradeOrRethrow(error, 'Failed to resolve provider customer ID', { billingAccountId, scope: variants.scopeType });\n }\n return null;\n }\n}\n"]}
1
+ {"version":3,"file":"usage-metering.backend.service.js","sourceRoot":"","sources":["../../../../../../src/billing/services/back-office/usage-metering.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Usage Metering Backend Service\n *\n * Tracks and reports usage for METERED products.\n * Usage is recorded locally (buffered) and periodically flushed to the billing provider.\n *\n * Flow:\n * 1. Operation hook calls recordUsage() after successful operation\n * 2. Usage records are stored in DB (flushState: pending)\n * 3. Periodic flush (cron) aggregates and reports to provider\n * 4. Provider bills at the end of the billing period\n *\n * @see billing-and-features-system.md §9 (Usage & Consumption Tracking)\n */\n\nimport { injectable, inject } from 'inversify';\nimport { createHash } from 'node:crypto';\nimport {\n type UsageRecord,\n type BillingSubscriptionBase,\n type Product,\n type ProductBehaviorPolicy,\n type MeteredUsageRecordingDefinition,\n UsageSourceType,\n UsageRecordFlushState,\n UsageRecordUnreportableReason,\n ProductType,\n SubscriptionStatus,\n MeteringAggregationWindow,\n CoreResourceType,\n CoreResourceOperation,\n} from '@wildo-ai/saas-models';\nimport type { StandardBilling_Interface, StandardBilling_ReportUsageRequest } from '@wildo-ai/external-connectors-models';\nimport { AbstractBillingBackendService } from '~wildo-backend-lib/billing/services/back-office/abstract-billing.backend.service';\nimport { type BillingResolvedVariants, BILLING_SCOPE_TO_VARIANTS, resolveBillingVariants } from '~wildo-backend-lib/billing/services/custom-impl/billing-custom-impl-utils.backend';\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 { ServicesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/services/services-registry-handler.backend.service';\nimport type { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\n\n// =====================================================\n// Types\n// =====================================================\n\nexport interface RecordUsageOptions {\n /** What generated this usage */\n source?: {\n type: UsageSourceType;\n resourceType?: string;\n operationIdentifier?: string;\n description?: string;\n };\n metadata?: Record<string, string>;\n}\n\nexport interface UsageFlushResult {\n totalRecords: number;\n reported: number;\n failed: number;\n /**\n * Rows this run moved to `flushState: unreportable` — a PERMANENT determination, distinct from\n * `failed`, which means \"try again next run\" (#512).\n *\n * The two must never be merged. A failure that is counted as unreportable silently abandons\n * billable usage; an unreportable row counted as failed is re-selected forever and grows a\n * backlog nothing can drain, which is the defect this counter was added with.\n */\n unreportable: number;\n errors: string[];\n /**\n * The RECONCILIATION line: quantity recorded locally versus quantity reported to the provider,\n * per run (#415).\n *\n * Getting metering wrong moves money in BOTH directions, and neither direction announces itself —\n * an under-report is revenue that never appears, an over-report is a customer charged twice. A\n * counter of ROWS cannot see either, because rows carry quantities: ten rows reported can be any\n * amount at all. So the run states what it took in and what it sent out, and the two are meant to\n * be equal. When they are not, `errors` says why.\n */\n quantityRecorded: number;\n quantityReported: number;\n /**\n * Quantity this run determined will NEVER be billed. Counted separately from\n * {@link quantityReported} because it is the opposite outcome: the provider was not told, and\n * never will be. It closes the reconciliation identity —\n * `quantityRecorded === quantityReported + quantityUnreportable + (what stays pending)`.\n */\n quantityUnreportable: number;\n}\n\n/**\n * One group of usage rows that will become ONE provider meter event.\n *\n * `periodStart` is present only under {@link MeteringAggregationWindow.PER_BILLING_PERIOD}, where it\n * is part of the key — see `buildFlushGroups`.\n */\ninterface UsageFlushGroup {\n billingAccountId: string;\n productKey: string;\n quantity: number;\n recordIds: string[];\n /** The LATEST usage instant in the group; what the provider is told the event happened at. */\n latestTimestamp: Date;\n periodStart?: Date;\n}\n\n// =====================================================\n// Service\n// =====================================================\n\n@injectable()\nexport class UsageMeteringBackendService extends AbstractBillingBackendService {\n\n /**\n * How many rows one LIST page fetches while draining the pending set.\n *\n * A page size, never a cap: the drain pages until exhausted. It exists because a single query for an\n * unbounded set is the shape that produced the `limit: 10000` this replaced.\n */\n private static readonly FLUSH_PAGE_SIZE = 500;\n\n /**\n * The runaway guard, in PAGES. Reaching it aborts the scope and reports nothing — see\n * `listAllUnreportedRecords` for why a partial flush is worse than none.\n *\n * 2,000 pages is a million pending rows. That is not a busy hour, it is a flush that has not run for\n * a long time, and the right response is a person rather than a bigger number.\n */\n private static readonly MAX_FLUSH_PAGES = 2_000;\n\n /** First retry delay; each subsequent one multiplies by the product's `backoffMultiplier`. */\n private static readonly RETRY_BASE_DELAY_MS = 250;\n\n /** Per-run caches, held only for the duration of one `flushToProvider`. `null` means \"looked up, absent\". */\n private flushProductCache?: Map<string, ProductBehaviorPolicy['metering'] | null>;\n private flushPeriodCache?: Map<string, { start: Date; end: Date } | null>;\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.ServicesRegistryHandlerService) servicesRegistry: ServicesRegistryHandlerBackendService,\n @inject(SAAS_SERVICE_TYPES.ExecutionContextCreatorBackendService) executionContextCreator: ExecutionContextCreatorBackendService,\n @inject(SAAS_SERVICE_TYPES.ResourceRegistryService) resourcesRegistry: ResourcesRegistryBackendService,\n @inject(SAAS_SERVICE_TYPES.ErrorBuilderService) errorBuilder: ErrorBuilderBackendService,\n @inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService) private readonly repositoriesRegistry: RepositoriesRegistryHandlerBackendService,\n ) {\n super(logger, servicesRegistry, executionContextCreator, resourcesRegistry, errorBuilder);\n }\n\n // ════════════════════════════════════════════════════════════\n // Initialization\n // ════════════════════════════════════════════════════════════\n\n public async initialize(provider: StandardBilling_Interface): Promise<void> {\n if (this.isInitialized) return;\n this.initializeProvider(provider);\n this.logDebug('Usage metering service initialized');\n }\n\n // ════════════════════════════════════════════════════════════\n // Public API\n // ════════════════════════════════════════════════════════════\n\n /**\n * Record a usage event for a billing account.\n * Stores locally — NOT reported to provider immediately.\n *\n * @param variants — resolved billing polymorphic variants for the target scope\n * @returns whether a usage row was actually written.\n *\n * The return type was `void` until 2026-09-08 (#415), which was harmless only while nothing called\n * this: the method DECLINES silently when the account holds no active metered subscription, so a\n * caller could not distinguish \"recorded\" from \"declined\". The first real caller then reported the\n * quantity it had ASKED for whichever happened — an operational counter claiming usage that was\n * never written, the same shape as the discarded `modifiedCount` this file already fixed once in\n * the flush. Caught by a pin rather than by a reading, which is the argument for writing the\n * refusal cases as carefully as the success ones.\n */\n public async recordUsage(\n variants: BillingResolvedVariants,\n billingAccountId: string,\n productKey: string,\n quantity: number,\n options?: RecordUsageOptions,\n ): Promise<boolean> {\n this.logDebug('Recording usage', { billingAccountId, productKey, quantity, scope: variants.scopeType });\n\n const hasSubscription = await this.hasActiveMeteredSubscription(variants, billingAccountId, productKey);\n if (!hasSubscription) {\n this.logger.warn('No active metered subscription found for usage recording', {\n billingAccountId,\n productKey,\n scope: variants.scopeType,\n });\n return false;\n }\n\n const ctx = await this.internalCtx(variants.usageRecord as CoreResourceType, CoreResourceOperation.CREATE);\n await this.servicesRegistry.create(variants.usageRecord as CoreResourceType, ctx, {\n [variants.billingAccountFkField]: billingAccountId,\n productKey,\n quantity,\n timestamp: new Date(),\n source: options?.source,\n flushState: UsageRecordFlushState.PENDING,\n metadata: options?.metadata,\n });\n return true;\n }\n\n /**\n * Record usage declared by an OPERATION, resolving the scope, the billing account and the quantity\n * from the operation's own execution context and result (#415).\n *\n * This is the caller `recordUsage` never had. Until it existed, a product could be declared METERED,\n * priced and synced to the provider while nothing in the framework ever wrote a usage row — the\n * only way to meter was to reach into this service by hand from a custom implementation, which is a\n * workaround rather than an authoring surface.\n *\n * **Never throws.** It runs after a write has already committed, so a failure here must not turn a\n * successful operation into an error the caller sees. Every refusal is a warning naming the product\n * and the reason, because an unrecorded unit is revenue that will not be billed and the log line is\n * the only thing that will ever say so.\n *\n * @returns the quantity recorded, or 0 when nothing was recorded — so a caller can log the outcome\n * rather than assume it.\n */\n public async recordDeclaredOperationUsage(\n declaration: MeteredUsageRecordingDefinition,\n executionContext: ExecutionContext<any>,\n operationResult: unknown,\n ): Promise<number> {\n try {\n const variants = resolveBillingVariants(executionContext);\n if (!variants) {\n this.logger.warn('Declared metered usage not recorded: no billing scope on the execution context', {\n productKey: declaration.productKey,\n });\n return 0;\n }\n\n const quantity = this.resolveDeclaredQuantity(declaration, operationResult);\n if (quantity === undefined) return 0;\n // Zero is a legitimate outcome of a result-derived quantity — an export of nothing — and\n // reporting it would be a meter event carrying no usage.\n if (quantity === 0) return 0;\n\n const billingAccountId = await this.resolveBillingAccountIdForScope(variants, executionContext);\n if (!billingAccountId) {\n this.logger.warn('Declared metered usage not recorded: no billing account for this scope', {\n productKey: declaration.productKey,\n scope: variants.scopeType,\n });\n return 0;\n }\n\n // Honour what `recordUsage` REPORTS rather than what was asked for: it declines silently when\n // the account holds no active metered subscription, and returning the requested quantity there\n // would make the hook's own log claim usage that was never written.\n const recorded = await this.recordUsage(variants, billingAccountId, declaration.productKey, quantity, {\n source: {\n // OPERATION, and this declaration is what that member was always for: usage generated by a\n // resource operation succeeding, as opposed to a periodic RESOURCE_COUNT or a CUSTOM\n // recording an application makes for itself.\n type: UsageSourceType.OPERATION,\n resourceType: String(executionContext.operation?.resourceIdentifier ?? ''),\n operationIdentifier: String(executionContext.operation?.operationIdentifier ?? ''),\n description: 'Declared on the operation configuration',\n },\n });\n return recorded ? quantity : 0;\n } catch (error) {\n this.logger.error('Failed to record declared metered usage', {\n productKey: declaration.productKey,\n message: (error as Error).message,\n });\n return 0;\n }\n }\n\n /**\n * The declared quantity: fixed, or read from the written row.\n *\n * A `quantityFromResultField` that does not resolve to a finite non-negative number records NOTHING\n * and warns, rather than falling back to 1. Silently billing the wrong amount is worse than billing\n * nothing and saying so — a fallback here would be a wrong number nobody could distinguish from a\n * right one.\n */\n private resolveDeclaredQuantity(\n declaration: MeteredUsageRecordingDefinition,\n operationResult: unknown,\n ): number | undefined {\n if (declaration.quantityFromResultField === undefined) {\n return declaration.quantity ?? 1;\n }\n\n const raw = declaration.quantityFromResultField\n .split('.')\n .reduce<unknown>((value, segment) => (\n value !== null && typeof value === 'object' ? (value as Record<string, unknown>)[segment] : undefined\n ), operationResult);\n\n if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 0) {\n this.logger.warn('Declared metered usage not recorded: quantity field did not resolve to a usable number', {\n productKey: declaration.productKey,\n quantityFromResultField: declaration.quantityFromResultField,\n resolvedType: typeof raw,\n });\n return undefined;\n }\n return raw;\n }\n\n /** The scope's billing account, addressed by the scope entity rather than by an id the caller supplies. */\n private async resolveBillingAccountIdForScope(\n variants: BillingResolvedVariants,\n executionContext: ExecutionContext<any>,\n ): Promise<string | undefined> {\n const scopeEntityId = (executionContext as unknown as Record<string, string | undefined>)[variants.scopeKey];\n if (!scopeEntityId) return undefined;\n\n const ctx = await this.internalCtx(variants.billingAccount as CoreResourceType, CoreResourceOperation.LIST);\n const accounts = await this.servicesRegistry.list<{ _id: string }>(\n variants.billingAccount as CoreResourceType, ctx,\n { [variants.scopeEntityDocField]: scopeEntityId },\n { page: 1, limit: 1 },\n ) as { _id: string }[];\n return accounts[0]?._id;\n }\n\n /**\n * Get usage summary for a billing account.\n *\n * @param variants — resolved billing polymorphic variants for the target scope\n */\n public async getUsage(\n variants: BillingResolvedVariants,\n billingAccountId: string,\n productKey?: string,\n period?: { start: Date; end: Date },\n ): Promise<Record<string, number>> {\n const filters: Record<string, unknown> = {\n [variants.billingAccountFkField]: billingAccountId,\n ...(productKey && { productKey }),\n ...(period && {\n timestamp: {\n $gte: period.start,\n $lte: period.end,\n },\n }),\n };\n\n const ctx = await this.internalCtx(variants.usageRecord as CoreResourceType, CoreResourceOperation.LIST);\n /*\n * A SUMMARY read, and its cap is honest about being one: `getUsage` answers \"roughly how much has\n * this account used\", for a dashboard. It is not the billing path — `flushToProvider` drains the\n * pending set by paging and never truncates, because money depends on it. Keeping a cap here and\n * removing it there is the distinction, not an inconsistency.\n */\n const records = await this.servicesRegistry.list<UsageRecord>(variants.usageRecord as CoreResourceType, ctx, filters, { limit: 10000 }) as UsageRecord[];\n\n // Aggregate by product key\n const usage: Record<string, number> = {};\n for (const record of records) {\n usage[record.productKey] = (usage[record.productKey] ?? 0) + record.quantity;\n }\n\n return usage;\n }\n\n /**\n * Flush unreported usage records to the billing provider.\n * Called periodically by a cron job.\n *\n * Iterates all billing scopes, aggregates records by (billingAccountId, productKey)\n * per scope, then reports to the provider.\n */\n public async flushToProvider(): Promise<UsageFlushResult> {\n if (!this.billingProvider) {\n return { totalRecords: 0, reported: 0, failed: 0, unreportable: 0, errors: ['Provider not initialized'], quantityRecorded: 0, quantityReported: 0, quantityUnreportable: 0 };\n }\n\n this.logDebug('Starting usage flush to provider');\n\n const result: UsageFlushResult = {\n totalRecords: 0,\n reported: 0,\n failed: 0,\n unreportable: 0,\n errors: [],\n quantityRecorded: 0,\n quantityReported: 0,\n quantityUnreportable: 0,\n };\n\n // Per-run caches. A flush touches the same handful of products and subscriptions repeatedly, and\n // both lookups are needed PER GROUP; without these the policy read alone is one query per group.\n this.flushProductCache = new Map();\n this.flushPeriodCache = new Map();\n\n // Process each billing scope independently — usage records live in per-scope collections\n for (const [scopeKey, scopeData] of Object.entries(BILLING_SCOPE_TO_VARIANTS)) {\n const variants: BillingResolvedVariants = { scopeKey, ...scopeData };\n try {\n await this.flushScopeToProvider(variants, result);\n } catch (error) {\n result.errors.push(`Flush error for scope ${variants.scopeType}: ${(error as Error).message}`);\n }\n }\n\n /*\n * The reconciliation check, stated as an ERROR rather than left to a reader of two numbers.\n * Anything not reported is money not billed, and the run is the only moment at which the two\n * quantities are both known.\n */\n /*\n * Unreportable quantity is stated on its OWN line, and always — it is not an anomaly to be\n * inferred from a mismatch. This is usage a customer generated and will never be billed for,\n * which somebody may want to write off, invoice out of band, or simply know about. It appears\n * exactly once per row, on the run that made the determination, because the row leaves the\n * pending set at the same moment (#512).\n */\n if (result.quantityUnreportable > 0) {\n result.errors.push(\n `UNREPORTABLE USAGE — ${result.quantityUnreportable} unit(s) across ${result.unreportable} record(s) were ` +\n `permanently abandoned this run and will never be billed. The per-group lines above name the billing ` +\n `accounts and the reason. Those rows are now marked unreportable and will not be selected again, so ` +\n `THIS IS THE ONLY RUN THAT WILL REPORT THEM.`,\n );\n }\n\n const quantityAccountedFor = result.quantityReported + result.quantityUnreportable;\n if (quantityAccountedFor !== result.quantityRecorded) {\n const shortfall = result.quantityRecorded - quantityAccountedFor;\n result.errors.push(\n `RECONCILIATION MISMATCH — ${result.quantityRecorded} unit(s) of usage were pending, ` +\n `${result.quantityReported} were reported to the provider and ${result.quantityUnreportable} were ` +\n `determined unreportable (${shortfall > 0 ? `${shortfall} NEITHER billed nor accounted for` : `${-shortfall} billed in EXCESS`}). ` +\n `The per-group errors above name which groups; every row left pending stays selectable by the next run.`,\n );\n }\n\n this.flushProductCache = undefined;\n this.flushPeriodCache = undefined;\n\n this.logDebug('Usage flush complete', { ...result });\n return result;\n }\n\n // ════════════════════════════════════════════════════════════\n // Private — Flush per scope\n // ════════════════════════════════════════════════════════════\n\n private async flushScopeToProvider(variants: BillingResolvedVariants, result: UsageFlushResult): Promise<void> {\n const pending = await this.listAllUnreportedRecords(variants, result);\n if (pending.length === 0) return;\n\n const records = await this.selectDueRecords(pending);\n result.totalRecords += records.length;\n for (const record of records) result.quantityRecorded += record.quantity;\n\n if (records.length === 0) return;\n\n const groups = await this.buildFlushGroups(variants, records);\n\n for (const group of groups) {\n await this.reportGroup(variants, group, result);\n }\n }\n\n /**\n * Page through EVERY unreported row in this scope.\n *\n * The whole set is read before anything is reported, because aggregation is defined over the whole\n * pending set and a page is not a meaningful unit of it.\n *\n * This replaced a single `{ limit: 10000 }` (#415). That cap did not fail when it was reached — it\n * returned the first ten thousand rows and the run looked healthy, so the eleven-thousandth unit of\n * usage was simply never billed and nothing anywhere said so. A cap that is reached is money not\n * billed; the only honest cap is one that REFUSES.\n */\n private async listAllUnreportedRecords(\n variants: BillingResolvedVariants,\n result: UsageFlushResult,\n ): Promise<UsageRecord[]> {\n const listCtx = await this.internalCtx(variants.usageRecord as CoreResourceType, CoreResourceOperation.LIST);\n const collected: UsageRecord[] = [];\n\n for (let page = 1; page <= UsageMeteringBackendService.MAX_FLUSH_PAGES; page += 1) {\n const pageRecords = await this.servicesRegistry.list<UsageRecord>(\n variants.usageRecord as CoreResourceType,\n listCtx,\n { flushState: UsageRecordFlushState.PENDING },\n { page, limit: UsageMeteringBackendService.FLUSH_PAGE_SIZE },\n ) as UsageRecord[];\n\n collected.push(...pageRecords);\n if (pageRecords.length < UsageMeteringBackendService.FLUSH_PAGE_SIZE) return collected;\n }\n\n /*\n * The runaway guard, and it reports NOTHING rather than reporting what it has. A partial flush\n * would mark those rows reported and leave the rest for a next run that would hit the same wall,\n * so the backlog would never drain while every run looked partially successful. Refusing keeps\n * every row selectable and puts a human in front of the reason.\n */\n result.errors.push(\n `FLUSH ABORTED for scope ${variants.scopeType}: more than ` +\n `${UsageMeteringBackendService.MAX_FLUSH_PAGES * UsageMeteringBackendService.FLUSH_PAGE_SIZE} unreported usage rows. ` +\n `Nothing was reported for this scope — every row remains pending. This is a backlog, not a spike: ` +\n `investigate why the scheduled flush stopped running before draining it.`,\n );\n return [];\n }\n\n /**\n * Keep only the rows whose PRODUCT is due to be flushed, per its authored `flushIntervalMinutes`\n * (#415).\n *\n * The field means \"usage for this product should reach the provider within N minutes of being\n * recorded\", so a product is due when its OLDEST pending row has waited that long. Derived from the\n * rows already in hand — no last-flush timestamp is stored anywhere, because storing one would be a\n * second source of truth for something the rows already say, and one that can go stale.\n *\n * The batch runs on a cadence at least as fast as the shortest interval any product can author; this\n * is what turns one shared schedule into per-product intervals. A product authoring 1440 accumulates\n * for a day and produces one provider event instead of 288, which is what its author asked for.\n *\n * Note the ASYMMETRY, and it is deliberate: waiting is per product, but once ONE product is due its\n * rows go now rather than at the next tick. Reporting sooner than authored is never wrong; later is.\n */\n private async selectDueRecords(records: UsageRecord[]): Promise<UsageRecord[]> {\n const oldestByProduct = new Map<string, number>();\n for (const record of records) {\n const at = (record.timestamp instanceof Date ? record.timestamp : new Date(record.timestamp)).getTime();\n const seen = oldestByProduct.get(record.productKey);\n if (seen === undefined || at < seen) oldestByProduct.set(record.productKey, at);\n }\n\n const now = Date.now();\n const dueProducts = new Set<string>();\n for (const [productKey, oldest] of oldestByProduct) {\n const policy = await this.resolveMeteringPolicy(productKey);\n const intervalMinutes = policy?.flushIntervalMinutes;\n // No authored policy means no authored patience: flush it on this tick, which is what every\n // product did before the field was read.\n if (intervalMinutes === undefined || now - oldest >= intervalMinutes * 60_000) {\n dueProducts.add(productKey);\n }\n }\n\n return records.filter((record) => dueProducts.has(record.productKey));\n }\n\n // ════════════════════════════════════════════════════════════\n // Private — Grouping (the authored metering policy is READ here)\n // ════════════════════════════════════════════════════════════\n\n /**\n * Turn pending rows into the groups that will each become one provider meter event, honouring the\n * product's authored `metering` policy (#415).\n *\n * Until this existed the policy block was declared, defaulted, documented and read by NOTHING: every\n * row was merged by (account, product) whatever the product said, so `preFlushAggregation: false`\n * was unrepresentable and `aggregationWindow` chose between two behaviours that were the same one.\n * Its own JSDoc said so and asked that the gap stay visible, which is why this comment says what\n * replaced it.\n *\n * The policy is per PRODUCT, so two products flushing in the same run are grouped by their own\n * rules — that is why the policy is resolved inside the loop rather than once for the run.\n */\n private async buildFlushGroups(\n variants: BillingResolvedVariants,\n records: UsageRecord[],\n ): Promise<UsageFlushGroup[]> {\n const billingAccountFk = variants.billingAccountFkField;\n const grouped = new Map<string, UsageFlushGroup>();\n const ungrouped: UsageFlushGroup[] = [];\n\n for (const record of records) {\n const billingAccountId = (record as unknown as Record<string, string>)[billingAccountFk];\n const timestamp = record.timestamp instanceof Date ? record.timestamp : new Date(record.timestamp);\n const policy = await this.resolveMeteringPolicy(record.productKey);\n\n /*\n * `preFlushAggregation: false` means exactly what it says: report each row on its own. It is the\n * shape a product picks when the provider must see every event — because the provider's own\n * aggregation differs from a sum, or because each event carries a distinct instant. Merging\n * locally destroys both, irreversibly, before the provider ever sees them.\n */\n if (policy?.preFlushAggregation === false) {\n ungrouped.push({\n billingAccountId,\n productKey: record.productKey,\n quantity: record.quantity,\n recordIds: [record._id],\n latestTimestamp: timestamp,\n });\n continue;\n }\n\n /*\n * `PER_BILLING_PERIOD` splits a group at a billing-period boundary. It is not a preference: a\n * merged group carries ONE timestamp, and the provider assigns a meter event to the period that\n * timestamp falls in — so merging across a boundary bills a whole period's usage into the wrong\n * period. `PER_FLUSH` merges everything pending, which is right when a product's periods do not\n * matter to how it is priced.\n */\n const periodStart = policy?.aggregationWindow === MeteringAggregationWindow.PER_BILLING_PERIOD\n ? await this.resolvePeriodStartFor(variants, billingAccountId, record.productKey, timestamp)\n : undefined;\n\n const key = `${billingAccountId}::${record.productKey}::${periodStart?.toISOString() ?? 'all'}`;\n const existing = grouped.get(key);\n if (existing) {\n existing.quantity += record.quantity;\n existing.recordIds.push(record._id);\n if (timestamp > existing.latestTimestamp) existing.latestTimestamp = timestamp;\n } else {\n grouped.set(key, {\n billingAccountId,\n productKey: record.productKey,\n quantity: record.quantity,\n recordIds: [record._id],\n latestTimestamp: timestamp,\n periodStart,\n });\n }\n }\n\n return [...grouped.values(), ...ungrouped];\n }\n\n // ════════════════════════════════════════════════════════════\n // Private — Reporting one group\n // ════════════════════════════════════════════════════════════\n\n private async reportGroup(\n variants: BillingResolvedVariants,\n group: UsageFlushGroup,\n result: UsageFlushResult,\n ): Promise<void> {\n try {\n const { accountExists, providerCustomerId } = await this.resolveProviderCustomer(variants, group.billingAccountId);\n\n /*\n * The billing account is GONE — permanent, and the reason the rows get a terminal state\n * instead of another failure count (#512). Usage rows are RETAINED when their subject is\n * erased, so this is a designed outcome rather than corruption; what was not designed was the\n * flush treating it as retryable, which re-selected the same rows on every five-minute run,\n * failed identically, and grew an error backlog no operator action could drain.\n */\n if (!accountExists) {\n result.errors.push(\n `UNREPORTABLE — billing account ${group.billingAccountId} no longer exists (scope: ${variants.scopeType}), so ` +\n `${group.quantity} unit(s) of ${group.productKey} usage across ${group.recordIds.length} record(s) can never be ` +\n `reported. The rows are RETAINED for the tax/audit obligation and are being marked unreportable so the flush ` +\n `stops re-selecting them.`,\n );\n await this.markGroupUnreportable(variants, group, UsageRecordUnreportableReason.BILLING_ACCOUNT_DELETED, result);\n return;\n }\n\n /*\n * The account exists but has no provider customer yet — TRANSIENT. Provisioning may still\n * complete, so the rows stay pending and this stays a failure. Do not be tempted to reuse the\n * terminal state here: it would abandon billable usage the moment a flush overtook an\n * in-progress customer creation.\n */\n if (!providerCustomerId) {\n result.errors.push(`No provider customer ID for billing account ${group.billingAccountId} (scope: ${variants.scopeType})`);\n result.failed += group.recordIds.length;\n return;\n }\n\n const policy = await this.resolveMeteringPolicy(group.productKey);\n\n /*\n * The meterEventName is derived from the product key.\n * Convention: product key IS the meter event name (configured when creating the meter in Stripe).\n *\n * `timestamp` and `identifier` were BOTH omitted until 2026-09-08 (#415), and each omission was\n * its own defect:\n *\n * - Without a timestamp the provider stamps the event with the moment the FLUSH ran, so usage\n * recorded before a period boundary and flushed after it is billed to the wrong period. Every\n * metered product was exposed to that, on every run that crossed a boundary.\n * - Without an identifier a re-report is a SECOND charge. The whole duplicate-charge apparatus\n * below exists because of that, and an identifier is the provider's own answer to it: a meter\n * event carrying one that has already been seen is discarded. So a re-report of an identical\n * group is now a no-op at the provider rather than money moving twice — which is a far better\n * property than detecting the risk after the fact.\n *\n * The identifier is DERIVED FROM THE ROWS, not from the attempt, so a retry of the same group\n * sends the same identifier while a genuinely different group cannot collide with it.\n */\n await this.reportWithRetry(policy, {\n meterEventName: group.productKey,\n providerCustomerId,\n value: group.quantity,\n timestamp: group.latestTimestamp,\n identifier: this.buildUsageEventIdentifier(variants, group),\n });\n\n // Bulk-mark all records in this group as reported (single DB call).\n //\n // The `reportUsage` above ALREADY moved money — it is not retryable-for-free. The marking is\n // what stops the next sweep from re-reporting the same usage, because the sweep selects on\n // `flushState: pending`. So a PARTIAL marking is a duplicate-charge condition: any record\n // that stayed unmarked will be picked up again and billed to the customer a second time.\n //\n // Honour `modifiedCount` rather than assuming success. Previously the return value was\n // discarded and `result.reported` was incremented by the full group size, which made a partial\n // marking both invisible and unfalsifiable — the operational counter reported success for\n // records that were about to be re-billed.\n const markedCount = await this.repositoriesRegistry.bulkUpdateForInfrastructure(\n variants.usageRecord,\n { _id: { $in: group.recordIds } },\n // The adapter-neutral guarded-mutation descriptor. This was `{ $set: … }` — raw MongoDB —\n // until `bulkUpdateForInfrastructure` became adapter-neutral; on a PostgreSQL-backed usage\n // record the old path threw before marking anything, which is the duplicate-charge\n // condition the block below exists to detect.\n { set: { flushState: UsageRecordFlushState.REPORTED, reportedAt: new Date() } },\n );\n\n // Reported is reported: the provider has the quantity whatever the marking did.\n result.quantityReported += group.quantity;\n\n const unmarkedCount = group.recordIds.length - markedCount;\n if (unmarkedCount > 0) {\n /*\n * Still loud, and still not a \"retry me\" — but no longer a duplicate CHARGE, because the\n * identifier above makes the provider discard a repeat of this exact group. What survives is a\n * repeat of a DIFFERENT group: the next sweep re-selects the unmarked rows, and if new usage\n * has arrived meanwhile it aggregates them together into a group with a different identifier,\n * which the provider will accept. So this is still an operator's problem, one step less severe.\n */\n result.errors.push(\n `PARTIAL MARKING — ${group.billingAccountId}/${group.productKey} (scope: ${variants.scopeType}): ` +\n `usage of ${group.quantity} was REPORTED to the provider, but only ${markedCount}/${group.recordIds.length} ` +\n `records could be marked as reported. A re-report of this exact group is idempotent at the provider ` +\n `(same event identifier), but the next sweep may aggregate the ${unmarkedCount} unmarked record(s) with ` +\n `NEW usage into a different group, which would be accepted and double-count them. Mark them manually.`,\n );\n result.failed += unmarkedCount;\n }\n\n result.reported += markedCount;\n } catch (error) {\n result.errors.push(`${group.billingAccountId}/${group.productKey} (scope: ${variants.scopeType}): ${(error as Error).message}`);\n result.failed += group.recordIds.length;\n }\n }\n\n /**\n * Report one meter event, honouring the product's authored `retryPolicy` (#415).\n *\n * `maxRetries` and `backoffMultiplier` were authored, defaulted and read by nothing — a provider\n * blip failed the whole group and left it for the next scheduled run, which on a 60-minute schedule\n * is an hour of unbilled usage for a fault that would have cleared in a second.\n *\n * The retry is SAFE only because of the idempotency identifier the caller supplies: a retry after a\n * response that was lost in transit re-sends the same identifier, and the provider discards it. Retry\n * without that is how a timeout becomes a double charge, which is why the two landed together.\n */\n private async reportWithRetry(\n policy: ProductBehaviorPolicy['metering'] | undefined,\n request: StandardBilling_ReportUsageRequest,\n ): Promise<void> {\n const maxRetries = Math.max(0, policy?.retryPolicy?.maxRetries ?? 0);\n const backoffMultiplier = policy?.retryPolicy?.backoffMultiplier ?? 2;\n\n let attempt = 0;\n for (;;) {\n try {\n await this.billingProvider!.reportUsage(request);\n return;\n } catch (error) {\n if (attempt >= maxRetries) throw error;\n const delayMs = UsageMeteringBackendService.RETRY_BASE_DELAY_MS * Math.pow(backoffMultiplier, attempt);\n this.logger.warn('Usage report failed, retrying', {\n meterEventName: request.meterEventName,\n attempt: attempt + 1,\n maxRetries,\n delayMs,\n });\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n attempt += 1;\n }\n }\n }\n\n /**\n * A stable, bounded idempotency key for one meter event.\n *\n * Derived from the ROWS the event carries — sorted, so ordering cannot change it — and hashed, so a\n * group of ten thousand rows produces the same short key as a group of one. Two different groups\n * cannot collide; the same group retried, or re-reported after a partial marking, produces the same\n * key and the provider discards the repeat.\n */\n private buildUsageEventIdentifier(variants: BillingResolvedVariants, group: UsageFlushGroup): string {\n const material = [\n variants.scopeType,\n group.billingAccountId,\n group.productKey,\n ...[...group.recordIds].sort(),\n ].join('|');\n return `wildo-usage-${createHash('sha256').update(material).digest('hex').slice(0, 32)}`;\n }\n\n // ════════════════════════════════════════════════════════════\n // Private — Policy and period resolution (per-run cached)\n // ════════════════════════════════════════════════════════════\n\n /** The product's authored metering policy, or `undefined` when it authored none. */\n private async resolveMeteringPolicy(productKey: string): Promise<ProductBehaviorPolicy['metering'] | undefined> {\n const cached = this.flushProductCache?.get(productKey);\n if (cached !== undefined) return cached ?? undefined;\n\n const ctx = await this.internalCtx(CoreResourceType.PRODUCTS, CoreResourceOperation.LIST);\n let policy: ProductBehaviorPolicy['metering'] | undefined;\n try {\n const products = await this.servicesRegistry.list<Product>(\n CoreResourceType.PRODUCTS, ctx, { key: productKey }, { page: 1, limit: 1 },\n ) as Product[];\n policy = products[0]?.behaviorPolicy?.metering;\n } catch (error) {\n // A policy that cannot be read is not a reason to stop billing: fall through to the merged\n // default, which is what every product got before the policy was read at all.\n this.logger.warn('Failed to read metering policy; flushing this product with default aggregation', {\n productKey,\n message: (error as Error).message,\n });\n }\n\n this.flushProductCache?.set(productKey, policy ?? null);\n return policy;\n }\n\n /**\n * The start of the billing period containing `timestamp`, for `PER_BILLING_PERIOD` grouping.\n *\n * Derived from the subscription's own `currentPeriodStart` / `currentPeriodEnd` — real data, not a\n * calendar rule invented here — stepping backwards by the period's own length for usage older than\n * the current period. Returns `undefined` when no subscription can be resolved, which merges the\n * rows exactly as `PER_FLUSH` would: an unknown boundary must not silently invent one.\n */\n private async resolvePeriodStartFor(\n variants: BillingResolvedVariants,\n billingAccountId: string,\n productKey: string,\n timestamp: Date,\n ): Promise<Date | undefined> {\n const cacheKey = `${variants.scopeType}::${billingAccountId}`;\n let boundaries = this.flushPeriodCache?.get(cacheKey);\n\n if (boundaries === undefined) {\n boundaries = null;\n const ctx = await this.internalCtx(variants.subscription as CoreResourceType, CoreResourceOperation.LIST);\n try {\n const subscriptions = await this.servicesRegistry.list<BillingSubscriptionBase>(\n variants.subscription as CoreResourceType, ctx,\n {\n [variants.billingAccountFkField]: billingAccountId,\n status: { $in: [SubscriptionStatus.ACTIVE, SubscriptionStatus.TRIALING] },\n },\n ) as BillingSubscriptionBase[];\n const subscription = subscriptions[0];\n if (subscription?.currentPeriodStart && subscription?.currentPeriodEnd) {\n boundaries = {\n start: new Date(subscription.currentPeriodStart),\n end: new Date(subscription.currentPeriodEnd),\n };\n }\n } catch (error) {\n this.logger.warn('Failed to resolve billing period for per-period aggregation; merging as PER_FLUSH', {\n billingAccountId, productKey, message: (error as Error).message,\n });\n }\n this.flushPeriodCache?.set(cacheKey, boundaries);\n }\n\n if (!boundaries) return undefined;\n\n const periodLengthMs = boundaries.end.getTime() - boundaries.start.getTime();\n if (periodLengthMs <= 0) return boundaries.start;\n\n // Step backwards whole periods until the timestamp is inside one. Usage newer than the current\n // period end belongs to the current period — the subscription simply has not rolled over yet.\n let start = boundaries.start.getTime();\n while (timestamp.getTime() < start) start -= periodLengthMs;\n return new Date(start);\n }\n\n // ════════════════════════════════════════════════════════════\n // Private — Resolution\n // ════════════════════════════════════════════════════════════\n\n /**\n * Validate that the billing account has an active subscription containing\n * a metered product matching the given product key. Returns true as soon\n * as one matching item is found — the item identity is not needed because\n * the Billing Meter provider API routes usage by meterEventName + customer,\n * not by subscription item.\n */\n private async hasActiveMeteredSubscription(\n variants: BillingResolvedVariants,\n billingAccountId: string,\n productKey: string,\n ): Promise<boolean> {\n // Context construction stays OUTSIDE the guarded try: failing to resolve the\n // INTERNAL_CALL operation path is a wiring fault, never \"no metered subscription\".\n // Returning a masked `false` here silently stops metered usage from being\n // recorded — a billing-correctness failure, not a display one.\n const subsCtx = await this.internalCtx(variants.subscription as CoreResourceType, CoreResourceOperation.LIST);\n try {\n const subscriptions = await this.servicesRegistry.list<BillingSubscriptionBase>(variants.subscription as CoreResourceType, subsCtx, {\n [variants.billingAccountFkField]: billingAccountId,\n status: { $in: [SubscriptionStatus.ACTIVE, SubscriptionStatus.TRIALING] },\n }) as BillingSubscriptionBase[];\n\n for (const sub of subscriptions) {\n for (const item of sub.items) {\n const readCtx = await this.internalCtx(CoreResourceType.PRODUCTS, CoreResourceOperation.READ);\n try {\n const product = await this.servicesRegistry.read<Product>(CoreResourceType.PRODUCTS, readCtx, item.productId);\n if (product && product.key === productKey && product.type === ProductType.METERED) {\n return true;\n }\n } catch (error) {\n this.degradeOrRethrow(error, 'Failed to read product for metered item lookup', { productId: item.productId });\n continue;\n }\n }\n }\n } catch (error) {\n this.degradeOrRethrow(error, 'Failed to validate metered subscription', { billingAccountId, productKey });\n }\n return false;\n }\n\n /**\n * Resolve the provider customer for a billing account, distinguishing the two ways it can fail.\n *\n * This used to return `string | null`, and that single `null` fused a PERMANENT condition with a\n * TRANSIENT one (#512):\n *\n * - the account row is GONE — legitimately reachable, because usage rows are RETAINED when their\n * subject is erased, so a deleted account leaves rows behind. Nothing will ever restore the\n * mapping, and a flush that keeps retrying is building a backlog it cannot drain;\n * - the account EXISTS but carries no `providerCustomerId` yet — provisioning may still complete,\n * and abandoning those rows would throw away billable usage.\n *\n * They lead to opposite actions, so the caller must be able to tell them apart. Two plain fields\n * rather than a discriminated union deliberately: `engine/tsconfig.common.json` sets\n * `strict: false`, under which narrowing a union on a boolean-literal discriminant does not work,\n * and a caller that cannot narrow reads the wrong field with no diagnostic.\n *\n * A read that THROWS is treated as transient — `degradeOrRethrow` has already decided the error is\n * survivable, and a storage failure says nothing about whether the row exists.\n */\n private async resolveProviderCustomer(\n variants: BillingResolvedVariants,\n billingAccountId: string,\n ): Promise<{ accountExists: boolean; providerCustomerId: string | null }> {\n const readCtx = await this.internalCtx(variants.billingAccount as CoreResourceType, CoreResourceOperation.READ);\n try {\n const billingAccount = await this.servicesRegistry.read<{ providerCustomerId?: string }>(\n variants.billingAccount as CoreResourceType, readCtx, billingAccountId,\n );\n if (!billingAccount) return { accountExists: false, providerCustomerId: null };\n return { accountExists: true, providerCustomerId: billingAccount.providerCustomerId ?? null };\n } catch (error) {\n this.degradeOrRethrow(error, 'Failed to resolve provider customer ID', { billingAccountId, scope: variants.scopeType });\n }\n return { accountExists: true, providerCustomerId: null };\n }\n\n /**\n * Move a group's rows to the terminal `unreportable` state so the flush stops re-selecting them.\n *\n * NO money moved and none ever will, which is why this is its own state rather than a convenient\n * `reported: true`. The reason and the instant are written beside it, because the row is a\n * RETAINED financial record and the next reader of it — an auditor, an operator reconciling a\n * period — needs to know why a measured quantity was never billed.\n *\n * A marking that does not fully land is reported and NOT retried here: the rows that stayed\n * pending are simply selected again next run, which is harmless (unlike the reported case, where\n * a partial marking risks double-billing). The counters follow what the write actually did.\n */\n private async markGroupUnreportable(\n variants: BillingResolvedVariants,\n group: UsageFlushGroup,\n reason: UsageRecordUnreportableReason,\n result: UsageFlushResult,\n ): Promise<void> {\n const markedCount = await this.repositoriesRegistry.bulkUpdateForInfrastructure(\n variants.usageRecord,\n { _id: { $in: group.recordIds } },\n { set: { flushState: UsageRecordFlushState.UNREPORTABLE, unreportableReason: reason, unreportableAt: new Date() } },\n );\n\n result.unreportable += markedCount;\n result.quantityUnreportable += markedCount === group.recordIds.length\n ? group.quantity\n : 0;\n\n const unmarkedCount = group.recordIds.length - markedCount;\n if (unmarkedCount > 0) {\n /*\n * The quantity is credited only on a COMPLETE marking, above. A group's quantity is an\n * aggregate over its rows and this class does not carry per-row quantities into the group, so\n * a partial marking cannot be apportioned — and guessing would corrupt the reconciliation\n * identity in the direction that hides unbilled usage. The rows that stayed pending will be\n * re-selected, re-grouped and accounted for then.\n */\n result.errors.push(\n `PARTIAL UNREPORTABLE MARKING — ${group.billingAccountId}/${group.productKey} (scope: ${variants.scopeType}): ` +\n `only ${markedCount}/${group.recordIds.length} record(s) could be marked unreportable. The ${unmarkedCount} ` +\n `unmarked record(s) stay pending and will be re-selected next run; no usage was reported to the provider.`,\n );\n result.failed += unmarkedCount;\n }\n }\n}\n"]}
@@ -0,0 +1,36 @@
1
+ import type { StandardBilling_Interface } from '@wildo-ai/external-connectors-models';
2
+ /**
3
+ * What a billing adapter needs to exist: the provider's secret, and the optional wire-format pin
4
+ * the provider declared. Both come from the provider's own `kind: BILLING` runtime contract —
5
+ * `secretRef` resolved to a value, and `apiVersion` verbatim.
6
+ *
7
+ * An adapter that has no use for `apiVersion` ignores it; the contract's own JSDoc already says so
8
+ * ("Stripe uses this to lock the wire format; other billing adapters may ignore it").
9
+ */
10
+ export type BillingAdapterConstructionOptions = {
11
+ /** The resolved value of the contract's `secretRef` — never the ref itself. */
12
+ secretKey: string;
13
+ /** The contract's `apiVersion`, forwarded unchanged. `undefined` means the adapter's own default. */
14
+ apiVersion?: string;
15
+ };
16
+ /** Builds one `StandardBilling_Interface` implementation. Called once, at billing bootstrap. */
17
+ export type BillingAdapterFactory = (options: BillingAdapterConstructionOptions) => StandardBilling_Interface;
18
+ /**
19
+ * The adapter serving a provider that declares this `sdkPackage`, or `null` when the engine ships
20
+ * none.
21
+ *
22
+ * `null` is a first-class answer, not an error: it is what makes a second billing provider a
23
+ * legible REFUSAL at boot instead of a silent mis-binding. Before this seam existed, the resolution
24
+ * narrowed the contract to `kind: BILLING` and then constructed Stripe's adapter unconditionally,
25
+ * so a provider declaring `BILLING_PROVIDER` with any other SDK would have been handed Stripe's
26
+ * client built over ITS secret — every call reaching Stripe's API under the wrong credential, with
27
+ * nothing in the configuration, the logs or the types saying so.
28
+ */
29
+ export declare function resolveBillingAdapterFactory(sdkPackage: string): BillingAdapterFactory | null;
30
+ /**
31
+ * Every `sdkPackage` this engine ships an adapter for, sorted so a diagnostic reads the same way
32
+ * twice. Named in the refusal message, because "no adapter for X" is only actionable beside the
33
+ * set that would have worked.
34
+ */
35
+ export declare function listSupportedBillingSdkPackages(): readonly string[];
36
+ //# sourceMappingURL=billing-adapter-registry.backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing-adapter-registry.backend.d.ts","sourceRoot":"","sources":["../../../../../src/billing/services/billing-adapter-registry.backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAItF;;;;;;;GAOG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC5C,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB,qGAAqG;IACrG,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,gGAAgG;AAChG,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE,iCAAiC,KAAK,yBAAyB,CAAC;AA8D9G;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAE7F;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,SAAS,MAAM,EAAE,CAEnE"}
@@ -0,0 +1,83 @@
1
+ import { StripeStandardBillingProvider } from '../../billing/services/stripe-standard-billing-provider.backend.service.js';
2
+ /**
3
+ * The billing adapters this ENGINE ships, keyed by the `sdkPackage` their provider declares.
4
+ *
5
+ * ## Why a registry exists at all, and why it is keyed on `sdkPackage`
6
+ *
7
+ * The `kind: BILLING` runtime contract is the one protocol arm in this framework that is NOT
8
+ * self-describing. Its siblings each hand the engine enough to act:
9
+ *
10
+ * - `LLM` / `IMAGE` / `EMBEDDINGS` declare an `sdkFactory` returning the VENDOR's own AI-SDK
11
+ * client — a value that lives in an `@ai-sdk/*` package `external-connectors-private` already
12
+ * depends on, so the provider module can construct it;
13
+ * - `EMAIL` declares `buildSendRequest` / `parseResponse` — pure functions — and the ENGINE owns
14
+ * the transport;
15
+ * - `DOCUMENT_EXTRACTION` declares `baseUrl` + `endpointPath` and the engine issues the request.
16
+ *
17
+ * `BILLING` declares `secretRef`, `sdkPackage`, `apiVersion` and an operation list, and from that
18
+ * the engine cannot build anything: the standard billing interface is ~30 methods of Wildo-authored
19
+ * translation, not a vendor client and not a pair of request builders. So SOMETHING has to say
20
+ * which implementation serves a given provider, and there are exactly two places it can live.
21
+ *
22
+ * It cannot live on the provider module. `StripeStandardBillingProvider` is in
23
+ * `@wildo-ai/saas-backend-lib`, which DEPENDS ON `@wildo-ai/external-connectors-private`; a provider
24
+ * module constructing an adapter would need the reverse edge. That is why the `sdkFactory` this
25
+ * file replaces was proposed and never built (see the note at the resolution site) — the proposal
26
+ * predates nothing, it is simply not reachable in this dependency direction, and would require
27
+ * moving the adapter out of the engine that ships it.
28
+ *
29
+ * So it lives HERE, on the consumer side, as a REGISTRY rather than a branch. The distinction is
30
+ * the one `no-provider-ref-branches.guard.test.ts` is written around: a branch makes the engine
31
+ * behave differently for a named provider, while a registry answers "which of the implementations
32
+ * I ship serves this declaration". `EngineBackendProviderRegistry.modules` — a `Map` keyed by
33
+ * provider ref — is the same shape and the same reasoning.
34
+ *
35
+ * The key is `sdkPackage` because that field ALREADY decides this and nothing else read it. Before
36
+ * this file, `sdkPackage: "stripe"` was declared by the one billing provider, asserted truthy by
37
+ * one registry test, and consumed by no production code — a declaration with no reader. It is also
38
+ * the honest identity of an adapter: `StripeStandardBillingProvider` is precisely the code that
39
+ * knows how to drive the `stripe` npm package. A second declared field (`adapterRef`) was rejected
40
+ * for restating what `sdkPackage` already says, at the cost of an obligation on every future
41
+ * provider.
42
+ *
43
+ * ## The SDK stays undeclared, and this file must not change that
44
+ *
45
+ * `.claude/rules/toolchain-installation-baseline.md` records the deliberate posture: the engine
46
+ * ships the ADAPTER, not the provider's SDK, and no framework manifest declares `stripe`. This
47
+ * registry imports the adapter CLASS at module load, which is free — the class defers
48
+ * `require('stripe')` into `getStripe()`, called on the first API call and never at construction.
49
+ * Pinned by `billing-adapter-registry.test.ts`, which constructs the adapter through this registry
50
+ * in a workspace where `stripe` is not resolvable at all: an eager load would throw
51
+ * `MODULE_NOT_FOUND` there.
52
+ *
53
+ * Adding an adapter is one row here plus its class. Nothing else in the billing subsystem learns
54
+ * about it: every consumer — catalogue sync, usage metering, the reconciliation sweep, the webhook
55
+ * adapter, the subject-erasure effect, the custom implementations — is handed the resolved
56
+ * `StandardBilling_Interface` by the single bootstrap and never resolves one itself.
57
+ */
58
+ const ENGINE_BILLING_ADAPTERS = new Map([
59
+ ['stripe', ({ secretKey, apiVersion }) => new StripeStandardBillingProvider(secretKey, apiVersion)],
60
+ ]);
61
+ /**
62
+ * The adapter serving a provider that declares this `sdkPackage`, or `null` when the engine ships
63
+ * none.
64
+ *
65
+ * `null` is a first-class answer, not an error: it is what makes a second billing provider a
66
+ * legible REFUSAL at boot instead of a silent mis-binding. Before this seam existed, the resolution
67
+ * narrowed the contract to `kind: BILLING` and then constructed Stripe's adapter unconditionally,
68
+ * so a provider declaring `BILLING_PROVIDER` with any other SDK would have been handed Stripe's
69
+ * client built over ITS secret — every call reaching Stripe's API under the wrong credential, with
70
+ * nothing in the configuration, the logs or the types saying so.
71
+ */
72
+ export function resolveBillingAdapterFactory(sdkPackage) {
73
+ return ENGINE_BILLING_ADAPTERS.get(sdkPackage) ?? null;
74
+ }
75
+ /**
76
+ * Every `sdkPackage` this engine ships an adapter for, sorted so a diagnostic reads the same way
77
+ * twice. Named in the refusal message, because "no adapter for X" is only actionable beside the
78
+ * set that would have worked.
79
+ */
80
+ export function listSupportedBillingSdkPackages() {
81
+ return [...ENGINE_BILLING_ADAPTERS.keys()].sort();
82
+ }
83
+ //# sourceMappingURL=billing-adapter-registry.backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing-adapter-registry.backend.js","sourceRoot":"","sources":["../../../../../src/billing/services/billing-adapter-registry.backend.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,6BAA6B,EAAE,MAAM,sFAAsF,CAAC;AAoBrI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,uBAAuB,GAA+C,IAAI,GAAG,CAAgC;IAC/G,CAAC,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,IAAI,6BAA6B,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;CACtG,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,4BAA4B,CAAC,UAAkB;IAC3D,OAAO,uBAAuB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B;IAC3C,OAAO,CAAC,GAAG,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACtD,CAAC","sourcesContent":["import type { StandardBilling_Interface } from '@wildo-ai/external-connectors-models';\n\nimport { StripeStandardBillingProvider } from '~wildo-backend-lib/billing/services/stripe-standard-billing-provider.backend.service';\n\n/**\n * What a billing adapter needs to exist: the provider's secret, and the optional wire-format pin\n * the provider declared. Both come from the provider's own `kind: BILLING` runtime contract —\n * `secretRef` resolved to a value, and `apiVersion` verbatim.\n *\n * An adapter that has no use for `apiVersion` ignores it; the contract's own JSDoc already says so\n * (\"Stripe uses this to lock the wire format; other billing adapters may ignore it\").\n */\nexport type BillingAdapterConstructionOptions = {\n /** The resolved value of the contract's `secretRef` — never the ref itself. */\n secretKey: string;\n /** The contract's `apiVersion`, forwarded unchanged. `undefined` means the adapter's own default. */\n apiVersion?: string;\n};\n\n/** Builds one `StandardBilling_Interface` implementation. Called once, at billing bootstrap. */\nexport type BillingAdapterFactory = (options: BillingAdapterConstructionOptions) => StandardBilling_Interface;\n\n/**\n * The billing adapters this ENGINE ships, keyed by the `sdkPackage` their provider declares.\n *\n * ## Why a registry exists at all, and why it is keyed on `sdkPackage`\n *\n * The `kind: BILLING` runtime contract is the one protocol arm in this framework that is NOT\n * self-describing. Its siblings each hand the engine enough to act:\n *\n * - `LLM` / `IMAGE` / `EMBEDDINGS` declare an `sdkFactory` returning the VENDOR's own AI-SDK\n * client — a value that lives in an `@ai-sdk/*` package `external-connectors-private` already\n * depends on, so the provider module can construct it;\n * - `EMAIL` declares `buildSendRequest` / `parseResponse` — pure functions — and the ENGINE owns\n * the transport;\n * - `DOCUMENT_EXTRACTION` declares `baseUrl` + `endpointPath` and the engine issues the request.\n *\n * `BILLING` declares `secretRef`, `sdkPackage`, `apiVersion` and an operation list, and from that\n * the engine cannot build anything: the standard billing interface is ~30 methods of Wildo-authored\n * translation, not a vendor client and not a pair of request builders. So SOMETHING has to say\n * which implementation serves a given provider, and there are exactly two places it can live.\n *\n * It cannot live on the provider module. `StripeStandardBillingProvider` is in\n * `@wildo-ai/saas-backend-lib`, which DEPENDS ON `@wildo-ai/external-connectors-private`; a provider\n * module constructing an adapter would need the reverse edge. That is why the `sdkFactory` this\n * file replaces was proposed and never built (see the note at the resolution site) — the proposal\n * predates nothing, it is simply not reachable in this dependency direction, and would require\n * moving the adapter out of the engine that ships it.\n *\n * So it lives HERE, on the consumer side, as a REGISTRY rather than a branch. The distinction is\n * the one `no-provider-ref-branches.guard.test.ts` is written around: a branch makes the engine\n * behave differently for a named provider, while a registry answers \"which of the implementations\n * I ship serves this declaration\". `EngineBackendProviderRegistry.modules` — a `Map` keyed by\n * provider ref — is the same shape and the same reasoning.\n *\n * The key is `sdkPackage` because that field ALREADY decides this and nothing else read it. Before\n * this file, `sdkPackage: \"stripe\"` was declared by the one billing provider, asserted truthy by\n * one registry test, and consumed by no production code — a declaration with no reader. It is also\n * the honest identity of an adapter: `StripeStandardBillingProvider` is precisely the code that\n * knows how to drive the `stripe` npm package. A second declared field (`adapterRef`) was rejected\n * for restating what `sdkPackage` already says, at the cost of an obligation on every future\n * provider.\n *\n * ## The SDK stays undeclared, and this file must not change that\n *\n * `.claude/rules/toolchain-installation-baseline.md` records the deliberate posture: the engine\n * ships the ADAPTER, not the provider's SDK, and no framework manifest declares `stripe`. This\n * registry imports the adapter CLASS at module load, which is free — the class defers\n * `require('stripe')` into `getStripe()`, called on the first API call and never at construction.\n * Pinned by `billing-adapter-registry.test.ts`, which constructs the adapter through this registry\n * in a workspace where `stripe` is not resolvable at all: an eager load would throw\n * `MODULE_NOT_FOUND` there.\n *\n * Adding an adapter is one row here plus its class. Nothing else in the billing subsystem learns\n * about it: every consumer — catalogue sync, usage metering, the reconciliation sweep, the webhook\n * adapter, the subject-erasure effect, the custom implementations — is handed the resolved\n * `StandardBilling_Interface` by the single bootstrap and never resolves one itself.\n */\nconst ENGINE_BILLING_ADAPTERS: ReadonlyMap<string, BillingAdapterFactory> = new Map<string, BillingAdapterFactory>([\n ['stripe', ({ secretKey, apiVersion }) => new StripeStandardBillingProvider(secretKey, apiVersion)],\n]);\n\n/**\n * The adapter serving a provider that declares this `sdkPackage`, or `null` when the engine ships\n * none.\n *\n * `null` is a first-class answer, not an error: it is what makes a second billing provider a\n * legible REFUSAL at boot instead of a silent mis-binding. Before this seam existed, the resolution\n * narrowed the contract to `kind: BILLING` and then constructed Stripe's adapter unconditionally,\n * so a provider declaring `BILLING_PROVIDER` with any other SDK would have been handed Stripe's\n * client built over ITS secret — every call reaching Stripe's API under the wrong credential, with\n * nothing in the configuration, the logs or the types saying so.\n */\nexport function resolveBillingAdapterFactory(sdkPackage: string): BillingAdapterFactory | null {\n return ENGINE_BILLING_ADAPTERS.get(sdkPackage) ?? null;\n}\n\n/**\n * Every `sdkPackage` this engine ships an adapter for, sorted so a diagnostic reads the same way\n * twice. Named in the refusal message, because \"no adapter for X\" is only actionable beside the\n * set that would have worked.\n */\nexport function listSupportedBillingSdkPackages(): readonly string[] {\n return [...ENGINE_BILLING_ADAPTERS.keys()].sort();\n}\n"]}
@@ -81,6 +81,13 @@ export type BillingCheckoutMetadataOutcome = {
81
81
  productKey: string;
82
82
  /** A validated integer in `[1, BILLING_CHECKOUT_MAX_QUANTITY]`. Defaults to 1 when unstated. */
83
83
  quantity: number;
84
+ /**
85
+ * The promotion the framework validated when it opened this session, if any (#518).
86
+ *
87
+ * Undefined for the common case of a purchase with no code. Read back rather than validated —
88
+ * see the note at the read site for why this one field does not refuse.
89
+ */
90
+ promotionId?: string;
84
91
  } | {
85
92
  kind: BillingCheckoutMetadataOutcomeKind.NOT_FRAMEWORK_ORIGINATED;
86
93
  } | {
@@ -107,6 +114,8 @@ export declare function buildCheckoutSessionMetadata(params: {
107
114
  billingAccountId: string;
108
115
  productKey: string;
109
116
  quantity: number;
117
+ /** The validated promotion applied to this checkout, if any — counted when the session completes (#518). */
118
+ promotionId?: string;
110
119
  callerMetadata?: Record<string, string>;
111
120
  }): Record<string, string>;
112
121
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"billing-checkout-metadata.backend.utils.d.ts","sourceRoot":"","sources":["../../../../../src/billing/services/billing-checkout-metadata.backend.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAWH;;;;;;;GAOG;AACH,oBAAY,kCAAkC;IAC5C,iFAAiF;IACjF,QAAQ,aAAa;IACrB,8FAA8F;IAC9F,wBAAwB,6BAA6B;IACrD,mEAAmE;IACnE,OAAO,YAAY;CACpB;AAED,2FAA2F;AAC3F,oBAAY,8BAA8B;IACxC,uGAAuG;IACvG,mBAAmB,wBAAwB;IAC3C,gGAAgG;IAChG,+BAA+B,oCAAoC;IACnE,6EAA6E;IAC7E,sBAAsB,2BAA2B;IACjD;;;;OAIG;IACH,wBAAwB,6BAA6B;CACtD;AAED,MAAM,MAAM,8BAA8B,GACtC;IACE,IAAI,EAAE,kCAAkC,CAAC,QAAQ,CAAC;IAClD,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,QAAQ,EAAE,MAAM,CAAC;CAClB,GACD;IAAE,IAAI,EAAE,kCAAkC,CAAC,wBAAwB,CAAA;CAAE,GACrE;IACE,IAAI,EAAE,kCAAkC,CAAC,OAAO,CAAC;IACjD,MAAM,EAAE,8BAA8B,CAAC;IACvC,4FAA4F;IAC5F,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEN;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE;IACnD,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAazB;AAED;;;;;;;GAOG;AACH,oBAAY,yBAAyB;IACnC,uFAAuF;IACvF,OAAO,YAAY;IACnB,0FAA0F;IAC1F,UAAU,eAAe;CAC1B;AAED,MAAM,MAAM,yBAAyB,GACjC;IAAE,OAAO,EAAE,yBAAyB,CAAC,OAAO,CAAA;CAAE,GAC9C;IAAE,OAAO,EAAE,yBAAyB,CAAC,UAAU,CAAC;IAAC,wBAAwB,EAAE,MAAM,CAAA;CAAE,CAAC;AAExF;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC5C,6BAA6B,EAAE,MAAM,GACpC,yBAAyB,CAM3B;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC5C,6BAA6B,EAAE,MAAM,GACpC,8BAA8B,CAkEhC"}
1
+ {"version":3,"file":"billing-checkout-metadata.backend.utils.d.ts","sourceRoot":"","sources":["../../../../../src/billing/services/billing-checkout-metadata.backend.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAWH;;;;;;;GAOG;AACH,oBAAY,kCAAkC;IAC5C,iFAAiF;IACjF,QAAQ,aAAa;IACrB,8FAA8F;IAC9F,wBAAwB,6BAA6B;IACrD,mEAAmE;IACnE,OAAO,YAAY;CACpB;AAED,2FAA2F;AAC3F,oBAAY,8BAA8B;IACxC,uGAAuG;IACvG,mBAAmB,wBAAwB;IAC3C,gGAAgG;IAChG,+BAA+B,oCAAoC;IACnE,6EAA6E;IAC7E,sBAAsB,2BAA2B;IACjD;;;;OAIG;IACH,wBAAwB,6BAA6B;CACtD;AAED,MAAM,MAAM,8BAA8B,GACtC;IACE,IAAI,EAAE,kCAAkC,CAAC,QAAQ,CAAC;IAClD,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACD;IAAE,IAAI,EAAE,kCAAkC,CAAC,wBAAwB,CAAA;CAAE,GACrE;IACE,IAAI,EAAE,kCAAkC,CAAC,OAAO,CAAC;IACjD,MAAM,EAAE,8BAA8B,CAAC;IACvC,4FAA4F;IAC5F,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEN;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE;IACnD,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,4GAA4G;IAC5G,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAezB;AAED;;;;;;;GAOG;AACH,oBAAY,yBAAyB;IACnC,uFAAuF;IACvF,OAAO,YAAY;IACnB,0FAA0F;IAC1F,UAAU,eAAe;CAC1B;AAED,MAAM,MAAM,yBAAyB,GACjC;IAAE,OAAO,EAAE,yBAAyB,CAAC,OAAO,CAAA;CAAE,GAC9C;IAAE,OAAO,EAAE,yBAAyB,CAAC,UAAU,CAAC;IAAC,wBAAwB,EAAE,MAAM,CAAA;CAAE,CAAC;AAExF;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC5C,6BAA6B,EAAE,MAAM,GACpC,yBAAyB,CAM3B;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAC5C,6BAA6B,EAAE,MAAM,GACpC,8BAA8B,CA2EhC"}
@@ -103,6 +103,8 @@ export function buildCheckoutSessionMetadata(params) {
103
103
  [BillingCheckoutMetadataKey.BILLING_ACCOUNT_ID]: params.billingAccountId,
104
104
  [BillingCheckoutMetadataKey.PRODUCT_KEY]: params.productKey,
105
105
  [BillingCheckoutMetadataKey.QUANTITY]: String(params.quantity),
106
+ // Only when a validated promotion was applied; absent is the common case (#518).
107
+ ...(params.promotionId ? { [BillingCheckoutMetadataKey.PROMOTION_ID]: params.promotionId } : {}),
106
108
  };
107
109
  }
108
110
  /**
@@ -207,6 +209,14 @@ export function resolveCheckoutSessionMetadata(metadata, authoritativeBillingAcc
207
209
  };
208
210
  }
209
211
  }
210
- return { kind: BillingCheckoutMetadataOutcomeKind.ACCEPTED, productKey, quantity };
212
+ /*
213
+ * The promotion is read back but NOT validated here, deliberately (#518). Every other field in this
214
+ * function gates a GRANT — credits, a product — so a bad one must refuse. This one gates a COUNTER
215
+ * increment that is itself guarded by a compare-and-swap against `maxRedemptions`, so the worst a
216
+ * tampered value can do is count one redemption against a promotion that had room for it. Refusing
217
+ * the whole session over it would turn a counting problem into a customer who paid and got nothing.
218
+ */
219
+ const promotionId = metadata[BillingCheckoutMetadataKey.PROMOTION_ID];
220
+ return { kind: BillingCheckoutMetadataOutcomeKind.ACCEPTED, productKey, quantity, promotionId };
211
221
  }
212
222
  //# sourceMappingURL=billing-checkout-metadata.backend.utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"billing-checkout-metadata.backend.utils.js","sourceRoot":"","sources":["../../../../../src/billing/services/billing-checkout-metadata.backend.utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Provider checkout metadata — the producer/consumer trust boundary.\n *\n * ## The defect this module exists to close\n *\n * `OPEN_CHECKOUT` builds a provider checkout session and attaches a `metadata` map. The provider\n * echoes that map back, VERBATIM, inside a genuinely signed `checkout.session.completed` webhook,\n * and the webhook router used to read `billingAccountId` / `quantity` straight out of it and call\n * `CreditPool_Operations.TOP_UP`.\n *\n * The map, however, was assembled as `{ billingAccountId, productKey, ...quantity, ...input.metadata }`\n * — caller metadata spread LAST — and `input.metadata` is a free-form `Record<string, string>` on an\n * operation reachable by `ORG_OWNER`, `ORG_ADMIN` and `APP_USER`. So any caller could overwrite all\n * three authoritative entries, complete a real payment, and have the provider sign their values back\n * to us. **No signature forgery is involved at any point**, which is exactly why the signature check\n * upstream is no defence: a valid signature proves the PROVIDER sent the bytes, never that the\n * FRAMEWORK wrote them.\n *\n * Three further consequences lived in the same five lines, all confirmed by executing the original\n * expression `(metadata.quantity ? Number(metadata.quantity) : undefined) ?? 1`:\n * - `\"abc\"` yields `NaN` — the `?? 1` fallback is dead because `NaN` is not nullish — and `NaN`\n * reached `{ increment: { available: NaN } }`, permanently corrupting the balance;\n * - `\"1e9\"` yields 1000000000 with no upper bound;\n * - `\"-5\"` yields -5, a top-up that DEBITS.\n *\n * ## The shape of the fix\n *\n * Reordering the spread would close the immediate hole and leave the underlying one: an unmarked\n * namespace in which the next authoritative key is one careless line from being overridable again.\n * So the boundary is made a property of the KEY (see `BILLING_RESERVED_METADATA_KEY_PREFIX`) and\n * enforced at three points that each fail independently:\n *\n * 1. **The request DTO refuses** caller keys in the reserved namespace — loud, at the outer edge.\n * 2. **{@link buildCheckoutSessionMetadata} writes reserved entries LAST** and strips reserved keys\n * out of caller metadata — structural, so a future edit cannot reintroduce the ordering bug, and\n * an internal caller that constructs the input object directly (bypassing the DTO) is covered too.\n * 3. **{@link resolveCheckoutSessionMetadata} treats the echoed map as UNTRUSTED INPUT** — it reads\n * only reserved keys, strictly parses and bounds the quantity, and REQUIRES the caller to supply\n * the provider-authoritative billing account id so the echoed one can only ever be cross-checked,\n * never used.\n *\n * Point 3 is why the resolver takes the authoritative id as a parameter rather than returning the\n * echoed one for the caller to compare: a consumer cannot obtain the parsed values without having\n * already resolved the account from provider truth. The invariant is unbypassable instead of\n * hand-applied at each of the router's handlers.\n */\n\nimport {\n BILLING_CHECKOUT_MAX_QUANTITY,\n BILLING_RESERVED_METADATA_KEY_PREFIX,\n BillingCheckoutMetadataKey,\n} from '@wildo-ai/saas-models';\n\n/** Decimal integer, nothing else. Rejects `\"abc\"`, `\"-5\"`, `\"1e9\"`, `\"1.5\"`, `\"0x10\"`, `\" 1\"`, `\"\"`. */\nconst STRICT_POSITIVE_INTEGER = /^[0-9]+$/;\n\n/**\n * Why a checkout event did or did not yield a usable purchase instruction.\n *\n * The two non-accepting outcomes are semantically different and must not be merged: one is a\n * perfectly ordinary session the framework did not originate (a purchase started in the provider\n * dashboard, say) and is a DEBUG-level skip; the other is a session that claims to be ours and is\n * internally inconsistent, which is a tamper signal and must be logged as an error.\n */\nexport enum BillingCheckoutMetadataOutcomeKind {\n /** Reserved keys present, coherent, and cross-checked against provider truth. */\n ACCEPTED = 'accepted',\n /** No reserved keys at all — this checkout session was not opened through `OPEN_CHECKOUT`. */\n NOT_FRAMEWORK_ORIGINATED = 'not_framework_originated',\n /** Reserved keys present but unusable. Fail closed and say why. */\n REFUSED = 'refused',\n}\n\n/** The closed vocabulary of reasons a framework-originated checkout session is refused. */\nexport enum BillingCheckoutMetadataRefusal {\n /** Reserved keys exist but the product key is absent or blank — nothing identifies what was bought. */\n MISSING_PRODUCT_KEY = 'missing_product_key',\n /** The quantity is not a plain decimal integer (`\"abc\"`, `\"-5\"`, `\"1e9\"`, `\"1.5\"`, `\"\"`, …). */\n QUANTITY_NOT_A_POSITIVE_INTEGER = 'quantity_not_a_positive_integer',\n /** The quantity parses but exceeds {@link BILLING_CHECKOUT_MAX_QUANTITY}. */\n QUANTITY_ABOVE_MAXIMUM = 'quantity_above_maximum',\n /**\n * The echoed billing account disagrees with the one derived from the provider-authoritative\n * customer on the event. Either the session was tampered with or the catalog is inconsistent;\n * both mean the grant must not happen.\n */\n BILLING_ACCOUNT_MISMATCH = 'billing_account_mismatch',\n}\n\nexport type BillingCheckoutMetadataOutcome =\n | {\n kind: BillingCheckoutMetadataOutcomeKind.ACCEPTED;\n /** The catalog product key that was purchased. */\n productKey: string;\n /** A validated integer in `[1, BILLING_CHECKOUT_MAX_QUANTITY]`. Defaults to 1 when unstated. */\n quantity: number;\n }\n | { kind: BillingCheckoutMetadataOutcomeKind.NOT_FRAMEWORK_ORIGINATED }\n | {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED;\n reason: BillingCheckoutMetadataRefusal;\n /** Structured detail for the error log. Never contains a secret — these are catalog ids. */\n detail: Record<string, unknown>;\n };\n\n/**\n * Assemble the metadata map for a provider checkout session.\n *\n * Caller metadata is written FIRST and the framework's reserved entries LAST, so the authoritative\n * values win by construction rather than by remembering the right spread order. Reserved keys are\n * additionally stripped out of `callerMetadata` before it is written: the request DTO already\n * refuses them, but this function is also reachable from in-process callers that build the input\n * object directly, and a defence that only exists at the HTTP edge is not a defence of the invariant.\n *\n * @param params.billingAccountId - The account the checkout was opened for (traceability + cross-check).\n * @param params.productKey - The catalog product key being purchased.\n * @param params.quantity - Units purchased; must already be a bounded integer (the DTO enforces it).\n * @param params.callerMetadata - Application-supplied tags. No authority; mirrored to the provider as-is.\n */\nexport function buildCheckoutSessionMetadata(params: {\n billingAccountId: string;\n productKey: string;\n quantity: number;\n callerMetadata?: Record<string, string>;\n}): Record<string, string> {\n const callerEntries = Object.entries(params.callerMetadata ?? {}).filter(\n ([key]) => !key.startsWith(BILLING_RESERVED_METADATA_KEY_PREFIX),\n );\n\n return {\n ...Object.fromEntries(callerEntries),\n // Reserved entries LAST. This ordering is the structural half of the trust boundary — see the\n // module header. Do not move caller metadata below this block.\n [BillingCheckoutMetadataKey.BILLING_ACCOUNT_ID]: params.billingAccountId,\n [BillingCheckoutMetadataKey.PRODUCT_KEY]: params.productKey,\n [BillingCheckoutMetadataKey.QUANTITY]: String(params.quantity),\n };\n}\n\n/**\n * Whether the account a provider event ECHOES matches the one derived from provider truth.\n *\n * A string-enum discriminant rather than a boolean flag, deliberately: the engine compiles with\n * `strict: false`, and TypeScript does not narrow a union on a BOOLEAN literal discriminant without\n * `strictNullChecks` — a `{ ok: true } | { ok: false, … }` result object would have forced every\n * consumer into a cast, which is precisely how a mismatch stops being checked.\n */\nexport enum BillingAccountEchoVerdict {\n /** The echoed account matches, or the event makes no claim about an account at all. */\n MATCHES = 'matches',\n /** The event names a DIFFERENT billing account than the provider customer resolves to. */\n MISMATCHED = 'mismatched',\n}\n\nexport type BillingAccountEchoOutcome =\n | { verdict: BillingAccountEchoVerdict.MATCHES }\n | { verdict: BillingAccountEchoVerdict.MISMATCHED; declaredBillingAccountId: string };\n\n/**\n * Compare a provider-echoed metadata map against the billing account derived from provider truth.\n *\n * The single predicate behind BOTH consumers of echoed metadata — `checkout.session.completed` and\n * `subscription.created`. It exists as one function rather than two comparisons because the two\n * handlers were written in different passes and neither performed the check; a shared predicate is\n * the difference between an invariant and a habit.\n *\n * A map carrying no reserved account key at all MATCHES — an event the framework did not originate\n * makes no claim about the account, so there is nothing to contradict. Only a PRESENT and DIFFERENT\n * value is a mismatch. (The checkout resolver applies a stricter rule on top of this one: a session\n * that claims to be framework-originated must carry the key.)\n */\nexport function compareEchoedBillingAccount(\n metadata: Record<string, string> | undefined,\n authoritativeBillingAccountId: string,\n): BillingAccountEchoOutcome {\n const declaredBillingAccountId = metadata?.[BillingCheckoutMetadataKey.BILLING_ACCOUNT_ID];\n if (declaredBillingAccountId === undefined || declaredBillingAccountId === authoritativeBillingAccountId) {\n return { verdict: BillingAccountEchoVerdict.MATCHES };\n }\n return { verdict: BillingAccountEchoVerdict.MISMATCHED, declaredBillingAccountId };\n}\n\n/**\n * Read a provider-echoed metadata map back as a purchase instruction, treating it as untrusted input.\n *\n * @param metadata - The map exactly as the provider echoed it. May be undefined, may be hostile.\n * @param authoritativeBillingAccountId - The account resolved from the event's provider customer id.\n * REQUIRED, and deliberately so: the echoed account id is only ever compared against this, never\n * substituted for it, and taking it as a parameter is what makes that impossible to skip.\n */\nexport function resolveCheckoutSessionMetadata(\n metadata: Record<string, string> | undefined,\n authoritativeBillingAccountId: string,\n): BillingCheckoutMetadataOutcome {\n const reservedKeysPresent = Object.keys(metadata ?? {}).some(\n (key) => key.startsWith(BILLING_RESERVED_METADATA_KEY_PREFIX),\n );\n if (!metadata || !reservedKeysPresent) {\n return { kind: BillingCheckoutMetadataOutcomeKind.NOT_FRAMEWORK_ORIGINATED };\n }\n\n // Fail closed on both the tampered case and the \"we opened it for a different account than the\n // provider says paid\" case. Neither is a state in which crediting anybody is correct. A session\n // carrying reserved keys but no account key is equally refused — it claims to be ours and cannot\n // be reconciled, which is exactly the shape a stripped-key forgery attempt would take.\n const echo = compareEchoedBillingAccount(metadata, authoritativeBillingAccountId);\n const declaredBillingAccountId = metadata[BillingCheckoutMetadataKey.BILLING_ACCOUNT_ID];\n if (echo.verdict === BillingAccountEchoVerdict.MISMATCHED || declaredBillingAccountId === undefined) {\n return {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED,\n reason: BillingCheckoutMetadataRefusal.BILLING_ACCOUNT_MISMATCH,\n detail: { declaredBillingAccountId: declaredBillingAccountId ?? null, authoritativeBillingAccountId },\n };\n }\n\n const productKey = metadata[BillingCheckoutMetadataKey.PRODUCT_KEY];\n if (!productKey) {\n return {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED,\n reason: BillingCheckoutMetadataRefusal.MISSING_PRODUCT_KEY,\n detail: { authoritativeBillingAccountId },\n };\n }\n\n const rawQuantity = metadata[BillingCheckoutMetadataKey.QUANTITY];\n // Absent is legitimate and means one unit. Present-but-unparseable is not, and must NOT degrade to\n // the default: the original code's `?? 1` never fired for `NaN`, and even if it had, silently\n // granting one unit would have hidden a tampered session behind a successful-looking top-up.\n let quantity = 1;\n if (rawQuantity !== undefined) {\n if (!STRICT_POSITIVE_INTEGER.test(rawQuantity)) {\n return {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED,\n reason: BillingCheckoutMetadataRefusal.QUANTITY_NOT_A_POSITIVE_INTEGER,\n detail: { rawQuantity, authoritativeBillingAccountId },\n };\n }\n quantity = Number.parseInt(rawQuantity, 10);\n if (quantity < 1) {\n return {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED,\n reason: BillingCheckoutMetadataRefusal.QUANTITY_NOT_A_POSITIVE_INTEGER,\n detail: { rawQuantity, authoritativeBillingAccountId },\n };\n }\n if (quantity > BILLING_CHECKOUT_MAX_QUANTITY) {\n // Refused, not clamped. Clamping would grant the ceiling — hundreds of thousands of credit\n // units — to a session that asked for something impossible, which is the attacker's win with\n // extra steps. The bound is shared with the request DTO, so a legitimately billed quantity can\n // never land here.\n return {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED,\n reason: BillingCheckoutMetadataRefusal.QUANTITY_ABOVE_MAXIMUM,\n detail: { rawQuantity, maximum: BILLING_CHECKOUT_MAX_QUANTITY, authoritativeBillingAccountId },\n };\n }\n }\n\n return { kind: BillingCheckoutMetadataOutcomeKind.ACCEPTED, productKey, quantity };\n}\n"]}
1
+ {"version":3,"file":"billing-checkout-metadata.backend.utils.js","sourceRoot":"","sources":["../../../../../src/billing/services/billing-checkout-metadata.backend.utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Provider checkout metadata — the producer/consumer trust boundary.\n *\n * ## The defect this module exists to close\n *\n * `OPEN_CHECKOUT` builds a provider checkout session and attaches a `metadata` map. The provider\n * echoes that map back, VERBATIM, inside a genuinely signed `checkout.session.completed` webhook,\n * and the webhook router used to read `billingAccountId` / `quantity` straight out of it and call\n * `CreditPool_Operations.TOP_UP`.\n *\n * The map, however, was assembled as `{ billingAccountId, productKey, ...quantity, ...input.metadata }`\n * — caller metadata spread LAST — and `input.metadata` is a free-form `Record<string, string>` on an\n * operation reachable by `ORG_OWNER`, `ORG_ADMIN` and `APP_USER`. So any caller could overwrite all\n * three authoritative entries, complete a real payment, and have the provider sign their values back\n * to us. **No signature forgery is involved at any point**, which is exactly why the signature check\n * upstream is no defence: a valid signature proves the PROVIDER sent the bytes, never that the\n * FRAMEWORK wrote them.\n *\n * Three further consequences lived in the same five lines, all confirmed by executing the original\n * expression `(metadata.quantity ? Number(metadata.quantity) : undefined) ?? 1`:\n * - `\"abc\"` yields `NaN` — the `?? 1` fallback is dead because `NaN` is not nullish — and `NaN`\n * reached `{ increment: { available: NaN } }`, permanently corrupting the balance;\n * - `\"1e9\"` yields 1000000000 with no upper bound;\n * - `\"-5\"` yields -5, a top-up that DEBITS.\n *\n * ## The shape of the fix\n *\n * Reordering the spread would close the immediate hole and leave the underlying one: an unmarked\n * namespace in which the next authoritative key is one careless line from being overridable again.\n * So the boundary is made a property of the KEY (see `BILLING_RESERVED_METADATA_KEY_PREFIX`) and\n * enforced at three points that each fail independently:\n *\n * 1. **The request DTO refuses** caller keys in the reserved namespace — loud, at the outer edge.\n * 2. **{@link buildCheckoutSessionMetadata} writes reserved entries LAST** and strips reserved keys\n * out of caller metadata — structural, so a future edit cannot reintroduce the ordering bug, and\n * an internal caller that constructs the input object directly (bypassing the DTO) is covered too.\n * 3. **{@link resolveCheckoutSessionMetadata} treats the echoed map as UNTRUSTED INPUT** — it reads\n * only reserved keys, strictly parses and bounds the quantity, and REQUIRES the caller to supply\n * the provider-authoritative billing account id so the echoed one can only ever be cross-checked,\n * never used.\n *\n * Point 3 is why the resolver takes the authoritative id as a parameter rather than returning the\n * echoed one for the caller to compare: a consumer cannot obtain the parsed values without having\n * already resolved the account from provider truth. The invariant is unbypassable instead of\n * hand-applied at each of the router's handlers.\n */\n\nimport {\n BILLING_CHECKOUT_MAX_QUANTITY,\n BILLING_RESERVED_METADATA_KEY_PREFIX,\n BillingCheckoutMetadataKey,\n} from '@wildo-ai/saas-models';\n\n/** Decimal integer, nothing else. Rejects `\"abc\"`, `\"-5\"`, `\"1e9\"`, `\"1.5\"`, `\"0x10\"`, `\" 1\"`, `\"\"`. */\nconst STRICT_POSITIVE_INTEGER = /^[0-9]+$/;\n\n/**\n * Why a checkout event did or did not yield a usable purchase instruction.\n *\n * The two non-accepting outcomes are semantically different and must not be merged: one is a\n * perfectly ordinary session the framework did not originate (a purchase started in the provider\n * dashboard, say) and is a DEBUG-level skip; the other is a session that claims to be ours and is\n * internally inconsistent, which is a tamper signal and must be logged as an error.\n */\nexport enum BillingCheckoutMetadataOutcomeKind {\n /** Reserved keys present, coherent, and cross-checked against provider truth. */\n ACCEPTED = 'accepted',\n /** No reserved keys at all — this checkout session was not opened through `OPEN_CHECKOUT`. */\n NOT_FRAMEWORK_ORIGINATED = 'not_framework_originated',\n /** Reserved keys present but unusable. Fail closed and say why. */\n REFUSED = 'refused',\n}\n\n/** The closed vocabulary of reasons a framework-originated checkout session is refused. */\nexport enum BillingCheckoutMetadataRefusal {\n /** Reserved keys exist but the product key is absent or blank — nothing identifies what was bought. */\n MISSING_PRODUCT_KEY = 'missing_product_key',\n /** The quantity is not a plain decimal integer (`\"abc\"`, `\"-5\"`, `\"1e9\"`, `\"1.5\"`, `\"\"`, …). */\n QUANTITY_NOT_A_POSITIVE_INTEGER = 'quantity_not_a_positive_integer',\n /** The quantity parses but exceeds {@link BILLING_CHECKOUT_MAX_QUANTITY}. */\n QUANTITY_ABOVE_MAXIMUM = 'quantity_above_maximum',\n /**\n * The echoed billing account disagrees with the one derived from the provider-authoritative\n * customer on the event. Either the session was tampered with or the catalog is inconsistent;\n * both mean the grant must not happen.\n */\n BILLING_ACCOUNT_MISMATCH = 'billing_account_mismatch',\n}\n\nexport type BillingCheckoutMetadataOutcome =\n | {\n kind: BillingCheckoutMetadataOutcomeKind.ACCEPTED;\n /** The catalog product key that was purchased. */\n productKey: string;\n /** A validated integer in `[1, BILLING_CHECKOUT_MAX_QUANTITY]`. Defaults to 1 when unstated. */\n quantity: number;\n /**\n * The promotion the framework validated when it opened this session, if any (#518).\n *\n * Undefined for the common case of a purchase with no code. Read back rather than validated —\n * see the note at the read site for why this one field does not refuse.\n */\n promotionId?: string;\n }\n | { kind: BillingCheckoutMetadataOutcomeKind.NOT_FRAMEWORK_ORIGINATED }\n | {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED;\n reason: BillingCheckoutMetadataRefusal;\n /** Structured detail for the error log. Never contains a secret — these are catalog ids. */\n detail: Record<string, unknown>;\n };\n\n/**\n * Assemble the metadata map for a provider checkout session.\n *\n * Caller metadata is written FIRST and the framework's reserved entries LAST, so the authoritative\n * values win by construction rather than by remembering the right spread order. Reserved keys are\n * additionally stripped out of `callerMetadata` before it is written: the request DTO already\n * refuses them, but this function is also reachable from in-process callers that build the input\n * object directly, and a defence that only exists at the HTTP edge is not a defence of the invariant.\n *\n * @param params.billingAccountId - The account the checkout was opened for (traceability + cross-check).\n * @param params.productKey - The catalog product key being purchased.\n * @param params.quantity - Units purchased; must already be a bounded integer (the DTO enforces it).\n * @param params.callerMetadata - Application-supplied tags. No authority; mirrored to the provider as-is.\n */\nexport function buildCheckoutSessionMetadata(params: {\n billingAccountId: string;\n productKey: string;\n quantity: number;\n /** The validated promotion applied to this checkout, if any — counted when the session completes (#518). */\n promotionId?: string;\n callerMetadata?: Record<string, string>;\n}): Record<string, string> {\n const callerEntries = Object.entries(params.callerMetadata ?? {}).filter(\n ([key]) => !key.startsWith(BILLING_RESERVED_METADATA_KEY_PREFIX),\n );\n\n return {\n ...Object.fromEntries(callerEntries),\n // Reserved entries LAST. This ordering is the structural half of the trust boundary — see the\n // module header. Do not move caller metadata below this block.\n [BillingCheckoutMetadataKey.BILLING_ACCOUNT_ID]: params.billingAccountId,\n [BillingCheckoutMetadataKey.PRODUCT_KEY]: params.productKey,\n [BillingCheckoutMetadataKey.QUANTITY]: String(params.quantity),\n // Only when a validated promotion was applied; absent is the common case (#518).\n ...(params.promotionId ? { [BillingCheckoutMetadataKey.PROMOTION_ID]: params.promotionId } : {}),\n };\n}\n\n/**\n * Whether the account a provider event ECHOES matches the one derived from provider truth.\n *\n * A string-enum discriminant rather than a boolean flag, deliberately: the engine compiles with\n * `strict: false`, and TypeScript does not narrow a union on a BOOLEAN literal discriminant without\n * `strictNullChecks` — a `{ ok: true } | { ok: false, … }` result object would have forced every\n * consumer into a cast, which is precisely how a mismatch stops being checked.\n */\nexport enum BillingAccountEchoVerdict {\n /** The echoed account matches, or the event makes no claim about an account at all. */\n MATCHES = 'matches',\n /** The event names a DIFFERENT billing account than the provider customer resolves to. */\n MISMATCHED = 'mismatched',\n}\n\nexport type BillingAccountEchoOutcome =\n | { verdict: BillingAccountEchoVerdict.MATCHES }\n | { verdict: BillingAccountEchoVerdict.MISMATCHED; declaredBillingAccountId: string };\n\n/**\n * Compare a provider-echoed metadata map against the billing account derived from provider truth.\n *\n * The single predicate behind BOTH consumers of echoed metadata — `checkout.session.completed` and\n * `subscription.created`. It exists as one function rather than two comparisons because the two\n * handlers were written in different passes and neither performed the check; a shared predicate is\n * the difference between an invariant and a habit.\n *\n * A map carrying no reserved account key at all MATCHES — an event the framework did not originate\n * makes no claim about the account, so there is nothing to contradict. Only a PRESENT and DIFFERENT\n * value is a mismatch. (The checkout resolver applies a stricter rule on top of this one: a session\n * that claims to be framework-originated must carry the key.)\n */\nexport function compareEchoedBillingAccount(\n metadata: Record<string, string> | undefined,\n authoritativeBillingAccountId: string,\n): BillingAccountEchoOutcome {\n const declaredBillingAccountId = metadata?.[BillingCheckoutMetadataKey.BILLING_ACCOUNT_ID];\n if (declaredBillingAccountId === undefined || declaredBillingAccountId === authoritativeBillingAccountId) {\n return { verdict: BillingAccountEchoVerdict.MATCHES };\n }\n return { verdict: BillingAccountEchoVerdict.MISMATCHED, declaredBillingAccountId };\n}\n\n/**\n * Read a provider-echoed metadata map back as a purchase instruction, treating it as untrusted input.\n *\n * @param metadata - The map exactly as the provider echoed it. May be undefined, may be hostile.\n * @param authoritativeBillingAccountId - The account resolved from the event's provider customer id.\n * REQUIRED, and deliberately so: the echoed account id is only ever compared against this, never\n * substituted for it, and taking it as a parameter is what makes that impossible to skip.\n */\nexport function resolveCheckoutSessionMetadata(\n metadata: Record<string, string> | undefined,\n authoritativeBillingAccountId: string,\n): BillingCheckoutMetadataOutcome {\n const reservedKeysPresent = Object.keys(metadata ?? {}).some(\n (key) => key.startsWith(BILLING_RESERVED_METADATA_KEY_PREFIX),\n );\n if (!metadata || !reservedKeysPresent) {\n return { kind: BillingCheckoutMetadataOutcomeKind.NOT_FRAMEWORK_ORIGINATED };\n }\n\n // Fail closed on both the tampered case and the \"we opened it for a different account than the\n // provider says paid\" case. Neither is a state in which crediting anybody is correct. A session\n // carrying reserved keys but no account key is equally refused — it claims to be ours and cannot\n // be reconciled, which is exactly the shape a stripped-key forgery attempt would take.\n const echo = compareEchoedBillingAccount(metadata, authoritativeBillingAccountId);\n const declaredBillingAccountId = metadata[BillingCheckoutMetadataKey.BILLING_ACCOUNT_ID];\n if (echo.verdict === BillingAccountEchoVerdict.MISMATCHED || declaredBillingAccountId === undefined) {\n return {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED,\n reason: BillingCheckoutMetadataRefusal.BILLING_ACCOUNT_MISMATCH,\n detail: { declaredBillingAccountId: declaredBillingAccountId ?? null, authoritativeBillingAccountId },\n };\n }\n\n const productKey = metadata[BillingCheckoutMetadataKey.PRODUCT_KEY];\n if (!productKey) {\n return {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED,\n reason: BillingCheckoutMetadataRefusal.MISSING_PRODUCT_KEY,\n detail: { authoritativeBillingAccountId },\n };\n }\n\n const rawQuantity = metadata[BillingCheckoutMetadataKey.QUANTITY];\n // Absent is legitimate and means one unit. Present-but-unparseable is not, and must NOT degrade to\n // the default: the original code's `?? 1` never fired for `NaN`, and even if it had, silently\n // granting one unit would have hidden a tampered session behind a successful-looking top-up.\n let quantity = 1;\n if (rawQuantity !== undefined) {\n if (!STRICT_POSITIVE_INTEGER.test(rawQuantity)) {\n return {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED,\n reason: BillingCheckoutMetadataRefusal.QUANTITY_NOT_A_POSITIVE_INTEGER,\n detail: { rawQuantity, authoritativeBillingAccountId },\n };\n }\n quantity = Number.parseInt(rawQuantity, 10);\n if (quantity < 1) {\n return {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED,\n reason: BillingCheckoutMetadataRefusal.QUANTITY_NOT_A_POSITIVE_INTEGER,\n detail: { rawQuantity, authoritativeBillingAccountId },\n };\n }\n if (quantity > BILLING_CHECKOUT_MAX_QUANTITY) {\n // Refused, not clamped. Clamping would grant the ceiling — hundreds of thousands of credit\n // units — to a session that asked for something impossible, which is the attacker's win with\n // extra steps. The bound is shared with the request DTO, so a legitimately billed quantity can\n // never land here.\n return {\n kind: BillingCheckoutMetadataOutcomeKind.REFUSED,\n reason: BillingCheckoutMetadataRefusal.QUANTITY_ABOVE_MAXIMUM,\n detail: { rawQuantity, maximum: BILLING_CHECKOUT_MAX_QUANTITY, authoritativeBillingAccountId },\n };\n }\n }\n\n /*\n * The promotion is read back but NOT validated here, deliberately (#518). Every other field in this\n * function gates a GRANT — credits, a product — so a bad one must refuse. This one gates a COUNTER\n * increment that is itself guarded by a compare-and-swap against `maxRedemptions`, so the worst a\n * tampered value can do is count one redemption against a promotion that had room for it. Refusing\n * the whole session over it would turn a counting problem into a customer who paid and got nothing.\n */\n const promotionId = metadata[BillingCheckoutMetadataKey.PROMOTION_ID];\n\n return { kind: BillingCheckoutMetadataOutcomeKind.ACCEPTED, productKey, quantity, promotionId };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"billing-account.mutations.custom-impl.backend.service.d.ts","sourceRoot":"","sources":["../../../../../../src/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,OAAO,EAEL,KAAK,0CAA0C,EAChD,MAAM,4GAA4G,CAAC;AAqBpH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mCAAmC,IAAI,0CAA0C,EAAE,CA0ClG;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kDAAkD,IAAI,0CAA0C,EAAE,CAiDjH;AAMD;;;;;;GAMG;AACH,wBAAgB,yCAAyC,IAAI,0CAA0C,EAAE,CA4IxG;AAMD;;;;;;GAMG;AACH,wBAAgB,uCAAuC,IAAI,0CAA0C,EAAE,CAoCtG;AAMD;;;;;;;GAOG;AACH,wBAAgB,qCAAqC,IAAI,0CAA0C,EAAE,CAuCpG"}
1
+ {"version":3,"file":"billing-account.mutations.custom-impl.backend.service.d.ts","sourceRoot":"","sources":["../../../../../../src/billing/services/custom-impl/billing-account.mutations.custom-impl.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAeH,OAAO,EAEL,KAAK,0CAA0C,EAChD,MAAM,4GAA4G,CAAC;AAqBpH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mCAAmC,IAAI,0CAA0C,EAAE,CAyClG;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kDAAkD,IAAI,0CAA0C,EAAE,CAiDjH;AAMD;;;;;;GAMG;AACH,wBAAgB,yCAAyC,IAAI,0CAA0C,EAAE,CAsLxG;AAMD;;;;;;GAMG;AACH,wBAAgB,uCAAuC,IAAI,0CAA0C,EAAE,CAoCtG;AAMD;;;;;;;GAOG;AACH,wBAAgB,qCAAqC,IAAI,0CAA0C,EAAE,CAuCpG"}