@wildo-ai/saas-backend-lib 1.1.12 → 1.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/dist/esm/base-classes/models/manual-controllers.backend.definition.d.ts.map +1 -1
  2. package/dist/esm/base-classes/models/manual-controllers.backend.definition.js +2 -0
  3. package/dist/esm/base-classes/models/manual-controllers.backend.definition.js.map +1 -1
  4. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts +4 -0
  5. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts.map +1 -1
  6. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js +20 -5
  7. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js.map +1 -1
  8. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts +3 -0
  9. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts.map +1 -1
  10. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js +10 -1
  11. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js.map +1 -1
  12. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts +22 -0
  13. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts.map +1 -1
  14. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js +25 -1
  15. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js.map +1 -1
  16. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts +38 -3
  17. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts.map +1 -1
  18. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js +68 -5
  19. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js.map +1 -1
  20. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts +2 -2
  21. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts.map +1 -1
  22. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js +6 -3
  23. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js.map +1 -1
  24. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts +83 -0
  25. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts.map +1 -1
  26. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js +217 -14
  27. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js.map +1 -1
  28. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts +32 -0
  29. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts.map +1 -0
  30. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js +36 -0
  31. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js.map +1 -0
  32. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts +38 -0
  33. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts.map +1 -0
  34. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js +83 -0
  35. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js.map +1 -0
  36. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts +36 -0
  37. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts.map +1 -0
  38. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js +51 -0
  39. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js.map +1 -0
  40. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts +46 -0
  41. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts.map +1 -1
  42. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js +68 -0
  43. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js.map +1 -1
  44. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts +27 -0
  45. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts.map +1 -1
  46. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js +42 -3
  47. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js.map +1 -1
  48. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts +26 -1
  49. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts.map +1 -1
  50. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js +10 -0
  51. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js.map +1 -1
  52. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts +10 -1
  53. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts.map +1 -1
  54. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js +60 -28
  55. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js.map +1 -1
  56. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts +90 -0
  57. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts.map +1 -0
  58. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js +373 -0
  59. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js.map +1 -0
  60. package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts +29 -2
  61. package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts.map +1 -1
  62. package/dist/esm/compliance/approval-seals/decision-presentation.backend.js +40 -3
  63. package/dist/esm/compliance/approval-seals/decision-presentation.backend.js.map +1 -1
  64. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.d.ts.map +1 -1
  65. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js +34 -6
  66. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js.map +1 -1
  67. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts +30 -6
  68. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts.map +1 -1
  69. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js +67 -22
  70. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js.map +1 -1
  71. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.d.ts.map +1 -1
  72. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js +18 -1
  73. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js.map +1 -1
  74. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts +66 -1
  75. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts.map +1 -1
  76. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js +161 -14
  77. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js.map +1 -1
  78. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts +47 -0
  79. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts.map +1 -1
  80. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.js.map +1 -1
  81. package/dist/esm/external-providers/services/content-safety.backend.service.d.ts +27 -2
  82. package/dist/esm/external-providers/services/content-safety.backend.service.d.ts.map +1 -1
  83. package/dist/esm/external-providers/services/content-safety.backend.service.js +46 -1
  84. package/dist/esm/external-providers/services/content-safety.backend.service.js.map +1 -1
  85. package/dist/esm/external-providers/services/embeddings.backend.service.d.ts.map +1 -1
  86. package/dist/esm/external-providers/services/embeddings.backend.service.js +2 -0
  87. package/dist/esm/external-providers/services/embeddings.backend.service.js.map +1 -1
  88. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +11 -0
  89. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -1
  90. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +23 -0
  91. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
  92. package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts +19 -1
  93. package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts.map +1 -1
  94. package/dist/esm/external-providers/services/provider-service-account-token.backend.js +41 -1
  95. package/dist/esm/external-providers/services/provider-service-account-token.backend.js.map +1 -1
  96. package/dist/esm/files/utils/file-parent-read-context.backend.d.ts +27 -2
  97. package/dist/esm/files/utils/file-parent-read-context.backend.d.ts.map +1 -1
  98. package/dist/esm/files/utils/file-parent-read-context.backend.js +23 -4
  99. package/dist/esm/files/utils/file-parent-read-context.backend.js.map +1 -1
  100. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts +26 -0
  101. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts.map +1 -1
  102. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js +100 -8
  103. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js.map +1 -1
  104. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts +3 -1
  105. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts.map +1 -1
  106. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js +8 -2
  107. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js.map +1 -1
  108. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts +43 -0
  109. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts.map +1 -1
  110. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js +37 -0
  111. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js.map +1 -1
  112. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts +7 -0
  113. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts.map +1 -1
  114. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js +8 -3
  115. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js.map +1 -1
  116. package/dist/esm/flows-actors/services/agents.backend.service.d.ts +31 -6
  117. package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
  118. package/dist/esm/flows-actors/services/agents.backend.service.js +78 -30
  119. package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
  120. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.d.ts.map +1 -1
  121. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js +4 -0
  122. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js.map +1 -1
  123. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts +28 -2
  124. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts.map +1 -1
  125. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js +132 -22
  126. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js.map +1 -1
  127. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.d.ts.map +1 -1
  128. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js +12 -8
  129. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js.map +1 -1
  130. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts +5 -0
  131. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts.map +1 -1
  132. package/dist/esm/flows-actors/services/flows-actors-registry.service.js +18 -2
  133. package/dist/esm/flows-actors/services/flows-actors-registry.service.js.map +1 -1
  134. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts +33 -0
  135. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts.map +1 -1
  136. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js +58 -0
  137. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
  138. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts +12 -1
  139. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts.map +1 -1
  140. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js +23 -4
  141. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js.map +1 -1
  142. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts +12 -1
  143. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts.map +1 -1
  144. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js +55 -17
  145. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js.map +1 -1
  146. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts +22 -1
  147. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts.map +1 -1
  148. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js +52 -9
  149. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js.map +1 -1
  150. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts +79 -0
  151. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts.map +1 -0
  152. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js +211 -0
  153. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js.map +1 -0
  154. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts +2 -2
  155. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts.map +1 -1
  156. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js +9 -1
  157. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js.map +1 -1
  158. package/dist/esm/index.d.ts +1 -0
  159. package/dist/esm/index.d.ts.map +1 -1
  160. package/dist/esm/index.js +1 -0
  161. package/dist/esm/index.js.map +1 -1
  162. package/dist/esm/inject/models/container.d.ts.map +1 -1
  163. package/dist/esm/inject/models/container.js +6 -0
  164. package/dist/esm/inject/models/container.js.map +1 -1
  165. package/dist/esm/inject/models/service-types.d.ts +5 -0
  166. package/dist/esm/inject/models/service-types.d.ts.map +1 -1
  167. package/dist/esm/inject/models/service-types.js +3 -0
  168. package/dist/esm/inject/models/service-types.js.map +1 -1
  169. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts +5 -0
  170. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts.map +1 -1
  171. package/dist/esm/monitoring/observability/models/observability.backend.schemas.js.map +1 -1
  172. package/dist/esm/monitoring/observability/services/metrics.service.d.ts +34 -1
  173. package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -1
  174. package/dist/esm/monitoring/observability/services/metrics.service.js +49 -0
  175. package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -1
  176. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts +6 -1
  177. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts.map +1 -1
  178. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js +15 -4
  179. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js.map +1 -1
  180. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.d.ts.map +1 -1
  181. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js +3 -1
  182. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js.map +1 -1
  183. package/dist/esm/runtime/services/http-server.backend.service.d.ts +3 -1
  184. package/dist/esm/runtime/services/http-server.backend.service.d.ts.map +1 -1
  185. package/dist/esm/runtime/services/http-server.backend.service.js +11 -3
  186. package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -1
  187. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts +22 -0
  188. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts.map +1 -1
  189. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js +54 -0
  190. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js.map +1 -1
  191. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts +51 -0
  192. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts.map +1 -1
  193. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js +87 -15
  194. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js.map +1 -1
  195. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.d.ts.map +1 -1
  196. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js +5 -2
  197. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js.map +1 -1
  198. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts.map +1 -1
  199. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js +65 -24
  200. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js.map +1 -1
  201. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts +64 -1
  202. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts.map +1 -1
  203. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js +84 -2
  204. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js.map +1 -1
  205. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts +14 -0
  206. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts.map +1 -1
  207. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js +13 -5
  208. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js.map +1 -1
  209. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.d.ts.map +1 -1
  210. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js +6 -2
  211. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js.map +1 -1
  212. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts +7 -0
  213. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts.map +1 -1
  214. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js +65 -20
  215. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js.map +1 -1
  216. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.d.ts.map +1 -1
  217. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js +11 -4
  218. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js.map +1 -1
  219. package/dist/esm/users/services/user-self-custom-implementations.backend.d.ts.map +1 -1
  220. package/dist/esm/users/services/user-self-custom-implementations.backend.js +4 -2
  221. package/dist/esm/users/services/user-self-custom-implementations.backend.js.map +1 -1
  222. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.d.ts.map +1 -1
  223. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js +16 -0
  224. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js.map +1 -1
  225. package/dist/tsconfig.build.tsbuildinfo +1 -1
  226. package/package.json +10 -10
@@ -0,0 +1,211 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ /**
14
+ * A delivery body too large for its row, stored beside it (#3395).
15
+ *
16
+ * A delivery keeps its exact verified bytes inside its row (`rawBody`, base64) up to `INBOUND_DELIVERY_MAX_STORED_BODY_BYTES`
17
+ * (10 MiB): MongoDB refuses a document over 16 MiB. A provider that pushes a whole email in its webhook (Postmark, Mailgun)
18
+ * sends more than that, so a larger body is written to the application's object storage as a FILE and the row names it:
19
+ *
20
+ * ```
21
+ * receiver: verify over every byte ─► write the file (delivery-scoped key) ─► link it to the row's id ─► insert the row
22
+ * (rawBody '', storedBody { sha256, byteLength }, storedBodyFile { fileId })
23
+ * worker: read the file ─► check length and SHA-256 against the row ─► decode ─► run the handler
24
+ * ```
25
+ *
26
+ * ## Why a FILE, through the file service
27
+ *
28
+ * The storage providers are file-record oriented: an object's key is derived from a `files` row (its scope, the resource
29
+ * it belongs to and its id), which is also what legal holds, the files cleanup and a tenant's teardown operate on. A
30
+ * second, delivery-only object store would need its own sweep, its own legal-hold check and its own erasure, and would
31
+ * drift from them. Writing the body through `writeServerProducedFile` gives it a key under the delivery's tenant scope and
32
+ * resource (`…/<scope>/<scopeId>/…/<fileId>`), and linking it to the row (`storedBodyFile`, a `z_file` field) is what makes
33
+ * it follow the row:
34
+ *
35
+ * - **Kept with the row.** A linked file is never swept as an orphan; an unlinked one would be swept a day later, while a
36
+ * delivery may wait days for its retries or sit DEAD until an operator replays it.
37
+ * - **Retention and a tenant's deletion.** Both delete deliveries through the service tier (the INTERNAL_CALL DELETE
38
+ * variants), which releases a row's linked files; the files cleanup then removes their bytes.
39
+ * - **Redaction.** When the row's body is emptied (`bodyRedactionFields`, every redaction door of the store), the store
40
+ * clears `storedBody` / `storedBodyFile` in the same compare-and-swap and then {@link discard}s the file: its row is
41
+ * marked deleted and its bytes are removed at once.
42
+ * - **A person's erasure.** Both doors delete rows by repository (`deleteInboundDeliveriesNamingKeys`), which releases no
43
+ * file, so that function marks the deleted rows' body files deleted in the same transaction
44
+ * ({@link releaseStoredBodyFilesOfDeletedRows}); the files cleanup removes their bytes, as for every erased file.
45
+ *
46
+ * Scan: NONE. The file is the verified vendor request, never served as a message; an attachment it carries is written,
47
+ * scanned and linked by the handler (the email reception) like any received attachment.
48
+ *
49
+ * Rejected: streaming the request straight to storage before verifying. A scheme may sign the whole body (Mailgun signs
50
+ * `{timestamp}{raw body}`), and storing bytes nobody has authenticated yet would turn every forged request into a write.
51
+ * The body is held in memory once, bounded by `INBOUND_DELIVERY_MAX_BODY_BYTES`, verified, and then streamed to storage.
52
+ */
53
+ import { createHash } from 'node:crypto';
54
+ import { inject, injectable } from 'inversify';
55
+ import { CoreResourceOperation, CoreResourceType, FileStatus, INBOUND_DELIVERY_STORED_BODY_FILE_FIELD, } from '@wildo-ai/saas-models';
56
+ import { SAAS_SERVICE_TYPES } from '../../inject/models/service-types.js';
57
+ import { ServerProducedFileScan, writeServerProducedFile } from '../../files/services/server-produced-file-writer.backend.js';
58
+ import { projectCaughtErrorLogFields } from '../../errors/utils/error-log-level-classification.backend.utils.js';
59
+ /**
60
+ * The bytes read back for a delivery are not the bytes it received: the file is gone, or its length or SHA-256 differs
61
+ * from what the row recorded at receipt. Permanent: no retry brings the received message back, so the delivery dies and
62
+ * an operator sees why. A storage outage is NOT this error; it is retried.
63
+ */
64
+ export class InboundStoredBodyIntegrityError extends Error {
65
+ name = 'InboundStoredBodyIntegrityError';
66
+ }
67
+ /** The `files` statuses a stored body can be in before it is released: written, linked. */
68
+ const RELEASABLE_STATUSES = [FileStatus.UPLOADED, FileStatus.LINKED, FileStatus.CLEAN];
69
+ const LINK_FIELDS = ['linkedResourceType', 'linkedResourceId', 'linkedFieldName'];
70
+ /** The file a row's body is stored as, or undefined for a body kept in the row. */
71
+ export function storedBodyFileIdOf(row) {
72
+ const value = row.storedBodyFile;
73
+ return typeof value?.fileId === 'string' && value.fileId.length > 0 ? value.fileId : undefined;
74
+ }
75
+ /**
76
+ * Mark the body files of rows a repository delete removed as DELETED, in the caller's transaction (#3395): a person's
77
+ * erasure deletes deliveries by repository, which releases no file. The files cleanup then removes their bytes, exactly as
78
+ * it does for every file an erasure releases (`FilesBackendService.eraseFile`: a DB rollback must never be mixed with
79
+ * storage side effects). Guarded on the file still being linked to that row and field, so a file another row took is
80
+ * never touched. Returns how many were released.
81
+ */
82
+ export async function releaseStoredBodyFilesOfDeletedRows(input) {
83
+ let released = 0;
84
+ for (const row of input.rows) {
85
+ const fileId = storedBodyFileIdOf(row);
86
+ if (!fileId)
87
+ continue;
88
+ const claimed = await input.registry.atomicConditionalSet(CoreResourceType.FILES, { _id: fileId, status: { $in: [...RELEASABLE_STATUSES] }, linkedResourceType: input.table, linkedResourceId: String(row._id), linkedFieldName: INBOUND_DELIVERY_STORED_BODY_FILE_FIELD }, { set: { status: FileStatus.DELETED, deletedAt: new Date() }, clear: [...LINK_FIELDS] }, input.executionContext, input.options);
89
+ if (claimed)
90
+ released++;
91
+ }
92
+ return released;
93
+ }
94
+ let InboundDeliveryStoredBodyBackendService = class InboundDeliveryStoredBodyBackendService {
95
+ logger;
96
+ fileWriter;
97
+ files;
98
+ repositoriesRegistry;
99
+ contexts;
100
+ resources;
101
+ constructor(logger, fileWriter, files, repositoriesRegistry, contexts, resources) {
102
+ this.logger = logger;
103
+ this.fileWriter = fileWriter;
104
+ this.files = files;
105
+ this.repositoriesRegistry = repositoriesRegistry;
106
+ this.contexts = contexts;
107
+ this.resources = resources;
108
+ }
109
+ /**
110
+ * Write a verified body for the delivery that will be stored at `resourceType` / `deliveryId`, and link it to that row
111
+ * before the row exists (its id is derived from the event, so it is known). `ownerRow` names the row's owner (its
112
+ * `organizationId`, or its `applicationId`): an internal context carries no organization. A failure after the write
113
+ * releases the file and throws, so the caller answers "retry later" and nothing half-written is kept.
114
+ */
115
+ // assurance-control: WILDO.DATA.SECURE_LIFECYCLE — a delivery body too large for its row is stored as a file linked to it, so it lives and is deleted with the row.
116
+ async write(input) {
117
+ const sha256 = createHash('sha256').update(input.bytes).digest('hex');
118
+ const context = await this.context(input.resourceType);
119
+ const written = await writeServerProducedFile(this.fileWriter, {
120
+ resourceType: input.resourceType,
121
+ fieldName: INBOUND_DELIVERY_STORED_BODY_FILE_FIELD,
122
+ bytes: input.bytes,
123
+ mimeType: input.mimeType,
124
+ filename: `${input.deliveryId}.body`,
125
+ scopeOwnerRow: input.ownerRow,
126
+ executionContext: context,
127
+ scan: ServerProducedFileScan.NONE,
128
+ describedAs: 'inbound delivery body',
129
+ });
130
+ try {
131
+ await this.files.linkFileToResource(written.fileId, input.resourceType, input.deliveryId, INBOUND_DELIVERY_STORED_BODY_FILE_FIELD, context, undefined, input.ownerRow);
132
+ }
133
+ catch (error) {
134
+ await this.discard(written.fileId, 'link_failed');
135
+ throw error;
136
+ }
137
+ return { fileId: written.fileId, sha256, byteLength: input.bytes.byteLength };
138
+ }
139
+ /**
140
+ * The bytes of a body stored outside its row, checked against the row: never past `byteLength`, exactly `byteLength`,
141
+ * and hashing to `sha256`. A mismatch, or a file that is gone, is {@link InboundStoredBodyIntegrityError}; a provider that
142
+ * does not answer throws its own error and the delivery is retried.
143
+ */
144
+ // assurance-control: WILDO.AUDIT.EVIDENCE_INTEGRITY — the worker runs the handler only on bytes whose length and SHA-256 match what was verified at receipt.
145
+ async read(resourceType, row) {
146
+ const fileId = storedBodyFileIdOf(row);
147
+ const expected = row.storedBody ?? null;
148
+ if (!fileId || expected === null)
149
+ throw new InboundStoredBodyIntegrityError(`Inbound delivery ${String(row._id)} names no stored body`);
150
+ const file = await this.repositoriesRegistry.readUnscopedByKey(CoreResourceType.FILES, { _id: fileId });
151
+ if (!file || !RELEASABLE_STATUSES.includes(file.status)) {
152
+ throw new InboundStoredBodyIntegrityError(`The stored body of inbound delivery ${String(row._id)} is gone (file ${fileId}${file ? `, ${file.status}` : ''})`);
153
+ }
154
+ const provider = file.storageProvider ? this.fileWriter.fileStorageRouter.getProviderById(file.storageProvider) : undefined;
155
+ if (!provider)
156
+ throw new Error(`No storage provider '${String(file.storageProvider)}' is registered for the stored body of inbound delivery ${String(row._id)}`);
157
+ const context = await this.context(resourceType);
158
+ const { stream } = await provider.download({ ...file, fileId }, context);
159
+ const hash = createHash('sha256');
160
+ const chunks = [];
161
+ let length = 0;
162
+ for await (const chunk of stream) {
163
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
164
+ length += buffer.byteLength;
165
+ if (length > expected.byteLength) {
166
+ stream.destroy();
167
+ throw new InboundStoredBodyIntegrityError(`The stored body of inbound delivery ${String(row._id)} is longer than the ${expected.byteLength} bytes received`);
168
+ }
169
+ hash.update(buffer);
170
+ chunks.push(buffer);
171
+ }
172
+ if (length !== expected.byteLength)
173
+ throw new InboundStoredBodyIntegrityError(`The stored body of inbound delivery ${String(row._id)} is ${length} bytes, not the ${expected.byteLength} received`);
174
+ if (hash.digest('hex') !== expected.sha256)
175
+ throw new InboundStoredBodyIntegrityError(`The stored body of inbound delivery ${String(row._id)} does not hash to what was received`);
176
+ return Buffer.concat(chunks, length);
177
+ }
178
+ /**
179
+ * Delete a stored body now: its `files` row is marked DELETED (unlinked), then its bytes and row are removed. Never
180
+ * throws: a body whose bytes could not be removed stays DELETED, and the files cleanup removes it at the FILES period.
181
+ * Used when the row's body is emptied and when a write is abandoned (a duplicate, a failed insert).
182
+ */
183
+ async discard(fileId, reason) {
184
+ try {
185
+ const claimed = await this.repositoriesRegistry.atomicConditionalSet(CoreResourceType.FILES, { _id: fileId, status: { $in: [...RELEASABLE_STATUSES] } }, { set: { status: FileStatus.DELETED, deletedAt: new Date() }, clear: [...LINK_FIELDS] });
186
+ if (!claimed)
187
+ return;
188
+ await this.files.hardDeleteFile(fileId, await this.context(CoreResourceType.APPLICATION_INBOUND_DELIVERIES));
189
+ }
190
+ catch (error) {
191
+ this.logger.warn('An inbound delivery body could not be deleted from storage now; the files cleanup removes it later', { fileId, reason, ...projectCaughtErrorLogFields(error) });
192
+ }
193
+ }
194
+ async context(resourceType) {
195
+ return this.contexts.createForInternalOperation({
196
+ operation: this.resources.getServiceOperationPathDefault(resourceType, CoreResourceOperation.READ),
197
+ });
198
+ }
199
+ };
200
+ InboundDeliveryStoredBodyBackendService = __decorate([
201
+ injectable(),
202
+ __param(0, inject(SAAS_SERVICE_TYPES.Logger)),
203
+ __param(1, inject(SAAS_SERVICE_TYPES.ServerProducedFileWriterDependencies)),
204
+ __param(2, inject(SAAS_SERVICE_TYPES.FilesBackendService)),
205
+ __param(3, inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)),
206
+ __param(4, inject(SAAS_SERVICE_TYPES.ExecutionContextCreatorBackendService)),
207
+ __param(5, inject(SAAS_SERVICE_TYPES.ResourceRegistryService)),
208
+ __metadata("design:paramtypes", [Function, Object, Object, Object, Object, Object])
209
+ ], InboundDeliveryStoredBodyBackendService);
210
+ export { InboundDeliveryStoredBodyBackendService };
211
+ //# sourceMappingURL=inbound-delivery-stored-body.backend.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound-delivery-stored-body.backend.service.js","sourceRoot":"","sources":["../../../../src/inbound/services/inbound-delivery-stored-body.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A delivery body too large for its row, stored beside it (#3395).\n *\n * A delivery keeps its exact verified bytes inside its row (`rawBody`, base64) up to `INBOUND_DELIVERY_MAX_STORED_BODY_BYTES`\n * (10 MiB): MongoDB refuses a document over 16 MiB. A provider that pushes a whole email in its webhook (Postmark, Mailgun)\n * sends more than that, so a larger body is written to the application's object storage as a FILE and the row names it:\n *\n * ```\n * receiver: verify over every byte ─► write the file (delivery-scoped key) ─► link it to the row's id ─► insert the row\n * (rawBody '', storedBody { sha256, byteLength }, storedBodyFile { fileId })\n * worker: read the file ─► check length and SHA-256 against the row ─► decode ─► run the handler\n * ```\n *\n * ## Why a FILE, through the file service\n *\n * The storage providers are file-record oriented: an object's key is derived from a `files` row (its scope, the resource\n * it belongs to and its id), which is also what legal holds, the files cleanup and a tenant's teardown operate on. A\n * second, delivery-only object store would need its own sweep, its own legal-hold check and its own erasure, and would\n * drift from them. Writing the body through `writeServerProducedFile` gives it a key under the delivery's tenant scope and\n * resource (`…/<scope>/<scopeId>/…/<fileId>`), and linking it to the row (`storedBodyFile`, a `z_file` field) is what makes\n * it follow the row:\n *\n * - **Kept with the row.** A linked file is never swept as an orphan; an unlinked one would be swept a day later, while a\n * delivery may wait days for its retries or sit DEAD until an operator replays it.\n * - **Retention and a tenant's deletion.** Both delete deliveries through the service tier (the INTERNAL_CALL DELETE\n * variants), which releases a row's linked files; the files cleanup then removes their bytes.\n * - **Redaction.** When the row's body is emptied (`bodyRedactionFields`, every redaction door of the store), the store\n * clears `storedBody` / `storedBodyFile` in the same compare-and-swap and then {@link discard}s the file: its row is\n * marked deleted and its bytes are removed at once.\n * - **A person's erasure.** Both doors delete rows by repository (`deleteInboundDeliveriesNamingKeys`), which releases no\n * file, so that function marks the deleted rows' body files deleted in the same transaction\n * ({@link releaseStoredBodyFilesOfDeletedRows}); the files cleanup removes their bytes, as for every erased file.\n *\n * Scan: NONE. The file is the verified vendor request, never served as a message; an attachment it carries is written,\n * scanned and linked by the handler (the email reception) like any received attachment.\n *\n * Rejected: streaming the request straight to storage before verifying. A scheme may sign the whole body (Mailgun signs\n * `{timestamp}{raw body}`), and storing bytes nobody has authenticated yet would turn every forged request into a write.\n * The body is held in memory once, bounded by `INBOUND_DELIVERY_MAX_BODY_BYTES`, verified, and then streamed to storage.\n */\nimport { createHash } from 'node:crypto';\nimport { Readable } from 'node:stream';\nimport { inject, injectable } from 'inversify';\nimport {\n CoreResourceOperation,\n CoreResourceType,\n FileStatus,\n INBOUND_DELIVERY_STORED_BODY_FILE_FIELD,\n type File,\n type InboundDeliveryStoredBody,\n type ResourceType,\n} from '@wildo-ai/saas-models';\n\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport type { RepositoryOptions } from '~wildo-backend-lib/base-classes/models/repositories.backend.schemas';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport type { FilesBackendService } from '~wildo-backend-lib/files/services/files.backend.service';\nimport { ServerProducedFileScan, writeServerProducedFile, type ServerProducedFileWriterDependencies } from '~wildo-backend-lib/files/services/server-produced-file-writer.backend';\nimport { projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\n\n/** A body written outside its row: the file, and the binding the row keeps. */\nexport interface StoredInboundBody extends InboundDeliveryStoredBody {\n readonly fileId: string;\n}\n\n/**\n * The bytes read back for a delivery are not the bytes it received: the file is gone, or its length or SHA-256 differs\n * from what the row recorded at receipt. Permanent: no retry brings the received message back, so the delivery dies and\n * an operator sees why. A storage outage is NOT this error; it is retried.\n */\nexport class InboundStoredBodyIntegrityError extends Error {\n override readonly name = 'InboundStoredBodyIntegrityError';\n}\n\n/** The `files` statuses a stored body can be in before it is released: written, linked. */\nconst RELEASABLE_STATUSES: readonly FileStatus[] = [FileStatus.UPLOADED, FileStatus.LINKED, FileStatus.CLEAN];\nconst LINK_FIELDS = ['linkedResourceType', 'linkedResourceId', 'linkedFieldName'] as const;\n\n/** The file a row's body is stored as, or undefined for a body kept in the row. */\nexport function storedBodyFileIdOf(row: { readonly storedBodyFile?: unknown }): string | undefined {\n const value = row.storedBodyFile as { fileId?: unknown } | null | undefined;\n return typeof value?.fileId === 'string' && value.fileId.length > 0 ? value.fileId : undefined;\n}\n\n/**\n * Mark the body files of rows a repository delete removed as DELETED, in the caller's transaction (#3395): a person's\n * erasure deletes deliveries by repository, which releases no file. The files cleanup then removes their bytes, exactly as\n * it does for every file an erasure releases (`FilesBackendService.eraseFile`: a DB rollback must never be mixed with\n * storage side effects). Guarded on the file still being linked to that row and field, so a file another row took is\n * never touched. Returns how many were released.\n */\nexport async function releaseStoredBodyFilesOfDeletedRows(input: {\n readonly registry: Pick<RepositoriesRegistryHandlerBackendService, 'atomicConditionalSet'>;\n readonly table: ResourceType;\n readonly rows: readonly Readonly<Record<string, unknown>>[];\n readonly executionContext?: ExecutionContext<any>;\n readonly options?: RepositoryOptions;\n}): Promise<number> {\n let released = 0;\n for (const row of input.rows) {\n const fileId = storedBodyFileIdOf(row);\n if (!fileId) continue;\n const claimed = await input.registry.atomicConditionalSet(\n CoreResourceType.FILES,\n { _id: fileId, status: { $in: [...RELEASABLE_STATUSES] }, linkedResourceType: input.table, linkedResourceId: String(row._id), linkedFieldName: INBOUND_DELIVERY_STORED_BODY_FILE_FIELD },\n { set: { status: FileStatus.DELETED, deletedAt: new Date() }, clear: [...LINK_FIELDS] },\n input.executionContext,\n input.options,\n );\n if (claimed) released++;\n }\n return released;\n}\n\n@injectable()\nexport class InboundDeliveryStoredBodyBackendService {\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger) private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.ServerProducedFileWriterDependencies) private readonly fileWriter: ServerProducedFileWriterDependencies,\n @inject(SAAS_SERVICE_TYPES.FilesBackendService) private readonly files: Pick<FilesBackendService, 'linkFileToResource' | 'hardDeleteFile'>,\n @inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)\n private readonly repositoriesRegistry: Pick<RepositoriesRegistryHandlerBackendService, 'readUnscopedByKey' | 'atomicConditionalSet'>,\n @inject(SAAS_SERVICE_TYPES.ExecutionContextCreatorBackendService) private readonly contexts: Pick<ExecutionContextCreatorBackendService, 'createForInternalOperation'>,\n @inject(SAAS_SERVICE_TYPES.ResourceRegistryService) private readonly resources: Pick<ResourcesRegistryBackendService, 'getServiceOperationPathDefault'>,\n ) {}\n\n /**\n * Write a verified body for the delivery that will be stored at `resourceType` / `deliveryId`, and link it to that row\n * before the row exists (its id is derived from the event, so it is known). `ownerRow` names the row's owner (its\n * `organizationId`, or its `applicationId`): an internal context carries no organization. A failure after the write\n * releases the file and throws, so the caller answers \"retry later\" and nothing half-written is kept.\n */\n // assurance-control: WILDO.DATA.SECURE_LIFECYCLE — a delivery body too large for its row is stored as a file linked to it, so it lives and is deleted with the row.\n async write(input: {\n readonly resourceType: ResourceType;\n readonly deliveryId: string;\n readonly bytes: Buffer;\n readonly mimeType: string;\n readonly ownerRow: Readonly<Record<string, unknown>>;\n }): Promise<StoredInboundBody> {\n const sha256 = createHash('sha256').update(input.bytes).digest('hex');\n const context = await this.context(input.resourceType);\n const written = await writeServerProducedFile(this.fileWriter, {\n resourceType: input.resourceType,\n fieldName: INBOUND_DELIVERY_STORED_BODY_FILE_FIELD,\n bytes: input.bytes,\n mimeType: input.mimeType,\n filename: `${input.deliveryId}.body`,\n scopeOwnerRow: input.ownerRow,\n executionContext: context,\n scan: ServerProducedFileScan.NONE,\n describedAs: 'inbound delivery body',\n });\n try {\n await this.files.linkFileToResource(written.fileId, input.resourceType, input.deliveryId, INBOUND_DELIVERY_STORED_BODY_FILE_FIELD, context, undefined, input.ownerRow as Record<string, unknown>);\n } catch (error) {\n await this.discard(written.fileId, 'link_failed');\n throw error;\n }\n return { fileId: written.fileId, sha256, byteLength: input.bytes.byteLength };\n }\n\n /**\n * The bytes of a body stored outside its row, checked against the row: never past `byteLength`, exactly `byteLength`,\n * and hashing to `sha256`. A mismatch, or a file that is gone, is {@link InboundStoredBodyIntegrityError}; a provider that\n * does not answer throws its own error and the delivery is retried.\n */\n // assurance-control: WILDO.AUDIT.EVIDENCE_INTEGRITY — the worker runs the handler only on bytes whose length and SHA-256 match what was verified at receipt.\n async read(resourceType: ResourceType, row: { readonly _id: unknown; readonly storedBody?: InboundDeliveryStoredBody | null; readonly storedBodyFile?: unknown }): Promise<Buffer> {\n const fileId = storedBodyFileIdOf(row);\n const expected = row.storedBody ?? null;\n if (!fileId || expected === null) throw new InboundStoredBodyIntegrityError(`Inbound delivery ${String(row._id)} names no stored body`);\n const file = await this.repositoriesRegistry.readUnscopedByKey<File & { _id: string }>(CoreResourceType.FILES, { _id: fileId });\n if (!file || !RELEASABLE_STATUSES.includes(file.status)) {\n throw new InboundStoredBodyIntegrityError(`The stored body of inbound delivery ${String(row._id)} is gone (file ${fileId}${file ? `, ${file.status}` : ''})`);\n }\n const provider = file.storageProvider ? this.fileWriter.fileStorageRouter.getProviderById(file.storageProvider) : undefined;\n if (!provider) throw new Error(`No storage provider '${String(file.storageProvider)}' is registered for the stored body of inbound delivery ${String(row._id)}`);\n const context = await this.context(resourceType);\n const { stream } = await provider.download({ ...file, fileId }, context);\n const hash = createHash('sha256');\n const chunks: Buffer[] = [];\n let length = 0;\n for await (const chunk of stream as Readable) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk as Uint8Array);\n length += buffer.byteLength;\n if (length > expected.byteLength) {\n (stream as Readable).destroy();\n throw new InboundStoredBodyIntegrityError(`The stored body of inbound delivery ${String(row._id)} is longer than the ${expected.byteLength} bytes received`);\n }\n hash.update(buffer);\n chunks.push(buffer);\n }\n if (length !== expected.byteLength) throw new InboundStoredBodyIntegrityError(`The stored body of inbound delivery ${String(row._id)} is ${length} bytes, not the ${expected.byteLength} received`);\n if (hash.digest('hex') !== expected.sha256) throw new InboundStoredBodyIntegrityError(`The stored body of inbound delivery ${String(row._id)} does not hash to what was received`);\n return Buffer.concat(chunks, length);\n }\n\n /**\n * Delete a stored body now: its `files` row is marked DELETED (unlinked), then its bytes and row are removed. Never\n * throws: a body whose bytes could not be removed stays DELETED, and the files cleanup removes it at the FILES period.\n * Used when the row's body is emptied and when a write is abandoned (a duplicate, a failed insert).\n */\n async discard(fileId: string, reason: string): Promise<void> {\n try {\n const claimed = await this.repositoriesRegistry.atomicConditionalSet(\n CoreResourceType.FILES,\n { _id: fileId, status: { $in: [...RELEASABLE_STATUSES] } },\n { set: { status: FileStatus.DELETED, deletedAt: new Date() }, clear: [...LINK_FIELDS] },\n );\n if (!claimed) return;\n await this.files.hardDeleteFile(fileId, await this.context(CoreResourceType.APPLICATION_INBOUND_DELIVERIES));\n } catch (error) {\n this.logger.warn('An inbound delivery body could not be deleted from storage now; the files cleanup removes it later', { fileId, reason, ...projectCaughtErrorLogFields(error) });\n }\n }\n\n private async context(resourceType: ResourceType): Promise<ExecutionContext<any>> {\n return this.contexts.createForInternalOperation({\n operation: this.resources.getServiceOperationPathDefault(resourceType, CoreResourceOperation.READ),\n } as never);\n }\n}\n"]}
@@ -45,7 +45,7 @@ export declare const INBOUND_DELIVERY_SUBJECT_SEVERER_REF = "inbound-delivery-su
45
45
  * a person in all of them, so one erasure removes them together.
46
46
  */
47
47
  export declare const INBOUND_SUBJECT_KEYED_TABLES: readonly ResourceType[];
48
- type Registry = Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure' | 'deleteManyForInfrastructure' | 'hasRepository' | 'readUnscopedByKey'>;
48
+ type Registry = Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure' | 'deleteManyForInfrastructure' | 'hasRepository' | 'readUnscopedByKey' | 'atomicConditionalSet'>;
49
49
  /**
50
50
  * The keys a person is named by in a delivery's `subjectKeys`: their user id, their email address lower-cased
51
51
  * (`inboundSubjectKeyForEmailAddress`, the form the handler contract writes), and each phone number they hold in E.164
@@ -99,7 +99,7 @@ export declare function confirmSeveranceDelete(input: {
99
99
  * {@link confirmSeveranceDelete}. `heldCount` is the rows the hold kept.
100
100
  */
101
101
  export declare function deleteInboundDeliveriesNamingKeys(input: {
102
- readonly registry: Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure' | 'deleteManyForInfrastructure'>;
102
+ readonly registry: Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure' | 'deleteManyForInfrastructure' | 'atomicConditionalSet'>;
103
103
  readonly table: ResourceType;
104
104
  readonly keys: readonly string[];
105
105
  /** A filter every deleted row must also match: the caller's scope. Absent for an erasure, which spans every scope. */
@@ -1 +1 @@
1
- {"version":3,"file":"inbound-delivery-subject-erasure-severance.backend.d.ts","sourceRoot":"","sources":["../../../../src/inbound/services/inbound-delivery-subject-erasure-severance.backend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inbound-delivery-subject-erasure-severance.backend.d.ts","sourceRoot":"","sources":["../../../../src/inbound/services/inbound-delivery-subject-erasure-severance.backend.ts"],"names":[],"mappings":"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"}
@@ -34,6 +34,7 @@
34
34
  import { CoreResourceType, inboundSubjectKeyForEmailAddress, inboundSubjectKeyForPhoneNumber, SortOrder, SubjectErasureSeveredReferenceTreatment, } from '@wildo-ai/saas-models';
35
35
  import { SAAS_SERVICE_TYPES } from '../../inject/models/service-types.js';
36
36
  import { declareSubjectReferenceReaders } from '../../base-classes/services/services/subject-reference-severance.backend.utils.js';
37
+ import { releaseStoredBodyFilesOfDeletedRows } from './inbound-delivery-stored-body.backend.service.js';
37
38
  /** The severer's identity, as the erasure registers it and its declaration names it. */
38
39
  export const INBOUND_DELIVERY_SUBJECT_SEVERER_REF = 'inbound-delivery-subjects';
39
40
  /** The delivery tables: one per scope variant of the polymorphic resource. */
@@ -150,6 +151,11 @@ export async function deleteInboundDeliveriesNamingKeys(input) {
150
151
  // Guarded on the keys (and the scope) as well as the ids: a row whose keys no longer name the person is not this erasure's.
151
152
  const deleted = await registry.deleteManyForInfrastructure(table, { _id: { $in: deletable }, ...selection }, executionContext, options);
152
153
  const outcome = await confirmSeveranceDelete({ registry, resourceType: table, handed: deletable, deleted, keys, ...(options ? { options } : {}) });
154
+ // #3395: a body too large for its row is a file linked to it, and a repository delete releases no file. The deleted rows'
155
+ // body files are marked deleted in the same transaction; the files cleanup removes their bytes.
156
+ // assurance-control: WILDO.PRIVACY.SUBJECT_ERASURE — a delivery's body stored outside its row is erased with the row.
157
+ const gone = new Set(outcome.confirmed);
158
+ await releaseStoredBodyFilesOfDeletedRows({ registry, table, rows: page.filter((row) => gone.has(String(row._id))), executionContext, ...(options ? { options } : {}) });
153
159
  confirmed.push(...outcome.confirmed);
154
160
  unconfirmed.push(...outcome.unconfirmed);
155
161
  }
@@ -232,7 +238,9 @@ export function inboundDeliverySubjectReaders() {
232
238
  return row;
233
239
  withheld.add('subjectKeys[]');
234
240
  withheld.add('rawBody');
235
- const { rawBody: _othersToo, ...kept } = row;
241
+ // #3395: a body too large for the row is the same payload, stored beside it: kept back with it.
242
+ withheld.add('storedBodyFile');
243
+ const { rawBody: _othersToo, storedBodyFile: _othersBodyToo, ...kept } = row;
236
244
  return { ...kept, subjectKeys: theirs };
237
245
  });
238
246
  return { rows, withheldWithinRows: [...withheld] };
@@ -1 +1 @@
1
- {"version":3,"file":"inbound-delivery-subject-erasure-severance.backend.js","sourceRoot":"","sources":["../../../../src/inbound/services/inbound-delivery-subject-erasure-severance.backend.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The inbound-delivery subject severer (#1642): a person's erasure DELETES every stored inbound delivery whose payload\n * names them, as the delivery's handler declared it (`subjectKeys`).\n *\n * ## Why a delivery is off the erasure graph, and why it is deleted rather than scrubbed\n *\n * A delivery (`INBOUND_DELIVERIES`, #1596) keeps the sender's raw payload, which routinely names a person (a contact's\n * address, a signer, a customer). It has no relationship to that person: it belongs to the organization (or the\n * application) it was routed to, so no erasure edge reaches it, and its body is stored base64, so nothing could find it\n * by searching. Its handler, which knows what its payload means, declares the people it names at receipt\n * (`InboundHandlerDefinition.subjectKeys`), and those keys are what this severer reads: the subject's user id and their\n * email address, lower-cased, as the handler contract asks keys to be written.\n *\n * The row is DELETED, not scrubbed: nothing references a delivery, and its payload scrubbed in place would leave a row\n * a replay could not parse. Deleting it does early what the OPERATIONAL_LOGS retention period would do later.\n *\n * ## What it does, per erasure\n *\n * - Before the erasure tears the subject's dependents down (`beforeDependentTeardown`), reads the phone numbers on\n * their profile and their credentials, which are scrubbed or deleted before `sever` runs.\n * - Reads the subjects' user rows in the erasure's transaction (the subject row is scrubbed AFTER the severers, so its\n * address is still there) and builds the keys: every user id, every address lower-cased, and every phone number in\n * E.164 form (an SMS notification is keyed by the person's number; an email channel delivery by its addresses).\n * - For each delivery table (organization and application), reads the matching rows in pages by `_id` (never inferring\n * the end from a short page), asks each page of the legal hold, and deletes the rows the hold does not keep, guarded\n * on their keys still naming the subject.\n * - Lists each row its delete answered for as `ROW_DELETED`, ids only, never the payload. A count shorter than the rows\n * handed is resolved by reading them back: a row still there and still naming the subject is reported unconfirmed.\n *\n * A delivery being processed when its row is deleted finishes its run; its settle finds no row. Rejected: refusing the\n * erasure while a delivery is leased. The run is the handler's work on behalf of the organization, already under way,\n * and an erasure that waited on it could wait on a retry policy measured in days.\n */\nimport {\n CoreResourceType,\n inboundSubjectKeyForEmailAddress,\n inboundSubjectKeyForPhoneNumber,\n SortOrder,\n SubjectErasureSeveredReferenceTreatment,\n type ResourceType,\n type SubjectErasureSeveredReference,\n} from '@wildo-ai/saas-models';\nimport type { Container } from 'inversify';\n\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport type { RepositoryOptions } from '~wildo-backend-lib/base-classes/models/repositories.backend.schemas';\nimport type { ServicesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/services/services-registry-handler.backend.service';\nimport type {\n SubjectReferenceExportRead,\n SubjectReferenceCaptureEvent,\n SubjectReferenceReader,\n SubjectReferenceSeveranceEvent,\n SubjectReferenceSeverer,\n} from '~wildo-backend-lib/base-classes/services/services/subject-reference-severance.backend.schemas';\nimport { declareSubjectReferenceReaders } from '~wildo-backend-lib/base-classes/services/services/subject-reference-severance.backend.utils';\n\n/** The severer's identity, as the erasure registers it and its declaration names it. */\nexport const INBOUND_DELIVERY_SUBJECT_SEVERER_REF = 'inbound-delivery-subjects';\n\n/** The delivery tables: one per scope variant of the polymorphic resource. */\nconst DELIVERY_TABLES: readonly ResourceType[] = [CoreResourceType.ORGANIZATION_INBOUND_DELIVERIES, CoreResourceType.APPLICATION_INBOUND_DELIVERIES];\n\n/**\n * Every table keyed by `subjectKeys` the way deliveries are (#1642): the deliveries, and the SMS provider reports the SMS\n * intake records from them (`smsProviderEvents`, #3394 item 2: the person's number and what they texted). One key names\n * a person in all of them, so one erasure removes them together.\n */\nexport const INBOUND_SUBJECT_KEYED_TABLES: readonly ResourceType[] = [...DELIVERY_TABLES, CoreResourceType.SMS_PROVIDER_EVENTS];\n\n/** How many deliveries one page reads; pages are read until one comes back empty. */\nconst PAGE_SIZE = 200;\n\ntype Registry = Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure' | 'deleteManyForInfrastructure' | 'hasRepository' | 'readUnscopedByKey'>;\n\n/**\n * The keys a person is named by in a delivery's `subjectKeys`: their user id, their email address lower-cased\n * (`inboundSubjectKeyForEmailAddress`, the form the handler contract writes), and each phone number they hold in E.164\n * form (`inboundSubjectKeyForPhoneNumber`, the form an SMS notification is keyed by), #1642. Pure, so the derivation is\n * pinned on its own.\n */\nexport function inboundDeliverySubjectKeysOfUser(\n user: { readonly _id: unknown; readonly email?: unknown },\n phoneNumbers: readonly unknown[] = [],\n): string[] {\n const keys = [String(user._id)];\n const address = typeof user.email === 'string' ? inboundSubjectKeyForEmailAddress(user.email) : undefined;\n if (address !== undefined) keys.push(address);\n for (const phoneNumber of phoneNumbers) {\n const key = typeof phoneNumber === 'string' ? inboundSubjectKeyForPhoneNumber(phoneNumber) : undefined;\n if (key !== undefined && !keys.includes(key)) keys.push(key);\n }\n return keys;\n}\n\n/**\n * Where a person's phone numbers are (#1642): the number on their profile and the one their sign-in credentials send\n * codes to. Both are DEPENDENTS of the person, scrubbed or deleted by the erasure before any severer runs, which is why\n * the severer reads them in `beforeDependentTeardown`.\n */\nconst PHONE_NUMBER_HOLDERS: readonly ResourceType[] = [CoreResourceType.USER_PROFILES, CoreResourceType.USER_CREDENTIALS];\n\n/** What the severer reads of the subjects before their dependents are torn down: each user's phone numbers. */\nexport interface InboundDeliverySubjectCapture {\n readonly phoneNumbersByUserId: Readonly<Record<string, readonly string[]>>;\n}\n\nfunction isInboundDeliverySubjectCapture(value: unknown): value is InboundDeliverySubjectCapture {\n return typeof value === 'object' && value !== null && typeof (value as { phoneNumbersByUserId?: unknown }).phoneNumbersByUserId === 'object';\n}\n\n/**\n * The phone numbers each of `userIds` holds on their profile or their credentials (#1642), raw as stored. Exported so\n * what an erasure deletes by and what an export reads by are derived from the same holders.\n */\nexport async function readSubjectPhoneNumbers(\n registry: Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure' | 'hasRepository'>,\n userIds: readonly string[],\n options?: RepositoryOptions,\n): Promise<InboundDeliverySubjectCapture> {\n return readSubjectPhoneNumbersThrough(\n (holder) => registry.hasRepository(holder),\n (holder, filter) => registry.findManyForInfrastructure<Record<string, unknown>>(holder, filter, undefined, options),\n userIds,\n );\n}\n\n/**\n * The same holders and the same extraction as {@link readSubjectPhoneNumbers}, through any read: the erasure's\n * infrastructure read, or a subject export's own door (#2958), so the keys an access export reads deliveries by are the\n * keys an erasure deletes them by.\n */\nexport async function readSubjectPhoneNumbersThrough(\n hasRepository: (resourceType: ResourceType) => boolean,\n readRows: (resourceType: ResourceType, filter: Record<string, unknown>) => Promise<Record<string, unknown>[]>,\n userIds: readonly string[],\n): Promise<InboundDeliverySubjectCapture> {\n const phoneNumbersByUserId: Record<string, string[]> = {};\n for (const holder of PHONE_NUMBER_HOLDERS) {\n if (userIds.length === 0 || !hasRepository(holder)) continue;\n const rows = await readRows(holder, { userId: { $in: [...userIds] } });\n for (const row of rows) {\n if (typeof row.phoneNumber !== 'string' || row.phoneNumber.length === 0) continue;\n const numbers = (phoneNumbersByUserId[String(row.userId)] ??= []);\n if (!numbers.includes(row.phoneNumber)) numbers.push(row.phoneNumber);\n }\n }\n return { phoneNumbersByUserId };\n}\n\n/**\n * Which of the rows a delete was handed it answered for, from its COUNT (#3272): equal answers for all of them; a\n * shorter count is resolved by reading the rows back. A row still there and still naming the subject was not deleted\n * (unconfirmed). The rows gone are this delete's when there are exactly as many as it counted; otherwise another writer\n * (the retention sweep) removed some too, a count cannot say which, and the receipt states none of them rather than\n * overstate. The delete form of `confirmSeveranceWrite`, whose read-back judges a row LEFT in place.\n */\nexport async function confirmSeveranceDelete(input: {\n readonly registry: Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure'>;\n readonly resourceType: ResourceType;\n readonly handed: readonly string[];\n readonly deleted: number;\n readonly keys: readonly string[];\n readonly options?: RepositoryOptions;\n}): Promise<{ readonly confirmed: readonly string[]; readonly unconfirmed: readonly string[] }> {\n const { registry, resourceType, handed, deleted, keys, options } = input;\n if (deleted === handed.length) return { confirmed: handed, unconfirmed: [] };\n const present = await registry.findManyForInfrastructure<Record<string, unknown>>(resourceType, { _id: { $in: [...handed] } }, undefined, options);\n const presentIds = new Set(present.map((row) => String(row._id)));\n const stillNamed = present\n .filter((row) => Array.isArray(row.subjectKeys) && row.subjectKeys.some((key) => keys.includes(String(key))))\n .map((row) => String(row._id));\n const gone = handed.filter((rowId) => !presentIds.has(rowId));\n return gone.length === deleted ? { confirmed: gone, unconfirmed: stillNamed } : { confirmed: [], unconfirmed: [...stillNamed, ...gone] };\n}\n\n/**\n * Delete the deliveries of `table` whose keys name one of `keys` (#1642): the one delete both doors make, a person's\n * erasure (this module's severer) and an administrator's erasure of a person with no account (`eraseForSubjectKey`).\n *\n * Reads the matching rows in pages by `_id` (never inferring the end from a short page), hands each page to `deletableOf`\n * (the legal hold's question: which of these may go), and deletes those, guarded on their keys still naming the person and\n * on `scope` (a caller confined to one organization passes its id). What each delete answered for is resolved by\n * {@link confirmSeveranceDelete}. `heldCount` is the rows the hold kept.\n */\nexport async function deleteInboundDeliveriesNamingKeys(input: {\n readonly registry: Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure' | 'deleteManyForInfrastructure'>;\n readonly table: ResourceType;\n readonly keys: readonly string[];\n /** A filter every deleted row must also match: the caller's scope. Absent for an erasure, which spans every scope. */\n readonly scope?: Record<string, unknown>;\n readonly deletableOf: (page: readonly Record<string, unknown>[]) => Promise<readonly string[]>;\n readonly executionContext: Parameters<RepositoriesRegistryHandlerBackendService['deleteManyForInfrastructure']>[2];\n readonly options?: RepositoryOptions;\n}): Promise<{ readonly confirmed: readonly string[]; readonly unconfirmed: readonly string[]; readonly heldCount: number }> {\n const { registry, table, keys, scope, deletableOf, executionContext, options } = input;\n const confirmed: string[] = [];\n const unconfirmed: string[] = [];\n let heldCount = 0;\n const selection = { subjectKeys: { $in: [...keys] }, ...(scope ?? {}) };\n // The deletes remove what the selection matched, so each page starts after the last row read by `_id`: a row the hold\n // keeps stays matched, and paging by `_id` never reads it twice.\n let after: string | undefined;\n for (;;) {\n const page = await registry.findManyForInfrastructure<Record<string, unknown>>(\n table, after === undefined ? selection : { $and: [selection, { _id: { $gt: after } }] }, undefined, options,\n { sort: [{ field: '_id', order: SortOrder.ASC }], limit: PAGE_SIZE },\n );\n if (page.length === 0) break;\n after = String(page[page.length - 1]!._id);\n const deletable = [...(await deletableOf(page))];\n heldCount += page.length - deletable.length;\n if (deletable.length === 0) continue;\n // Guarded on the keys (and the scope) as well as the ids: a row whose keys no longer name the person is not this erasure's.\n const deleted = await registry.deleteManyForInfrastructure(table, { _id: { $in: deletable }, ...selection }, executionContext, options);\n const outcome = await confirmSeveranceDelete({ registry, resourceType: table, handed: deletable, deleted, keys, ...(options ? { options } : {}) });\n confirmed.push(...outcome.confirmed);\n unconfirmed.push(...outcome.unconfirmed);\n }\n return { confirmed, unconfirmed, heldCount };\n}\n\n/** The severer, over the repositories registry (so a test can hand it a stack's). */\nexport function createInboundDeliverySubjectSeverer(repositoriesRegistry: () => Registry): SubjectReferenceSeverer {\n return {\n severerRef: INBOUND_DELIVERY_SUBJECT_SEVERER_REF,\n // The phone numbers are read here: by the time `sever` runs, the profile's number is scrubbed and the credentials\n // are gone, and a delivery keyed by the number would keep the person in its payload.\n async beforeDependentTeardown(event: SubjectReferenceCaptureEvent): Promise<InboundDeliverySubjectCapture> {\n const options = event.options?.transaction ? { transaction: event.options.transaction } : undefined;\n return readSubjectPhoneNumbers(repositoriesRegistry(), event.subjectIds, options);\n },\n async sever(event: SubjectReferenceSeveranceEvent): Promise<readonly SubjectErasureSeveredReference[]> {\n const registry = repositoriesRegistry();\n const tables = INBOUND_SUBJECT_KEYED_TABLES.filter((table) => registry.hasRepository(table));\n if (tables.length === 0) return [];\n const options = event.options?.transaction ? { transaction: event.options.transaction } : undefined;\n // Captured before the teardown in an erasure; read now when no capture reached this run (a caller with no\n // capture phase), which reads the holders as they stand.\n const captured = isInboundDeliverySubjectCapture(event.capturedBeforeTeardown)\n ? event.capturedBeforeTeardown\n : await readSubjectPhoneNumbers(registry, event.subjectIds, options);\n const keys = new Set<string>();\n for (const userId of event.subjectIds) {\n const user = await registry.readUnscopedByKey<{ readonly _id: unknown; readonly email?: unknown }>(CoreResourceType.USERS, { _id: userId }, options);\n for (const key of inboundDeliverySubjectKeysOfUser(user ?? { _id: userId }, captured.phoneNumbersByUserId[userId] ?? [])) keys.add(key);\n }\n const subjectKeys = [...keys];\n const severed: SubjectErasureSeveredReference[] = [];\n for (const table of tables) {\n const { confirmed, unconfirmed } = await deleteInboundDeliveriesNamingKeys({\n registry,\n table,\n keys: subjectKeys,\n deletableOf: (page) => event.partitionLegallyHeld(table, page),\n executionContext: event.executionContext,\n ...(options ? { options } : {}),\n });\n event.reportUnconfirmed(table, unconfirmed);\n for (const rowId of confirmed) severed.push({ resourceType: table, rowId, treatments: [SubjectErasureSeveredReferenceTreatment.ROW_DELETED] });\n }\n return severed;\n },\n };\n}\n\n/**\n * The readers a person's ACCESS export reads the stored inbound deliveries naming them through (#2958): the deliveries\n * whose handler declared one of their keys: their user id, their address lower-cased and the phone numbers they hold, the\n * keys this severer deletes by (`inboundDeliverySubjectKeysOfUser`, `readSubjectPhoneNumbersThrough`).\n * A delivery naming them is personal data concerning them (GDPR Art. 15(1)), and its handler's declaration decides what\n * else it holds about other people (Art. 15(4)):\n *\n * - `subjectKeys` keeps only THEIR keys: another key is another person.\n * - `rawBody`, the sender's payload, is disclosed only when the delivery names nobody else. The payload cannot be cut per\n * person (it is the exact signed bytes), so a delivery that also names someone else keeps it back, and the report says\n * so (`rawBody`). Rejected: disclosing every payload (it hands a third person's details to whoever is named beside\n * them) and withholding every payload (a delivery about them alone would then disclose nothing of what it said).\n * - `replays` names the administrators who replayed it, and is withheld.\n *\n * spec-cite: GDPR Art. 15(1), 15(4) (https://gdpr-info.eu/art-15-gdpr/)\n */\nexport function inboundDeliverySubjectReaders(): readonly SubjectReferenceReader[] {\n return declareSubjectReferenceReaders(INBOUND_DELIVERY_SUBJECT_SEVERER_REF, [...DELIVERY_TABLES.map((table) => ({\n resourceType: table,\n locator: 'subjectKeys',\n othersDataFields: ['replays'],\n async read({ subjectIds, readRows, hasRepository }: SubjectReferenceExportRead) {\n const keys = await subjectKeysForExport(subjectIds, readRows, hasRepository);\n const withheld = new Set<string>();\n const rows = (await readRows(table, { subjectKeys: { $in: [...keys] } })).map((row) => {\n const declared = Array.isArray(row.subjectKeys) ? row.subjectKeys.map(String) : [];\n const theirs = declared.filter((key) => keys.has(key));\n if (theirs.length === declared.length) return row;\n withheld.add('subjectKeys[]');\n withheld.add('rawBody');\n const { rawBody: _othersToo, ...kept } = row;\n return { ...kept, subjectKeys: theirs };\n });\n return { rows, withheldWithinRows: [...withheld] };\n },\n })), {\n // #3394 item 2: the SMS reports naming them by their number. A report names one person (the sender of a received\n // text, the recipient of the application's), and its other number is the application's own, so the row is theirs.\n resourceType: CoreResourceType.SMS_PROVIDER_EVENTS,\n locator: 'subjectKeys',\n othersDataFields: [],\n async read({ subjectIds, readRows, hasRepository }: SubjectReferenceExportRead) {\n if (!hasRepository(CoreResourceType.SMS_PROVIDER_EVENTS)) return { rows: [], withheldWithinRows: [] };\n const keys = await subjectKeysForExport(subjectIds, readRows, hasRepository);\n return { rows: await readRows(CoreResourceType.SMS_PROVIDER_EVENTS, { subjectKeys: { $in: [...keys] } }), withheldWithinRows: [] };\n },\n }]);\n}\n\n/** The keys a person's export reads by: the same derivation as the erasure's (id, address, phone numbers). */\nasync function subjectKeysForExport(\n subjectIds: readonly string[],\n readRows: SubjectReferenceExportRead['readRows'],\n hasRepository: SubjectReferenceExportRead['hasRepository'],\n): Promise<Set<string>> {\n const users = hasRepository(CoreResourceType.USERS) ? await readRows(CoreResourceType.USERS, { _id: { $in: [...subjectIds] } }) : [];\n const { phoneNumbersByUserId } = await readSubjectPhoneNumbersThrough(hasRepository, readRows, subjectIds);\n return new Set(subjectIds.flatMap((userId) => {\n const user = users.find((row) => String(row._id) === userId);\n return inboundDeliverySubjectKeysOfUser({ _id: userId, email: user?.email }, phoneNumbersByUserId[userId] ?? []);\n }));\n}\n\n/**\n * Register the inbound-delivery subject severer for a `USERS` erasure (#1642), resolved against the container at the\n * erasure.\n *\n * assurance-control: WILDO.PRIVACY.SUBJECT_ERASURE — a person's erasure deletes the stored inbound deliveries whose payload names them, by the keys their handler declared.\n */\nexport function registerInboundDeliverySubjectErasureSeverance(\n servicesRegistry: Pick<ServicesRegistryHandlerBackendService, 'registerSubjectReferenceSeverer'>,\n container: Container,\n): void {\n const severer = createInboundDeliverySubjectSeverer(\n () => container.get<RepositoriesRegistryHandlerBackendService>(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService),\n );\n servicesRegistry.registerSubjectReferenceSeverer(CoreResourceType.USERS, {\n severerRef: severer.severerRef,\n async beforeDependentTeardown(event) {\n if (!container.isBound(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)) return undefined;\n return severer.beforeDependentTeardown!(event);\n },\n subjectReferenceReaders: inboundDeliverySubjectReaders(),\n async sever(event) {\n if (!container.isBound(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)) return [];\n return severer.sever(event);\n },\n });\n}\n"]}
1
+ {"version":3,"file":"inbound-delivery-subject-erasure-severance.backend.js","sourceRoot":"","sources":["../../../../src/inbound/services/inbound-delivery-subject-erasure-severance.backend.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The inbound-delivery subject severer (#1642): a person's erasure DELETES every stored inbound delivery whose payload\n * names them, as the delivery's handler declared it (`subjectKeys`).\n *\n * ## Why a delivery is off the erasure graph, and why it is deleted rather than scrubbed\n *\n * A delivery (`INBOUND_DELIVERIES`, #1596) keeps the sender's raw payload, which routinely names a person (a contact's\n * address, a signer, a customer). It has no relationship to that person: it belongs to the organization (or the\n * application) it was routed to, so no erasure edge reaches it, and its body is stored base64, so nothing could find it\n * by searching. Its handler, which knows what its payload means, declares the people it names at receipt\n * (`InboundHandlerDefinition.subjectKeys`), and those keys are what this severer reads: the subject's user id and their\n * email address, lower-cased, as the handler contract asks keys to be written.\n *\n * The row is DELETED, not scrubbed: nothing references a delivery, and its payload scrubbed in place would leave a row\n * a replay could not parse. Deleting it does early what the OPERATIONAL_LOGS retention period would do later.\n *\n * ## What it does, per erasure\n *\n * - Before the erasure tears the subject's dependents down (`beforeDependentTeardown`), reads the phone numbers on\n * their profile and their credentials, which are scrubbed or deleted before `sever` runs.\n * - Reads the subjects' user rows in the erasure's transaction (the subject row is scrubbed AFTER the severers, so its\n * address is still there) and builds the keys: every user id, every address lower-cased, and every phone number in\n * E.164 form (an SMS notification is keyed by the person's number; an email channel delivery by its addresses).\n * - For each delivery table (organization and application), reads the matching rows in pages by `_id` (never inferring\n * the end from a short page), asks each page of the legal hold, and deletes the rows the hold does not keep, guarded\n * on their keys still naming the subject.\n * - Lists each row its delete answered for as `ROW_DELETED`, ids only, never the payload. A count shorter than the rows\n * handed is resolved by reading them back: a row still there and still naming the subject is reported unconfirmed.\n *\n * A delivery being processed when its row is deleted finishes its run; its settle finds no row. Rejected: refusing the\n * erasure while a delivery is leased. The run is the handler's work on behalf of the organization, already under way,\n * and an erasure that waited on it could wait on a retry policy measured in days.\n */\nimport {\n CoreResourceType,\n inboundSubjectKeyForEmailAddress,\n inboundSubjectKeyForPhoneNumber,\n SortOrder,\n SubjectErasureSeveredReferenceTreatment,\n type ResourceType,\n type SubjectErasureSeveredReference,\n} from '@wildo-ai/saas-models';\nimport type { Container } from 'inversify';\n\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport type { RepositoryOptions } from '~wildo-backend-lib/base-classes/models/repositories.backend.schemas';\nimport type { ServicesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/services/services-registry-handler.backend.service';\nimport type {\n SubjectReferenceExportRead,\n SubjectReferenceCaptureEvent,\n SubjectReferenceReader,\n SubjectReferenceSeveranceEvent,\n SubjectReferenceSeverer,\n} from '~wildo-backend-lib/base-classes/services/services/subject-reference-severance.backend.schemas';\nimport { declareSubjectReferenceReaders } from '~wildo-backend-lib/base-classes/services/services/subject-reference-severance.backend.utils';\nimport { releaseStoredBodyFilesOfDeletedRows } from './inbound-delivery-stored-body.backend.service';\n\n/** The severer's identity, as the erasure registers it and its declaration names it. */\nexport const INBOUND_DELIVERY_SUBJECT_SEVERER_REF = 'inbound-delivery-subjects';\n\n/** The delivery tables: one per scope variant of the polymorphic resource. */\nconst DELIVERY_TABLES: readonly ResourceType[] = [CoreResourceType.ORGANIZATION_INBOUND_DELIVERIES, CoreResourceType.APPLICATION_INBOUND_DELIVERIES];\n\n/**\n * Every table keyed by `subjectKeys` the way deliveries are (#1642): the deliveries, and the SMS provider reports the SMS\n * intake records from them (`smsProviderEvents`, #3394 item 2: the person's number and what they texted). One key names\n * a person in all of them, so one erasure removes them together.\n */\nexport const INBOUND_SUBJECT_KEYED_TABLES: readonly ResourceType[] = [...DELIVERY_TABLES, CoreResourceType.SMS_PROVIDER_EVENTS];\n\n/** How many deliveries one page reads; pages are read until one comes back empty. */\nconst PAGE_SIZE = 200;\n\ntype Registry = Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure' | 'deleteManyForInfrastructure' | 'hasRepository' | 'readUnscopedByKey' | 'atomicConditionalSet'>;\n\n/**\n * The keys a person is named by in a delivery's `subjectKeys`: their user id, their email address lower-cased\n * (`inboundSubjectKeyForEmailAddress`, the form the handler contract writes), and each phone number they hold in E.164\n * form (`inboundSubjectKeyForPhoneNumber`, the form an SMS notification is keyed by), #1642. Pure, so the derivation is\n * pinned on its own.\n */\nexport function inboundDeliverySubjectKeysOfUser(\n user: { readonly _id: unknown; readonly email?: unknown },\n phoneNumbers: readonly unknown[] = [],\n): string[] {\n const keys = [String(user._id)];\n const address = typeof user.email === 'string' ? inboundSubjectKeyForEmailAddress(user.email) : undefined;\n if (address !== undefined) keys.push(address);\n for (const phoneNumber of phoneNumbers) {\n const key = typeof phoneNumber === 'string' ? inboundSubjectKeyForPhoneNumber(phoneNumber) : undefined;\n if (key !== undefined && !keys.includes(key)) keys.push(key);\n }\n return keys;\n}\n\n/**\n * Where a person's phone numbers are (#1642): the number on their profile and the one their sign-in credentials send\n * codes to. Both are DEPENDENTS of the person, scrubbed or deleted by the erasure before any severer runs, which is why\n * the severer reads them in `beforeDependentTeardown`.\n */\nconst PHONE_NUMBER_HOLDERS: readonly ResourceType[] = [CoreResourceType.USER_PROFILES, CoreResourceType.USER_CREDENTIALS];\n\n/** What the severer reads of the subjects before their dependents are torn down: each user's phone numbers. */\nexport interface InboundDeliverySubjectCapture {\n readonly phoneNumbersByUserId: Readonly<Record<string, readonly string[]>>;\n}\n\nfunction isInboundDeliverySubjectCapture(value: unknown): value is InboundDeliverySubjectCapture {\n return typeof value === 'object' && value !== null && typeof (value as { phoneNumbersByUserId?: unknown }).phoneNumbersByUserId === 'object';\n}\n\n/**\n * The phone numbers each of `userIds` holds on their profile or their credentials (#1642), raw as stored. Exported so\n * what an erasure deletes by and what an export reads by are derived from the same holders.\n */\nexport async function readSubjectPhoneNumbers(\n registry: Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure' | 'hasRepository'>,\n userIds: readonly string[],\n options?: RepositoryOptions,\n): Promise<InboundDeliverySubjectCapture> {\n return readSubjectPhoneNumbersThrough(\n (holder) => registry.hasRepository(holder),\n (holder, filter) => registry.findManyForInfrastructure<Record<string, unknown>>(holder, filter, undefined, options),\n userIds,\n );\n}\n\n/**\n * The same holders and the same extraction as {@link readSubjectPhoneNumbers}, through any read: the erasure's\n * infrastructure read, or a subject export's own door (#2958), so the keys an access export reads deliveries by are the\n * keys an erasure deletes them by.\n */\nexport async function readSubjectPhoneNumbersThrough(\n hasRepository: (resourceType: ResourceType) => boolean,\n readRows: (resourceType: ResourceType, filter: Record<string, unknown>) => Promise<Record<string, unknown>[]>,\n userIds: readonly string[],\n): Promise<InboundDeliverySubjectCapture> {\n const phoneNumbersByUserId: Record<string, string[]> = {};\n for (const holder of PHONE_NUMBER_HOLDERS) {\n if (userIds.length === 0 || !hasRepository(holder)) continue;\n const rows = await readRows(holder, { userId: { $in: [...userIds] } });\n for (const row of rows) {\n if (typeof row.phoneNumber !== 'string' || row.phoneNumber.length === 0) continue;\n const numbers = (phoneNumbersByUserId[String(row.userId)] ??= []);\n if (!numbers.includes(row.phoneNumber)) numbers.push(row.phoneNumber);\n }\n }\n return { phoneNumbersByUserId };\n}\n\n/**\n * Which of the rows a delete was handed it answered for, from its COUNT (#3272): equal answers for all of them; a\n * shorter count is resolved by reading the rows back. A row still there and still naming the subject was not deleted\n * (unconfirmed). The rows gone are this delete's when there are exactly as many as it counted; otherwise another writer\n * (the retention sweep) removed some too, a count cannot say which, and the receipt states none of them rather than\n * overstate. The delete form of `confirmSeveranceWrite`, whose read-back judges a row LEFT in place.\n */\nexport async function confirmSeveranceDelete(input: {\n readonly registry: Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure'>;\n readonly resourceType: ResourceType;\n readonly handed: readonly string[];\n readonly deleted: number;\n readonly keys: readonly string[];\n readonly options?: RepositoryOptions;\n}): Promise<{ readonly confirmed: readonly string[]; readonly unconfirmed: readonly string[] }> {\n const { registry, resourceType, handed, deleted, keys, options } = input;\n if (deleted === handed.length) return { confirmed: handed, unconfirmed: [] };\n const present = await registry.findManyForInfrastructure<Record<string, unknown>>(resourceType, { _id: { $in: [...handed] } }, undefined, options);\n const presentIds = new Set(present.map((row) => String(row._id)));\n const stillNamed = present\n .filter((row) => Array.isArray(row.subjectKeys) && row.subjectKeys.some((key) => keys.includes(String(key))))\n .map((row) => String(row._id));\n const gone = handed.filter((rowId) => !presentIds.has(rowId));\n return gone.length === deleted ? { confirmed: gone, unconfirmed: stillNamed } : { confirmed: [], unconfirmed: [...stillNamed, ...gone] };\n}\n\n/**\n * Delete the deliveries of `table` whose keys name one of `keys` (#1642): the one delete both doors make, a person's\n * erasure (this module's severer) and an administrator's erasure of a person with no account (`eraseForSubjectKey`).\n *\n * Reads the matching rows in pages by `_id` (never inferring the end from a short page), hands each page to `deletableOf`\n * (the legal hold's question: which of these may go), and deletes those, guarded on their keys still naming the person and\n * on `scope` (a caller confined to one organization passes its id). What each delete answered for is resolved by\n * {@link confirmSeveranceDelete}. `heldCount` is the rows the hold kept.\n */\nexport async function deleteInboundDeliveriesNamingKeys(input: {\n readonly registry: Pick<RepositoriesRegistryHandlerBackendService, 'findManyForInfrastructure' | 'deleteManyForInfrastructure' | 'atomicConditionalSet'>;\n readonly table: ResourceType;\n readonly keys: readonly string[];\n /** A filter every deleted row must also match: the caller's scope. Absent for an erasure, which spans every scope. */\n readonly scope?: Record<string, unknown>;\n readonly deletableOf: (page: readonly Record<string, unknown>[]) => Promise<readonly string[]>;\n readonly executionContext: Parameters<RepositoriesRegistryHandlerBackendService['deleteManyForInfrastructure']>[2];\n readonly options?: RepositoryOptions;\n}): Promise<{ readonly confirmed: readonly string[]; readonly unconfirmed: readonly string[]; readonly heldCount: number }> {\n const { registry, table, keys, scope, deletableOf, executionContext, options } = input;\n const confirmed: string[] = [];\n const unconfirmed: string[] = [];\n let heldCount = 0;\n const selection = { subjectKeys: { $in: [...keys] }, ...(scope ?? {}) };\n // The deletes remove what the selection matched, so each page starts after the last row read by `_id`: a row the hold\n // keeps stays matched, and paging by `_id` never reads it twice.\n let after: string | undefined;\n for (;;) {\n const page = await registry.findManyForInfrastructure<Record<string, unknown>>(\n table, after === undefined ? selection : { $and: [selection, { _id: { $gt: after } }] }, undefined, options,\n { sort: [{ field: '_id', order: SortOrder.ASC }], limit: PAGE_SIZE },\n );\n if (page.length === 0) break;\n after = String(page[page.length - 1]!._id);\n const deletable = [...(await deletableOf(page))];\n heldCount += page.length - deletable.length;\n if (deletable.length === 0) continue;\n // Guarded on the keys (and the scope) as well as the ids: a row whose keys no longer name the person is not this erasure's.\n const deleted = await registry.deleteManyForInfrastructure(table, { _id: { $in: deletable }, ...selection }, executionContext, options);\n const outcome = await confirmSeveranceDelete({ registry, resourceType: table, handed: deletable, deleted, keys, ...(options ? { options } : {}) });\n // #3395: a body too large for its row is a file linked to it, and a repository delete releases no file. The deleted rows'\n // body files are marked deleted in the same transaction; the files cleanup removes their bytes.\n // assurance-control: WILDO.PRIVACY.SUBJECT_ERASURE — a delivery's body stored outside its row is erased with the row.\n const gone = new Set(outcome.confirmed);\n await releaseStoredBodyFilesOfDeletedRows({ registry, table, rows: page.filter((row) => gone.has(String(row._id))), executionContext, ...(options ? { options } : {}) });\n confirmed.push(...outcome.confirmed);\n unconfirmed.push(...outcome.unconfirmed);\n }\n return { confirmed, unconfirmed, heldCount };\n}\n\n/** The severer, over the repositories registry (so a test can hand it a stack's). */\nexport function createInboundDeliverySubjectSeverer(repositoriesRegistry: () => Registry): SubjectReferenceSeverer {\n return {\n severerRef: INBOUND_DELIVERY_SUBJECT_SEVERER_REF,\n // The phone numbers are read here: by the time `sever` runs, the profile's number is scrubbed and the credentials\n // are gone, and a delivery keyed by the number would keep the person in its payload.\n async beforeDependentTeardown(event: SubjectReferenceCaptureEvent): Promise<InboundDeliverySubjectCapture> {\n const options = event.options?.transaction ? { transaction: event.options.transaction } : undefined;\n return readSubjectPhoneNumbers(repositoriesRegistry(), event.subjectIds, options);\n },\n async sever(event: SubjectReferenceSeveranceEvent): Promise<readonly SubjectErasureSeveredReference[]> {\n const registry = repositoriesRegistry();\n const tables = INBOUND_SUBJECT_KEYED_TABLES.filter((table) => registry.hasRepository(table));\n if (tables.length === 0) return [];\n const options = event.options?.transaction ? { transaction: event.options.transaction } : undefined;\n // Captured before the teardown in an erasure; read now when no capture reached this run (a caller with no\n // capture phase), which reads the holders as they stand.\n const captured = isInboundDeliverySubjectCapture(event.capturedBeforeTeardown)\n ? event.capturedBeforeTeardown\n : await readSubjectPhoneNumbers(registry, event.subjectIds, options);\n const keys = new Set<string>();\n for (const userId of event.subjectIds) {\n const user = await registry.readUnscopedByKey<{ readonly _id: unknown; readonly email?: unknown }>(CoreResourceType.USERS, { _id: userId }, options);\n for (const key of inboundDeliverySubjectKeysOfUser(user ?? { _id: userId }, captured.phoneNumbersByUserId[userId] ?? [])) keys.add(key);\n }\n const subjectKeys = [...keys];\n const severed: SubjectErasureSeveredReference[] = [];\n for (const table of tables) {\n const { confirmed, unconfirmed } = await deleteInboundDeliveriesNamingKeys({\n registry,\n table,\n keys: subjectKeys,\n deletableOf: (page) => event.partitionLegallyHeld(table, page),\n executionContext: event.executionContext,\n ...(options ? { options } : {}),\n });\n event.reportUnconfirmed(table, unconfirmed);\n for (const rowId of confirmed) severed.push({ resourceType: table, rowId, treatments: [SubjectErasureSeveredReferenceTreatment.ROW_DELETED] });\n }\n return severed;\n },\n };\n}\n\n/**\n * The readers a person's ACCESS export reads the stored inbound deliveries naming them through (#2958): the deliveries\n * whose handler declared one of their keys: their user id, their address lower-cased and the phone numbers they hold, the\n * keys this severer deletes by (`inboundDeliverySubjectKeysOfUser`, `readSubjectPhoneNumbersThrough`).\n * A delivery naming them is personal data concerning them (GDPR Art. 15(1)), and its handler's declaration decides what\n * else it holds about other people (Art. 15(4)):\n *\n * - `subjectKeys` keeps only THEIR keys: another key is another person.\n * - `rawBody`, the sender's payload, is disclosed only when the delivery names nobody else. The payload cannot be cut per\n * person (it is the exact signed bytes), so a delivery that also names someone else keeps it back, and the report says\n * so (`rawBody`). Rejected: disclosing every payload (it hands a third person's details to whoever is named beside\n * them) and withholding every payload (a delivery about them alone would then disclose nothing of what it said).\n * - `replays` names the administrators who replayed it, and is withheld.\n *\n * spec-cite: GDPR Art. 15(1), 15(4) (https://gdpr-info.eu/art-15-gdpr/)\n */\nexport function inboundDeliverySubjectReaders(): readonly SubjectReferenceReader[] {\n return declareSubjectReferenceReaders(INBOUND_DELIVERY_SUBJECT_SEVERER_REF, [...DELIVERY_TABLES.map((table) => ({\n resourceType: table,\n locator: 'subjectKeys',\n othersDataFields: ['replays'],\n async read({ subjectIds, readRows, hasRepository }: SubjectReferenceExportRead) {\n const keys = await subjectKeysForExport(subjectIds, readRows, hasRepository);\n const withheld = new Set<string>();\n const rows = (await readRows(table, { subjectKeys: { $in: [...keys] } })).map((row) => {\n const declared = Array.isArray(row.subjectKeys) ? row.subjectKeys.map(String) : [];\n const theirs = declared.filter((key) => keys.has(key));\n if (theirs.length === declared.length) return row;\n withheld.add('subjectKeys[]');\n withheld.add('rawBody');\n // #3395: a body too large for the row is the same payload, stored beside it: kept back with it.\n withheld.add('storedBodyFile');\n const { rawBody: _othersToo, storedBodyFile: _othersBodyToo, ...kept } = row;\n return { ...kept, subjectKeys: theirs };\n });\n return { rows, withheldWithinRows: [...withheld] };\n },\n })), {\n // #3394 item 2: the SMS reports naming them by their number. A report names one person (the sender of a received\n // text, the recipient of the application's), and its other number is the application's own, so the row is theirs.\n resourceType: CoreResourceType.SMS_PROVIDER_EVENTS,\n locator: 'subjectKeys',\n othersDataFields: [],\n async read({ subjectIds, readRows, hasRepository }: SubjectReferenceExportRead) {\n if (!hasRepository(CoreResourceType.SMS_PROVIDER_EVENTS)) return { rows: [], withheldWithinRows: [] };\n const keys = await subjectKeysForExport(subjectIds, readRows, hasRepository);\n return { rows: await readRows(CoreResourceType.SMS_PROVIDER_EVENTS, { subjectKeys: { $in: [...keys] } }), withheldWithinRows: [] };\n },\n }]);\n}\n\n/** The keys a person's export reads by: the same derivation as the erasure's (id, address, phone numbers). */\nasync function subjectKeysForExport(\n subjectIds: readonly string[],\n readRows: SubjectReferenceExportRead['readRows'],\n hasRepository: SubjectReferenceExportRead['hasRepository'],\n): Promise<Set<string>> {\n const users = hasRepository(CoreResourceType.USERS) ? await readRows(CoreResourceType.USERS, { _id: { $in: [...subjectIds] } }) : [];\n const { phoneNumbersByUserId } = await readSubjectPhoneNumbersThrough(hasRepository, readRows, subjectIds);\n return new Set(subjectIds.flatMap((userId) => {\n const user = users.find((row) => String(row._id) === userId);\n return inboundDeliverySubjectKeysOfUser({ _id: userId, email: user?.email }, phoneNumbersByUserId[userId] ?? []);\n }));\n}\n\n/**\n * Register the inbound-delivery subject severer for a `USERS` erasure (#1642), resolved against the container at the\n * erasure.\n *\n * assurance-control: WILDO.PRIVACY.SUBJECT_ERASURE — a person's erasure deletes the stored inbound deliveries whose payload names them, by the keys their handler declared.\n */\nexport function registerInboundDeliverySubjectErasureSeverance(\n servicesRegistry: Pick<ServicesRegistryHandlerBackendService, 'registerSubjectReferenceSeverer'>,\n container: Container,\n): void {\n const severer = createInboundDeliverySubjectSeverer(\n () => container.get<RepositoriesRegistryHandlerBackendService>(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService),\n );\n servicesRegistry.registerSubjectReferenceSeverer(CoreResourceType.USERS, {\n severerRef: severer.severerRef,\n async beforeDependentTeardown(event) {\n if (!container.isBound(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)) return undefined;\n return severer.beforeDependentTeardown!(event);\n },\n subjectReferenceReaders: inboundDeliverySubjectReaders(),\n async sever(event) {\n if (!container.isBound(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)) return [];\n return severer.sever(event);\n },\n });\n}\n"]}
@@ -273,6 +273,7 @@ export * from './data-seeding/services/shared/data-seed-scope-resolution.backend
273
273
  export * from './data-seeding/services/shared/data-seed-scope-iteration.shared.utils';
274
274
  export * from './external-data/controllers/external-data-admin.backend.contracts';
275
275
  export * from './compliance/approval-seals/approval-seals-admin.backend.contracts';
276
+ export * from './compliance/approval-seals/approval-seal-currency.backend';
276
277
  export * from './external-data/controllers/external-data-admin.backend.controller';
277
278
  export * from './data-seeding/controllers/data-seeding-admin.backend.contracts';
278
279
  export * from './data-seeding/controllers/data-seeding-admin.backend.controller';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/dist/esm/index.js CHANGED
@@ -403,6 +403,7 @@ export * from './data-seeding/services/shared/data-seed-scope-iteration.shared.u
403
403
  // Data Seeding — admin controller (Phase 6.C — operator-facing surface)
404
404
  export * from './external-data/controllers/external-data-admin.backend.contracts.js';
405
405
  export * from './compliance/approval-seals/approval-seals-admin.backend.contracts.js';
406
+ export * from './compliance/approval-seals/approval-seal-currency.backend.js';
406
407
  export * from './external-data/controllers/external-data-admin.backend.controller.js';
407
408
  export * from './data-seeding/controllers/data-seeding-admin.backend.contracts.js';
408
409
  export * from './data-seeding/controllers/data-seeding-admin.backend.controller.js';