@tellescope/sdk 1.256.13 → 1.256.15

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 (352) hide show
  1. package/lib/cjs/tests/api_tests/auto_merge_form_submission.test.js +1 -1
  2. package/lib/cjs/tests/api_tests/auto_merge_form_submission.test.js.map +1 -1
  3. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.d.ts +5 -0
  4. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.d.ts.map +1 -0
  5. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.js +388 -0
  6. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.js.map +1 -0
  7. package/lib/cjs/tests/api_tests/integrations_redacted.test.js +3 -3
  8. package/lib/cjs/tests/api_tests/integrations_redacted.test.js.map +1 -1
  9. package/lib/cjs/tests/api_tests/organization_signup.test.d.ts +20 -0
  10. package/lib/cjs/tests/api_tests/organization_signup.test.d.ts.map +1 -0
  11. package/lib/cjs/tests/api_tests/organization_signup.test.js +272 -0
  12. package/lib/cjs/tests/api_tests/organization_signup.test.js.map +1 -0
  13. package/lib/cjs/tests/api_tests/purchase_made_trigger.test.d.ts.map +1 -1
  14. package/lib/cjs/tests/api_tests/purchase_made_trigger.test.js +103 -162
  15. package/lib/cjs/tests/api_tests/purchase_made_trigger.test.js.map +1 -1
  16. package/lib/cjs/tests/api_tests/security/F-0179-booking-info-idor-token-mint.test.d.ts +30 -0
  17. package/lib/cjs/tests/api_tests/security/F-0179-booking-info-idor-token-mint.test.d.ts.map +1 -0
  18. package/lib/cjs/tests/api_tests/security/F-0179-booking-info-idor-token-mint.test.js +336 -0
  19. package/lib/cjs/tests/api_tests/security/F-0179-booking-info-idor-token-mint.test.js.map +1 -0
  20. package/lib/cjs/tests/api_tests/security/F-0185-startlinktoken-enduser-staff-escalation.test.d.ts +6 -0
  21. package/lib/cjs/tests/api_tests/security/F-0185-startlinktoken-enduser-staff-escalation.test.d.ts.map +1 -0
  22. package/lib/cjs/tests/api_tests/security/F-0185-startlinktoken-enduser-staff-escalation.test.js +354 -0
  23. package/lib/cjs/tests/api_tests/security/F-0185-startlinktoken-enduser-staff-escalation.test.js.map +1 -0
  24. package/lib/cjs/tests/api_tests/security/F-0191-schema-adminonly-enforcement.test.d.ts +46 -0
  25. package/lib/cjs/tests/api_tests/security/F-0191-schema-adminonly-enforcement.test.d.ts.map +1 -0
  26. package/lib/cjs/tests/api_tests/security/F-0191-schema-adminonly-enforcement.test.js +389 -0
  27. package/lib/cjs/tests/api_tests/security/F-0191-schema-adminonly-enforcement.test.js.map +1 -0
  28. package/lib/cjs/tests/api_tests/security/F-0192-automated-actions-process-gate.test.d.ts +43 -0
  29. package/lib/cjs/tests/api_tests/security/F-0192-automated-actions-process-gate.test.d.ts.map +1 -0
  30. package/lib/cjs/tests/api_tests/security/F-0192-automated-actions-process-gate.test.js +324 -0
  31. package/lib/cjs/tests/api_tests/security/F-0192-automated-actions-process-gate.test.js.map +1 -0
  32. package/lib/cjs/tests/api_tests/security/F-0196-add-to-journey-foreign-enduserid.test.d.ts +43 -0
  33. package/lib/cjs/tests/api_tests/security/F-0196-add-to-journey-foreign-enduserid.test.d.ts.map +1 -0
  34. package/lib/cjs/tests/api_tests/security/F-0196-add-to-journey-foreign-enduserid.test.js +282 -0
  35. package/lib/cjs/tests/api_tests/security/F-0196-add-to-journey-foreign-enduserid.test.js.map +1 -0
  36. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts +33 -0
  37. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts.map +1 -0
  38. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.js +249 -0
  39. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.js.map +1 -0
  40. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts +42 -0
  41. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -0
  42. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +281 -0
  43. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -0
  44. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.d.ts +38 -0
  45. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.d.ts.map +1 -0
  46. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.js +390 -0
  47. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.js.map +1 -0
  48. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.d.ts +6 -0
  49. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.d.ts.map +1 -0
  50. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.js +1003 -0
  51. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.js.map +1 -0
  52. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.d.ts +42 -0
  53. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.d.ts.map +1 -0
  54. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.js +323 -0
  55. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.js.map +1 -0
  56. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts +29 -0
  57. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts.map +1 -0
  58. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.js +335 -0
  59. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.js.map +1 -0
  60. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts +32 -0
  61. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts.map +1 -0
  62. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js +237 -0
  63. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js.map +1 -0
  64. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts +28 -0
  65. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts.map +1 -0
  66. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.js +349 -0
  67. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.js.map +1 -0
  68. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts +30 -0
  69. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts.map +1 -0
  70. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js +314 -0
  71. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js.map +1 -0
  72. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.d.ts +21 -0
  73. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.d.ts.map +1 -0
  74. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.js +362 -0
  75. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.js.map +1 -0
  76. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.d.ts +21 -0
  77. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.d.ts.map +1 -0
  78. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.js +366 -0
  79. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.js.map +1 -0
  80. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.d.ts +32 -0
  81. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.d.ts.map +1 -0
  82. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.js +248 -0
  83. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.js.map +1 -0
  84. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts +19 -0
  85. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts.map +1 -0
  86. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.js +138 -0
  87. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.js.map +1 -0
  88. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts +24 -0
  89. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
  90. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js +201 -0
  91. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js.map +1 -0
  92. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.d.ts +29 -0
  93. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.d.ts.map +1 -0
  94. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.js +278 -0
  95. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.js.map +1 -0
  96. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.d.ts +17 -0
  97. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.d.ts.map +1 -0
  98. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.js +155 -0
  99. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.js.map +1 -0
  100. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.d.ts +2 -0
  101. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.d.ts.map +1 -0
  102. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.js +88 -0
  103. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.js.map +1 -0
  104. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts +34 -0
  105. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts.map +1 -0
  106. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.js +230 -0
  107. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.js.map +1 -0
  108. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts +2 -0
  109. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts.map +1 -0
  110. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js +242 -0
  111. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js.map +1 -0
  112. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.d.ts +2 -0
  113. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.d.ts.map +1 -0
  114. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.js +148 -0
  115. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.js.map +1 -0
  116. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts +45 -0
  117. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts.map +1 -0
  118. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.js +388 -0
  119. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.js.map +1 -0
  120. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.d.ts +38 -0
  121. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.d.ts.map +1 -0
  122. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.js +222 -0
  123. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.js.map +1 -0
  124. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts +6 -0
  125. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts.map +1 -0
  126. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js +354 -0
  127. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js.map +1 -0
  128. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts +28 -0
  129. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts.map +1 -0
  130. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.js +442 -0
  131. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.js.map +1 -0
  132. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.d.ts +19 -0
  133. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.d.ts.map +1 -0
  134. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.js +156 -0
  135. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.js.map +1 -0
  136. package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts +5 -0
  137. package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts.map +1 -0
  138. package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.js +329 -0
  139. package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.js.map +1 -0
  140. package/lib/cjs/tests/api_tests/webhook_error_handling.test.js +2 -2
  141. package/lib/cjs/tests/api_tests/webhook_error_handling.test.js.map +1 -1
  142. package/lib/cjs/tests/setup_isolated.d.ts +68 -0
  143. package/lib/cjs/tests/setup_isolated.d.ts.map +1 -0
  144. package/lib/cjs/tests/setup_isolated.js +232 -0
  145. package/lib/cjs/tests/setup_isolated.js.map +1 -0
  146. package/lib/cjs/tests/tests.d.ts.map +1 -1
  147. package/lib/cjs/tests/tests.js +287 -227
  148. package/lib/cjs/tests/tests.js.map +1 -1
  149. package/lib/cjs/tests/unit_tests/do_not_send_address.test.d.ts +2 -0
  150. package/lib/cjs/tests/unit_tests/do_not_send_address.test.d.ts.map +1 -0
  151. package/lib/cjs/tests/unit_tests/do_not_send_address.test.js +89 -0
  152. package/lib/cjs/tests/unit_tests/do_not_send_address.test.js.map +1 -0
  153. package/lib/cjs/tests/unit_tests/openapi_spec_freshness.test.d.ts +17 -0
  154. package/lib/cjs/tests/unit_tests/openapi_spec_freshness.test.d.ts.map +1 -0
  155. package/lib/cjs/tests/unit_tests/openapi_spec_freshness.test.js +140 -0
  156. package/lib/cjs/tests/unit_tests/openapi_spec_freshness.test.js.map +1 -0
  157. package/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  158. package/lib/esm/tests/api_tests/auto_merge_form_submission.test.js +1 -1
  159. package/lib/esm/tests/api_tests/auto_merge_form_submission.test.js.map +1 -1
  160. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.d.ts +5 -0
  161. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.d.ts.map +1 -0
  162. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.js +383 -0
  163. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.js.map +1 -0
  164. package/lib/esm/tests/api_tests/integrations_redacted.test.js +3 -3
  165. package/lib/esm/tests/api_tests/integrations_redacted.test.js.map +1 -1
  166. package/lib/esm/tests/api_tests/organization_signup.test.d.ts +20 -0
  167. package/lib/esm/tests/api_tests/organization_signup.test.d.ts.map +1 -0
  168. package/lib/esm/tests/api_tests/organization_signup.test.js +264 -0
  169. package/lib/esm/tests/api_tests/organization_signup.test.js.map +1 -0
  170. package/lib/esm/tests/api_tests/purchase_made_trigger.test.d.ts.map +1 -1
  171. package/lib/esm/tests/api_tests/purchase_made_trigger.test.js +104 -163
  172. package/lib/esm/tests/api_tests/purchase_made_trigger.test.js.map +1 -1
  173. package/lib/esm/tests/api_tests/security/F-0179-booking-info-idor-token-mint.test.d.ts +30 -0
  174. package/lib/esm/tests/api_tests/security/F-0179-booking-info-idor-token-mint.test.d.ts.map +1 -0
  175. package/lib/esm/tests/api_tests/security/F-0179-booking-info-idor-token-mint.test.js +332 -0
  176. package/lib/esm/tests/api_tests/security/F-0179-booking-info-idor-token-mint.test.js.map +1 -0
  177. package/lib/esm/tests/api_tests/security/F-0185-startlinktoken-enduser-staff-escalation.test.d.ts +6 -0
  178. package/lib/esm/tests/api_tests/security/F-0185-startlinktoken-enduser-staff-escalation.test.d.ts.map +1 -0
  179. package/lib/esm/tests/api_tests/security/F-0185-startlinktoken-enduser-staff-escalation.test.js +350 -0
  180. package/lib/esm/tests/api_tests/security/F-0185-startlinktoken-enduser-staff-escalation.test.js.map +1 -0
  181. package/lib/esm/tests/api_tests/security/F-0191-schema-adminonly-enforcement.test.d.ts +46 -0
  182. package/lib/esm/tests/api_tests/security/F-0191-schema-adminonly-enforcement.test.d.ts.map +1 -0
  183. package/lib/esm/tests/api_tests/security/F-0191-schema-adminonly-enforcement.test.js +382 -0
  184. package/lib/esm/tests/api_tests/security/F-0191-schema-adminonly-enforcement.test.js.map +1 -0
  185. package/lib/esm/tests/api_tests/security/F-0192-automated-actions-process-gate.test.d.ts +43 -0
  186. package/lib/esm/tests/api_tests/security/F-0192-automated-actions-process-gate.test.d.ts.map +1 -0
  187. package/lib/esm/tests/api_tests/security/F-0192-automated-actions-process-gate.test.js +317 -0
  188. package/lib/esm/tests/api_tests/security/F-0192-automated-actions-process-gate.test.js.map +1 -0
  189. package/lib/esm/tests/api_tests/security/F-0196-add-to-journey-foreign-enduserid.test.d.ts +43 -0
  190. package/lib/esm/tests/api_tests/security/F-0196-add-to-journey-foreign-enduserid.test.d.ts.map +1 -0
  191. package/lib/esm/tests/api_tests/security/F-0196-add-to-journey-foreign-enduserid.test.js +277 -0
  192. package/lib/esm/tests/api_tests/security/F-0196-add-to-journey-foreign-enduserid.test.js.map +1 -0
  193. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts +33 -0
  194. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts.map +1 -0
  195. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.js +244 -0
  196. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.js.map +1 -0
  197. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts +42 -0
  198. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -0
  199. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +276 -0
  200. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -0
  201. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.d.ts +38 -0
  202. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.d.ts.map +1 -0
  203. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.js +386 -0
  204. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.js.map +1 -0
  205. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.d.ts +6 -0
  206. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.d.ts.map +1 -0
  207. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.js +996 -0
  208. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.js.map +1 -0
  209. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.d.ts +42 -0
  210. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.d.ts.map +1 -0
  211. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.js +316 -0
  212. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.js.map +1 -0
  213. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts +29 -0
  214. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts.map +1 -0
  215. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.js +331 -0
  216. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.js.map +1 -0
  217. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts +32 -0
  218. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts.map +1 -0
  219. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js +233 -0
  220. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js.map +1 -0
  221. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts +28 -0
  222. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts.map +1 -0
  223. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.js +345 -0
  224. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.js.map +1 -0
  225. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts +30 -0
  226. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts.map +1 -0
  227. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js +310 -0
  228. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js.map +1 -0
  229. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.d.ts +21 -0
  230. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.d.ts.map +1 -0
  231. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.js +358 -0
  232. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.js.map +1 -0
  233. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.d.ts +21 -0
  234. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.d.ts.map +1 -0
  235. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.js +362 -0
  236. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.js.map +1 -0
  237. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.d.ts +32 -0
  238. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.d.ts.map +1 -0
  239. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.js +243 -0
  240. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.js.map +1 -0
  241. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts +19 -0
  242. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts.map +1 -0
  243. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.js +134 -0
  244. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.js.map +1 -0
  245. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts +24 -0
  246. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
  247. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js +194 -0
  248. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js.map +1 -0
  249. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.d.ts +29 -0
  250. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.d.ts.map +1 -0
  251. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.js +271 -0
  252. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.js.map +1 -0
  253. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.d.ts +17 -0
  254. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.d.ts.map +1 -0
  255. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.js +151 -0
  256. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.js.map +1 -0
  257. package/lib/esm/tests/api_tests/security/prototype-pollution.test.d.ts +2 -0
  258. package/lib/esm/tests/api_tests/security/prototype-pollution.test.d.ts.map +1 -0
  259. package/lib/esm/tests/api_tests/security/prototype-pollution.test.js +84 -0
  260. package/lib/esm/tests/api_tests/security/prototype-pollution.test.js.map +1 -0
  261. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts +34 -0
  262. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts.map +1 -0
  263. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.js +223 -0
  264. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.js.map +1 -0
  265. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts +2 -0
  266. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts.map +1 -0
  267. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.js +238 -0
  268. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.js.map +1 -0
  269. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.d.ts +2 -0
  270. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.d.ts.map +1 -0
  271. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.js +144 -0
  272. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.js.map +1 -0
  273. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts +45 -0
  274. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts.map +1 -0
  275. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.js +381 -0
  276. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.js.map +1 -0
  277. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.d.ts +38 -0
  278. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.d.ts.map +1 -0
  279. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.js +218 -0
  280. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.js.map +1 -0
  281. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts +6 -0
  282. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts.map +1 -0
  283. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js +350 -0
  284. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js.map +1 -0
  285. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts +28 -0
  286. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts.map +1 -0
  287. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.js +435 -0
  288. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.js.map +1 -0
  289. package/lib/esm/tests/api_tests/security/webhook-timeout.test.d.ts +19 -0
  290. package/lib/esm/tests/api_tests/security/webhook-timeout.test.d.ts.map +1 -0
  291. package/lib/esm/tests/api_tests/security/webhook-timeout.test.js +149 -0
  292. package/lib/esm/tests/api_tests/security/webhook-timeout.test.js.map +1 -0
  293. package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts +5 -0
  294. package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts.map +1 -0
  295. package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.js +324 -0
  296. package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.js.map +1 -0
  297. package/lib/esm/tests/api_tests/webhook_error_handling.test.js +2 -2
  298. package/lib/esm/tests/api_tests/webhook_error_handling.test.js.map +1 -1
  299. package/lib/esm/tests/setup_isolated.d.ts +68 -0
  300. package/lib/esm/tests/setup_isolated.d.ts.map +1 -0
  301. package/lib/esm/tests/setup_isolated.js +221 -0
  302. package/lib/esm/tests/setup_isolated.js.map +1 -0
  303. package/lib/esm/tests/tests.d.ts.map +1 -1
  304. package/lib/esm/tests/tests.js +287 -227
  305. package/lib/esm/tests/tests.js.map +1 -1
  306. package/lib/esm/tests/unit_tests/do_not_send_address.test.d.ts +2 -0
  307. package/lib/esm/tests/unit_tests/do_not_send_address.test.d.ts.map +1 -0
  308. package/lib/esm/tests/unit_tests/do_not_send_address.test.js +85 -0
  309. package/lib/esm/tests/unit_tests/do_not_send_address.test.js.map +1 -0
  310. package/lib/esm/tests/unit_tests/openapi_spec_freshness.test.d.ts +17 -0
  311. package/lib/esm/tests/unit_tests/openapi_spec_freshness.test.d.ts.map +1 -0
  312. package/lib/esm/tests/unit_tests/openapi_spec_freshness.test.js +113 -0
  313. package/lib/esm/tests/unit_tests/openapi_spec_freshness.test.js.map +1 -0
  314. package/lib/tsconfig.tsbuildinfo +1 -1
  315. package/package.json +10 -10
  316. package/src/tests/api_tests/auto_merge_form_submission.test.ts +1 -1
  317. package/src/tests/api_tests/enduser_observations_auto_review.test.ts +358 -0
  318. package/src/tests/api_tests/integrations_redacted.test.ts +1 -1
  319. package/src/tests/api_tests/organization_signup.test.ts +240 -0
  320. package/src/tests/api_tests/purchase_made_trigger.test.ts +29 -41
  321. package/src/tests/api_tests/security/add-to-journey-foreign-enduserid.test.ts +207 -0
  322. package/src/tests/api_tests/security/{F-0005-ai-conversations-rbac.test.ts → ai-conversations-rbac.test.ts} +14 -14
  323. package/src/tests/api_tests/security/{F-0166-allowed-paths-wildcard-bypass.test.ts → allowed-paths-confinement.test.ts} +11 -11
  324. package/src/tests/api_tests/security/automated-actions-process-gate.test.ts +237 -0
  325. package/src/tests/api_tests/security/booking-info-idor-token-mint.test.ts +224 -0
  326. package/src/tests/api_tests/security/{F-0053-cascade-role-rename-cross-tenant.test.ts → cascade-role-rename-cross-tenant.test.ts} +10 -10
  327. package/src/tests/api_tests/security/{F-0001-data-sync-redaction-bypass.test.ts → data-sync-redaction-bypass.test.ts} +9 -9
  328. package/src/tests/api_tests/security/{F-0006-develop-health-benefit-verification-rbac.test.ts → develop-health-benefit-verification-rbac.test.ts} +7 -8
  329. package/src/tests/api_tests/security/{F-0116-F-0119-enduser-cross-create.test.ts → enduser-cross-create.test.ts} +25 -25
  330. package/src/tests/api_tests/security/{F-0106-F-0110-enduser-write-restrictions.test.ts → enduser-write-restrictions.test.ts} +12 -14
  331. package/src/tests/api_tests/security/form-logic-js-execution.test.ts +183 -0
  332. package/src/tests/api_tests/security/{F-0145-globalunique-leak.test.ts → globalunique-conflict-redaction.test.ts} +5 -6
  333. package/src/tests/api_tests/security/{F-0008-handle-incoming-communication-cross-tenant.test.ts → handle-incoming-communication-cross-tenant.test.ts} +8 -8
  334. package/src/tests/api_tests/security/{F-0007-invite-user-enumeration.test.ts → invite-user-enumeration.test.ts} +8 -8
  335. package/src/tests/api_tests/security/{F-0151-load-inbox-redaction.test.ts → load-inbox-redaction.test.ts} +5 -6
  336. package/src/tests/api_tests/security/{F-0016-prototype-pollution.test.ts → prototype-pollution.test.ts} +4 -4
  337. package/src/tests/api_tests/security/{F-0025-proxy-image-unauth-ssrf.test.ts → proxy-image-unauth-ssrf.test.ts} +11 -12
  338. package/src/tests/api_tests/security/{F-0013-sanitize-user-html-with-iframes.test.ts → sanitize-user-html-with-iframes.test.ts} +5 -5
  339. package/src/tests/api_tests/security/{F-0013-sanitize-user-html.test.ts → sanitize-user-html.test.ts} +4 -4
  340. package/src/tests/api_tests/security/schema-adminonly-enforcement.test.ts +287 -0
  341. package/src/tests/api_tests/security/{F-0076-self-admin-role-assignment.test.ts → self-admin-role-assignment.test.ts} +13 -13
  342. package/src/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.ts +162 -0
  343. package/src/tests/api_tests/security/{F-0015-webhook-outbound-ssrf.test.ts → webhook-outbound-ssrf.test.ts} +13 -14
  344. package/src/tests/api_tests/security/{F-0155-webhook-timeout.test.ts → webhook-timeout.test.ts} +6 -7
  345. package/src/tests/api_tests/tickets_bulk_assign_from_queue.test.ts +279 -0
  346. package/src/tests/api_tests/webhook_error_handling.test.ts +1 -1
  347. package/src/tests/setup_isolated.ts +170 -0
  348. package/src/tests/tests.ts +60 -18
  349. package/src/tests/unit_tests/do_not_send_address.test.ts +60 -0
  350. package/src/tests/unit_tests/openapi_spec_freshness.test.ts +88 -0
  351. package/test_generated.pdf +0 -0
  352. package/src/tests/api_tests/security/readonly-enduser-preview.test.ts +0 -301
@@ -14,8 +14,7 @@ const host = process.env.API_URL || 'http://localhost:8080' as const
14
14
  const [nonAdminEmail, nonAdminPassword] = [process.env.NON_ADMIN_EMAIL, process.env.NON_ADMIN_PASSWORD]
15
15
 
16
16
  /**
17
- * Regression test for F-0006 (security-audit/findings/F-0006-zoom-and-benefit-verification-bypass-rbac.md),
18
- * reopened 2026-08-17 for the `develop_health_run_benefit_verification` sub-item.
17
+ * Regression test: the `develop_health_run_benefit_verification` RBAC gate.
19
18
  *
20
19
  * `enduser_eligibility_results.develop_health_run_benefit_verification` is registered with
21
20
  * `noAccessPermissions: true` (packages/private/api/api/v1/api.ts, ~line 24606). Before the fix,
@@ -39,7 +38,7 @@ const [nonAdminEmail, nonAdminPassword] = [process.env.NON_ADMIN_EMAIL, process.
39
38
  * Post-fix: the handler throws 403 before touching `DB.endusers` at all. Test passes.
40
39
  */
41
40
  export const develop_health_benefit_verification_rbac_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
42
- log_header("F-0006: develop_health benefit verification RBAC regression")
41
+ log_header("develop_health benefit verification RBAC regression")
43
42
 
44
43
  const roleName = `f0006-develop-health-no-access-${Date.now()}`
45
44
  let rbapId: string | undefined
@@ -74,7 +73,7 @@ export const develop_health_benefit_verification_rbac_tests = async ({ sdk, sdkN
74
73
  // Pre-fix: proceeds to DB.endusers.findById and either 400s on validation (fake id) or
75
74
  // succeeds and forwards PHI to Develop Health (real id) — never a 403.
76
75
  await async_test(
77
- "F-0006: enduser_eligibility_results.develop_health_run_benefit_verification must throw 403 when role denies endusers/enduser_eligibility_results",
76
+ "enduser_eligibility_results.develop_health_run_benefit_verification must throw 403 when role denies endusers/enduser_eligibility_results",
78
77
  () => sdkNonAdmin.api.enduser_eligibility_results.develop_health_run_benefit_verification({
79
78
  enduserId: new ObjectId().toHexString(), // fake id — access check should fire first
80
79
  providerUserId: new ObjectId().toHexString(), // fake id — access check should fire first
@@ -122,7 +121,7 @@ export const develop_health_benefit_verification_rbac_tests = async ({ sdk, sdkN
122
121
  await sdkNonAdmin.authenticate(nonAdminEmail!, nonAdminPassword!)
123
122
 
124
123
  await async_test(
125
- "F-0006: a provider role with enduser access passes the gate (reaches 'Integration not found', not 403)",
124
+ "a provider role with enduser access passes the gate (reaches 'Integration not found', not 403)",
126
125
  () => sdkNonAdmin.api.enduser_eligibility_results.develop_health_run_benefit_verification({
127
126
  enduserId: new ObjectId().toHexString(),
128
127
  providerUserId: new ObjectId().toHexString(),
@@ -159,7 +158,7 @@ export const develop_health_benefit_verification_rbac_tests = async ({ sdk, sdkN
159
158
  // the handler throws "Integration not found" BEFORE reaching the (now read-scoped) enduser load,
160
159
  // and the enduser load is what the create>read fix governs. Exercising it would need either a real
161
160
  // Develop Health integration or reordering the handler purely for the test. It is covered by code
162
- // review + F-0166 (systemic follow-up). If a Develop Health sandbox integration is ever available
161
+ // review + the systemic follow-up. If a Develop Health sandbox integration is ever available
163
162
  // in the test org, add: role { endusers: create 'All', read 'Assigned' } → call with a real
164
163
  // enduser NOT assigned to the caller → expect the enduser-not-found path, not a successful forward.
165
164
  } finally {
@@ -194,11 +193,11 @@ if (require.main === module) {
194
193
 
195
194
  runTests()
196
195
  .then(() => {
197
- console.log("✅ F-0006 develop_health_run_benefit_verification RBAC test suite completed successfully")
196
+ console.log("✅ develop_health_run_benefit_verification RBAC test suite completed successfully")
198
197
  process.exit(0)
199
198
  })
200
199
  .catch((error) => {
201
- console.error("❌ F-0006 develop_health_run_benefit_verification RBAC test suite failed:", error)
200
+ console.error("❌ develop_health_run_benefit_verification RBAC test suite failed:", error)
202
201
  process.exit(1)
203
202
  })
204
203
  }
@@ -16,10 +16,10 @@ const CROSS_ENDUSER_MESSAGE = "enduserId does not match creator id for enduser s
16
16
 
17
17
  /**
18
18
  * Regression test for the enduser cross-enduser CREATE gating gaps:
19
- * F-0116 enduser_observations (security-audit/findings/F-0116-*.md)
20
- * F-0117 enduser_orders (security-audit/findings/F-0117-*.md)
21
- * F-0119 managed_content_records (security-audit/findings/F-0119-*.md)
22
- * F-0118 chat_rooms (enduserIds-only gate; staff userIds targeting is by-design)
19
+ * enduser_observations
20
+ * enduser_orders
21
+ * managed_content_records
22
+ * chat_rooms (enduserIds-only gate; staff userIds targeting is by-design)
23
23
  *
24
24
  * Each model exposed enduserActions.create with an `enduserId`/`enduserIds` field that
25
25
  * lacked a write-side gate, letting an authenticated enduser create records bound to a
@@ -30,7 +30,7 @@ const CROSS_ENDUSER_MESSAGE = "enduserId does not match creator id for enduser s
30
30
  * legitimate path (self-create + staff-create) still works.
31
31
  */
32
32
  export const enduser_cross_create_tests = async ({ sdk } : { sdk: Session, sdkNonAdmin: Session }) => {
33
- log_header("F-0116/F-0117/F-0118/F-0119: enduser cross-enduser create gates")
33
+ log_header("enduser cross-enduser create gates")
34
34
 
35
35
  let attackerId: string | undefined
36
36
  let victimId: string | undefined
@@ -53,10 +53,10 @@ export const enduser_cross_create_tests = async ({ sdk } : { sdk: Session, sdkNo
53
53
  await attackerSDK.authenticate(attackerEmail, ENDUSER_PASSWORD)
54
54
 
55
55
  // ============================================================
56
- // F-0116 — enduser_observations
56
+ // enduser_observations
57
57
  // ============================================================
58
58
  await async_test(
59
- `F-0116: enduser cannot create observation on another enduser (createOne)`,
59
+ `enduser cannot create observation on another enduser (createOne)`,
60
60
  () => attackerSDK.api.enduser_observations.createOne({
61
61
  enduserId: victimId!, category: 'vital-signs', status: 'final',
62
62
  measurement: { unit: 'mmHg', value: 220 },
@@ -64,7 +64,7 @@ export const enduser_cross_create_tests = async ({ sdk } : { sdk: Session, sdkNo
64
64
  { shouldError: true, onError: e => e.message === CROSS_ENDUSER_MESSAGE },
65
65
  )
66
66
  await async_test(
67
- `F-0116: enduser cannot create observation on another enduser (createMany)`,
67
+ `enduser cannot create observation on another enduser (createMany)`,
68
68
  () => attackerSDK.api.enduser_observations.createSome([{
69
69
  enduserId: victimId!, category: 'vital-signs', status: 'final',
70
70
  measurement: { unit: 'mmHg', value: 220 },
@@ -74,7 +74,7 @@ export const enduser_cross_create_tests = async ({ sdk } : { sdk: Session, sdkNo
74
74
 
75
75
  // Positive control: enduser CAN create an observation on their OWN record
76
76
  await async_test(
77
- `F-0116: enduser can still create observation on own record`,
77
+ `enduser can still create observation on own record`,
78
78
  () => attackerSDK.api.enduser_observations.createOne({
79
79
  enduserId: attackerId!, category: 'vital-signs', status: 'final',
80
80
  measurement: { unit: 'mmHg', value: 120 },
@@ -83,7 +83,7 @@ export const enduser_cross_create_tests = async ({ sdk } : { sdk: Session, sdkNo
83
83
  )
84
84
  // Positive control: staff CAN create an observation on any tenant enduser
85
85
  await async_test(
86
- `F-0116: staff can still create observation on any enduser`,
86
+ `staff can still create observation on any enduser`,
87
87
  () => sdk.api.enduser_observations.createOne({
88
88
  enduserId: victimId!, category: 'vital-signs', status: 'final',
89
89
  measurement: { unit: 'mmHg', value: 118 },
@@ -92,61 +92,61 @@ export const enduser_cross_create_tests = async ({ sdk } : { sdk: Session, sdkNo
92
92
  )
93
93
 
94
94
  // ============================================================
95
- // F-0117 — enduser_orders
95
+ // enduser_orders
96
96
  // ============================================================
97
97
  const orderPayload = (enduserId: string) => ({
98
98
  enduserId, externalId: `f0117-${Date.now()}`, source: 'f0117-source',
99
99
  title: 'f0117 order', status: 'pending',
100
100
  })
101
101
  await async_test(
102
- `F-0117: enduser cannot create order on another enduser`,
102
+ `enduser cannot create order on another enduser`,
103
103
  () => attackerSDK.api.enduser_orders.createOne(orderPayload(victimId!) as any),
104
104
  { shouldError: true, onError: e => e.message === CROSS_ENDUSER_MESSAGE },
105
105
  )
106
106
  await async_test(
107
- `F-0117: enduser can still create order on own record`,
107
+ `enduser can still create order on own record`,
108
108
  () => attackerSDK.api.enduser_orders.createOne(orderPayload(attackerId!) as any),
109
109
  { onResult: (o: any) => { if (o?.id) createdOrderIds.push(o.id); return o?.enduserId === attackerId } },
110
110
  )
111
111
  await async_test(
112
- `F-0117: staff can still create order on any enduser`,
112
+ `staff can still create order on any enduser`,
113
113
  () => sdk.api.enduser_orders.createOne(orderPayload(victimId!) as any),
114
114
  { onResult: (o: any) => { if (o?.id) createdOrderIds.push(o.id); return o?.enduserId === victimId } },
115
115
  )
116
116
 
117
117
  // ============================================================
118
- // F-0119 — managed_content_records
118
+ // managed_content_records
119
119
  // ============================================================
120
120
  await async_test(
121
- `F-0119: enduser cannot create content with allowUnauthenticatedAccess`,
121
+ `enduser cannot create content with allowUnauthenticatedAccess`,
122
122
  () => attackerSDK.api.managed_content_records.createOne({
123
123
  title: 'f0119 phishing', textContent: 'x', allowUnauthenticatedAccess: true,
124
124
  } as any),
125
125
  { shouldError: true, onError: e => e.message === "allowUnauthenticatedAccess cannot be set by endusers" },
126
126
  )
127
127
  await async_test(
128
- `F-0119: enduser cannot create content with publicRead`,
128
+ `enduser cannot create content with publicRead`,
129
129
  () => attackerSDK.api.managed_content_records.createOne({
130
130
  title: 'f0119 broadcast', textContent: 'x', publicRead: true,
131
131
  } as any),
132
132
  { shouldError: true, onError: e => e.message === "publicRead cannot be set by endusers" },
133
133
  )
134
134
  await async_test(
135
- `F-0119: enduser cannot create content bound to another enduser`,
135
+ `enduser cannot create content bound to another enduser`,
136
136
  () => attackerSDK.api.managed_content_records.createOne({
137
137
  title: 'f0119 cross', textContent: 'x', enduserId: victimId!,
138
138
  } as any),
139
139
  { shouldError: true, onError: e => e.message === CROSS_ENDUSER_MESSAGE },
140
140
  )
141
141
  await async_test(
142
- `F-0119: enduser can still create ordinary content`,
142
+ `enduser can still create ordinary content`,
143
143
  () => attackerSDK.api.managed_content_records.createOne({
144
144
  title: 'f0119 ok', textContent: 'hello',
145
145
  } as any),
146
146
  { onResult: (o: any) => { if (o?.id) createdContentIds.push(o.id); return !o?.publicRead && !o?.allowUnauthenticatedAccess } },
147
147
  )
148
148
  await async_test(
149
- `F-0119: staff can still create public content`,
149
+ `staff can still create public content`,
150
150
  () => sdk.api.managed_content_records.createOne({
151
151
  title: 'f0119 staff public', textContent: 'x', publicRead: true,
152
152
  } as any),
@@ -154,11 +154,11 @@ export const enduser_cross_create_tests = async ({ sdk } : { sdk: Session, sdkNo
154
154
  )
155
155
 
156
156
  // ============================================================
157
- // F-0118 — chat_rooms (enduserIds-only gate; staff userIds targeting is by-design)
157
+ // chat_rooms (enduserIds-only gate; staff userIds targeting is by-design)
158
158
  // ============================================================
159
159
  const staffId = sdk.userInfo.id
160
160
  await async_test(
161
- `F-0118: enduser cannot add another patient to a chat room (enduserIds)`,
161
+ `enduser cannot add another patient to a chat room (enduserIds)`,
162
162
  () => attackerSDK.api.chat_rooms.createOne({
163
163
  type: 'internal', enduserIds: [attackerId!, victimId!], userIds: [staffId],
164
164
  } as any),
@@ -166,7 +166,7 @@ export const enduser_cross_create_tests = async ({ sdk } : { sdk: Session, sdkNo
166
166
  )
167
167
  // Positive control: patient CAN create a room with care-team staff + self (intended feature)
168
168
  await async_test(
169
- `F-0118: enduser can still create a room with staff + self`,
169
+ `enduser can still create a room with staff + self`,
170
170
  () => attackerSDK.api.chat_rooms.createOne({
171
171
  type: 'internal', enduserIds: [attackerId!], userIds: [staffId],
172
172
  } as any),
@@ -174,7 +174,7 @@ export const enduser_cross_create_tests = async ({ sdk } : { sdk: Session, sdkNo
174
174
  )
175
175
  // Positive control: staff can still create multi-patient rooms
176
176
  await async_test(
177
- `F-0118: staff can still create a room with multiple endusers`,
177
+ `staff can still create a room with multiple endusers`,
178
178
  () => sdk.api.chat_rooms.createOne({
179
179
  type: 'internal', enduserIds: [attackerId!, victimId!], userIds: [staffId],
180
180
  } as any),
@@ -211,7 +211,7 @@ if (require.main === module) {
211
211
 
212
212
  runTests()
213
213
  .then(() => {
214
- console.log("✅ F-0116/F-0117/F-0118/F-0119 enduser cross-create test suite completed successfully")
214
+ console.log("✅ enduser cross-create test suite completed successfully")
215
215
  process.exit(0)
216
216
  })
217
217
  .catch((error) => {
@@ -71,9 +71,7 @@ const restrictedFormResponseUpdates = (staffId: string, otherEnduserId: string):
71
71
  })
72
72
 
73
73
  /**
74
- * Regression test for F-0106 and F-0110
75
- * (security-audit/findings/F-0106-enduser-self-update-admin-only-fields.md,
76
- * security-audit/findings/F-0110-form-responses-enduser-update-admin-only-fields.md).
74
+ * Regression test: enduser self-updates must not write staff-only fields on `endusers` or `form_responses`.
77
75
  *
78
76
  * Endusers could PATCH admin-only / access-bearing / attribution-bearing fields on
79
77
  * their own endusers record (assignedTo, tags, references, ...) and their own
@@ -88,7 +86,7 @@ const restrictedFormResponseUpdates = (staffId: string, otherEnduserId: string):
88
86
  * - staff sessions can still update the restricted fields
89
87
  */
90
88
  export const enduser_write_restrictions_tests = async ({ sdk } : { sdk: Session, sdkNonAdmin: Session }) => {
91
- log_header("F-0106/F-0110: enduser write restrictions (enduserUpdatesDisabled)")
89
+ log_header("enduser write restrictions (enduserUpdatesDisabled)")
92
90
 
93
91
  let enduserId: string | undefined
94
92
  let otherEnduserId: string | undefined
@@ -111,7 +109,7 @@ export const enduser_write_restrictions_tests = async ({ sdk } : { sdk: Session,
111
109
  const enduserSDK = new EnduserSession({ host, businessId })
112
110
  await enduserSDK.authenticate(enduserEmail, ENDUSER_PASSWORD)
113
111
 
114
- const form = await sdk.api.forms.createOne({ title: 'F-0106/F-0110 Write Restriction Test Form' })
112
+ const form = await sdk.api.forms.createOne({ title: 'Write Restriction Test Form' })
115
113
  formId = form.id
116
114
  const { response: formResponse } = await sdk.api.form_responses.prepare_form_response({
117
115
  formId: form.id,
@@ -119,34 +117,34 @@ export const enduser_write_restrictions_tests = async ({ sdk } : { sdk: Session,
119
117
  })
120
118
  formResponseId = formResponse.id
121
119
 
122
- // ---- F-0106: enduser self-update of restricted endusers fields must 400 ----
120
+ // ---- enduser self-update of restricted endusers fields must 400 ----
123
121
  for (const [field, value] of Object.entries(restrictedEnduserUpdates(sdk.userInfo.id, enduser.id))) {
124
122
  await async_test(
125
- `F-0106: enduser cannot self-update endusers.${field}`,
123
+ `enduser cannot self-update endusers.${field}`,
126
124
  () => enduserSDK.api.endusers.updateOne(enduser.id, { [field]: value } as any),
127
125
  { shouldError: true, onError: e => e.message === `${field} cannot be updated by endusers` },
128
126
  )
129
127
  }
130
128
 
131
- // F-0106 Variant A persistence check: the rejected assignedTo write must not
129
+ // Variant A persistence check: the rejected assignedTo write must not
132
130
  // have granted the staff read-filter match.
133
131
  await async_test(
134
- 'F-0106: rejected assignedTo write did not persist',
132
+ 'rejected assignedTo write did not persist',
135
133
  () => sdk.api.endusers.getOne(enduser.id),
136
134
  { onResult: e => !e.assignedTo?.length && !e.tags?.length && e.externalId === undefined },
137
135
  )
138
136
 
139
- // ---- F-0110: enduser self-update of restricted form_responses fields must 400 ----
137
+ // ---- enduser self-update of restricted form_responses fields must 400 ----
140
138
  for (const [field, value] of Object.entries(restrictedFormResponseUpdates(sdk.userInfo.id, otherEnduser.id))) {
141
139
  await async_test(
142
- `F-0110: enduser cannot self-update form_responses.${field}`,
140
+ `enduser cannot self-update form_responses.${field}`,
143
141
  () => enduserSDK.api.form_responses.updateOne(formResponse.id, { [field]: value } as any),
144
142
  { shouldError: true, onError: e => e.message === `${field} cannot be updated by endusers` },
145
143
  )
146
144
  }
147
145
 
148
146
  await async_test(
149
- 'F-0110: rejected writes did not persist (markedAsSubmitted, procedureCodes, submittedBy, enduserId)',
147
+ 'rejected writes did not persist (markedAsSubmitted, procedureCodes, submittedBy, enduserId)',
150
148
  () => sdk.api.form_responses.getOne(formResponse.id),
151
149
  { onResult: fr => (
152
150
  !fr.markedAsSubmitted && !fr.procedureCodes?.length && fr.submittedBy === undefined
@@ -238,11 +236,11 @@ if (require.main === module) {
238
236
 
239
237
  runTests()
240
238
  .then(() => {
241
- console.log("✅ F-0106/F-0110 enduser write-restriction test suite completed successfully")
239
+ console.log("✅ enduser write-restriction test suite completed successfully")
242
240
  process.exit(0)
243
241
  })
244
242
  .catch((error) => {
245
- console.error("❌ F-0106/F-0110 enduser write-restriction test suite failed:", error)
243
+ console.error("❌ enduser write-restriction test suite failed:", error)
246
244
  process.exit(1)
247
245
  })
248
246
  }
@@ -0,0 +1,183 @@
1
+ require('source-map-support').install();
2
+
3
+ import {
4
+ assert_checks,
5
+ Check,
6
+ setup_isolated_tenant,
7
+ } from "../../setup_isolated"
8
+
9
+ const host = process.env.API_URL || 'http://localhost:8080' as const
10
+
11
+ const RAND = () => Math.random().toString(36).slice(2, 10)
12
+
13
+ /**
14
+ * Regression test: `$JS(...)` must be rejected in stored conditional logic.
15
+ *
16
+ * `responses_satisfy_conditions` (utilities/src/utils.ts) compiled a stored condition value of the
17
+ * form `$JS(...)` with `new Function()` and executed it — in every form-filler's browser, including
18
+ * anonymous visitors on public intake pages, AND inside the API process (automation_triggers.ts
19
+ * trigger matching on every form submission, ai_agent/form_filling.ts voice-agent navigation). The
20
+ * API process holds every tenant's database handle, so a condition authored by staff in one tenant
21
+ * reached all of them. Any staff user or API key with form_fields write access could plant one by
22
+ * typing into the free-text $gt/$lt box — no API call required.
23
+ *
24
+ * The sink is removed. This asserts the second half of the fix: `compoundFilterValidator` rejects the
25
+ * syntax at write time on every field that feeds that evaluator, so it cannot be reintroduced through
26
+ * stored configuration. The runtime half — that a `$JS` value is never evaluated — is covered by the
27
+ * pure-function cases in `form_conditional_logic_tests` in tests.ts.
28
+ *
29
+ * The five condition locations were established by enumerating every `responses_satisfy_conditions`
30
+ * call site, and all five are covered here. That completeness matters: the first run of this test
31
+ * caught a half fix. `event.conditions` is wrapped in an `orValidator`, which returns the first arm
32
+ * that does not throw, and its permissive `optional: optionalAnyObjectValidator` arm was declared
33
+ * before the guarded one — so the payload was accepted and stored even though the validator had been
34
+ * swapped. Pointing a field at the guard is not the same as the guard being reachable, which is why
35
+ * every location gets an assertion rather than an argument.
36
+ *
37
+ * Each rejection is paired with a positive control using the same shape without `$JS(`, so a passing
38
+ * test cannot be explained by the write failing for an unrelated reason.
39
+ */
40
+ export const form_logic_js_execution_checks = async (): Promise<Check[]> => {
41
+ const checks: Check[] = []
42
+ const record = (label: string, pass: boolean, detail: string) => checks.push({ label, pass, detail })
43
+
44
+ const JS_PAYLOAD = '$JS(return 0)'
45
+ const SAFE_VALUE = '18'
46
+
47
+ const condition = (value: string) => ({ $and: [{ condition: { 'someFieldId': { $gt: value } } }] })
48
+ const previousFields = (value: string) => ([{
49
+ type: 'compoundLogic',
50
+ info: { fieldId: '000000000000000000000000', priority: 5, label: '', condition: condition(value) },
51
+ }])
52
+
53
+ const attempt = async (fn: () => Promise<any>) => (
54
+ fn().then(() => ({ accepted: true, detail: 'accepted' }))
55
+ .catch((e: any) => ({ accepted: false, detail: `rejected: ${e?.message || e}` }))
56
+ )
57
+
58
+ let tenant: Awaited<ReturnType<typeof setup_isolated_tenant>> | undefined
59
+
60
+ try {
61
+ tenant = await setup_isolated_tenant({ name: `F0200 ${RAND()}`, users: [{ isAdmin: true }], apiKeys: 0 })
62
+ const sdk = tenant.sdk
63
+
64
+ const form = await sdk.api.forms.createOne({ title: `${RAND()}` })
65
+ const field = await sdk.api.form_fields.createOne({
66
+ formId: form.id, title: 'anchor', type: 'string', previousFields: [{ type: 'root', info: {} }],
67
+ })
68
+
69
+ /* ===== 1. previousFields[].info.condition — the field the finding was reported against ===== */
70
+
71
+ const controlCreate = await attempt(() => sdk.api.form_fields.createOne({
72
+ formId: form.id, title: 'control', type: 'string',
73
+ previousFields: previousFields(SAFE_VALUE) as any,
74
+ }))
75
+ record(
76
+ 'control: form_fields.createOne accepts a normal $gt condition',
77
+ controlCreate.accepted, controlCreate.detail,
78
+ )
79
+
80
+ const payloadCreate = await attempt(() => sdk.api.form_fields.createOne({
81
+ formId: form.id, title: 'payload', type: 'string',
82
+ previousFields: previousFields(JS_PAYLOAD) as any,
83
+ }))
84
+ record(
85
+ '1a: form_fields.createOne rejects $JS( in previousFields condition',
86
+ !payloadCreate.accepted, payloadCreate.detail,
87
+ )
88
+
89
+ const payloadUpdate = await attempt(() => sdk.api.form_fields.updateOne(field.id, {
90
+ previousFields: previousFields(JS_PAYLOAD) as any,
91
+ }))
92
+ record(
93
+ '1b: form_fields.updateOne rejects $JS( in previousFields condition',
94
+ !payloadUpdate.accepted, payloadUpdate.detail,
95
+ )
96
+
97
+ /* ===== 2. groupShowCondition ===== */
98
+
99
+ const groupControl = await attempt(() => sdk.api.form_fields.updateOne(field.id, {
100
+ groupShowCondition: condition(SAFE_VALUE) as any,
101
+ }))
102
+ record('control: groupShowCondition accepts a normal condition', groupControl.accepted, groupControl.detail)
103
+
104
+ const groupPayload = await attempt(() => sdk.api.form_fields.updateOne(field.id, {
105
+ groupShowCondition: condition(JS_PAYLOAD) as any,
106
+ }))
107
+ record('2: form_fields.updateOne rejects $JS( in groupShowCondition', !groupPayload.accepted, groupPayload.detail)
108
+
109
+ /* ===== 3. options.optionDetails[].showCondition ===== */
110
+
111
+ const optionControl = await attempt(() => sdk.api.form_fields.updateOne(field.id, {
112
+ options: { optionDetails: [{ option: 'A', showCondition: condition(SAFE_VALUE) }] } as any,
113
+ }))
114
+ record('control: optionDetails showCondition accepts a normal condition', optionControl.accepted, optionControl.detail)
115
+
116
+ const optionPayload = await attempt(() => sdk.api.form_fields.updateOne(field.id, {
117
+ options: { optionDetails: [{ option: 'A', showCondition: condition(JS_PAYLOAD) }] } as any,
118
+ }))
119
+ record('3: form_fields.updateOne rejects $JS( in optionDetails showCondition', !optionPayload.accepted, optionPayload.detail)
120
+
121
+ /* ===== 4. options.productConditions[].showCondition ===== */
122
+
123
+ const productControl = await attempt(() => sdk.api.form_fields.updateOne(field.id, {
124
+ options: { productConditions: [{ productId: '000000000000000000000000', showCondition: condition(SAFE_VALUE) }] } as any,
125
+ }))
126
+ record('control: productConditions showCondition accepts a normal condition', productControl.accepted, productControl.detail)
127
+
128
+ const productPayload = await attempt(() => sdk.api.form_fields.updateOne(field.id, {
129
+ options: { productConditions: [{ productId: '000000000000000000000000', showCondition: condition(JS_PAYLOAD) }] } as any,
130
+ }))
131
+ record('4: form_fields.updateOne rejects $JS( in productConditions showCondition', !productPayload.accepted, productPayload.detail)
132
+
133
+ /* ===== 5. automation_triggers — the server-side evaluation path ===== */
134
+
135
+ const trigger = (conditions: object, extraInfo: object = {}) => ({
136
+ title: `${RAND()}`,
137
+ status: 'Inactive',
138
+ event: { type: 'Form Submitted', info: { formId: form.id, ...extraInfo }, ...conditions },
139
+ action: { type: 'Add Tags', info: { tags: ['security-regression'] } },
140
+ } as any)
141
+
142
+ const triggerControl = await attempt(() => sdk.api.automation_triggers.createOne(
143
+ trigger({ conditions: condition(SAFE_VALUE) })
144
+ ))
145
+ record('control: automation_triggers accepts normal event conditions', triggerControl.accepted, triggerControl.detail)
146
+
147
+ // NOTE: this is the case that caught the half fix — the orValidator's permissive arm accepted it.
148
+ const triggerPayload = await attempt(() => sdk.api.automation_triggers.createOne(
149
+ trigger({ conditions: condition(JS_PAYLOAD) })
150
+ ))
151
+ record('5a: automation_triggers rejects $JS( in event.conditions', !triggerPayload.accepted, triggerPayload.detail)
152
+
153
+ const byFormIdPayload = await attempt(() => sdk.api.automation_triggers.createOne(
154
+ trigger({}, { conditionsByFormId: { [form.id]: condition(JS_PAYLOAD) } })
155
+ ))
156
+ record('5b: automation_triggers rejects $JS( in event.info.conditionsByFormId', !byFormIdPayload.accepted, byFormIdPayload.detail)
157
+ } finally {
158
+ // Teardown BEFORE anything asserts — assert calls process.exit, which skips pending finallys and
159
+ // would strand the provisioned tenant permanently.
160
+ if (tenant) { try { await tenant.teardown() } catch (e) { console.error('teardown failed', e) } }
161
+ }
162
+
163
+ return checks
164
+ }
165
+
166
+ /** Asserting wrapper, for standalone runs and for sequential use in the suite. */
167
+ export const form_logic_js_execution_tests = async () => {
168
+ assert_checks('$JS in stored conditional logic', await form_logic_js_execution_checks())
169
+ }
170
+
171
+ // Allow running this test file independently
172
+ if (require.main === module) {
173
+ console.log(`🌐 Using API URL: ${host}`)
174
+ form_logic_js_execution_tests()
175
+ .then(() => {
176
+ console.log("✅ form logic JS execution test suite completed successfully")
177
+ process.exit(0)
178
+ })
179
+ .catch((error) => {
180
+ console.error("❌ form logic JS execution test suite failed:", error)
181
+ process.exit(1)
182
+ })
183
+ }
@@ -10,8 +10,7 @@ import { setup_tests } from "../../setup"
10
10
  const host = process.env.API_URL || 'http://localhost:8080' as const
11
11
 
12
12
  /**
13
- * Regression test for F-0145
14
- * (security-audit/findings/F-0145-globalunique-conflict-leaks-cross-tenant-record.md).
13
+ * Regression test: a globalUnique conflict response must not echo the matched record.
15
14
  *
16
15
  * The create endpoint generator's unconditional globalUnique-enforcement block
17
16
  * (routing.ts, "globalUnique should be enforced even if _overrideUnique is true")
@@ -24,7 +23,7 @@ const host = process.env.API_URL || 'http://localhost:8080' as const
24
23
  * 409 body's existingRecord exposes nothing beyond _id + businessId.
25
24
  */
26
25
  export const globalunique_leak_tests = async ({ sdk } : { sdk: Session, sdkNonAdmin: Session }) => {
27
- log_header("F-0145: globalUnique conflict response redaction")
26
+ log_header("globalUnique conflict response redaction")
28
27
 
29
28
  let userId: string | undefined
30
29
  try {
@@ -33,7 +32,7 @@ export const globalunique_leak_tests = async ({ sdk } : { sdk: Session, sdkNonAd
33
32
  userId = user.id
34
33
 
35
34
  await async_test(
36
- 'F-0145: globalUnique 409 existingRecord exposes only _id + businessId (no email/hashedPass)',
35
+ 'globalUnique 409 existingRecord exposes only _id + businessId (no email/hashedPass)',
37
36
  () => sdk.api.users.createOne({ email, _overrideUnique: true } as any),
38
37
  {
39
38
  shouldError: true,
@@ -68,11 +67,11 @@ if (require.main === module) {
68
67
 
69
68
  runTests()
70
69
  .then(() => {
71
- console.log("✅ F-0145 globalUnique leak test suite completed successfully")
70
+ console.log("✅ globalUnique leak test suite completed successfully")
72
71
  process.exit(0)
73
72
  })
74
73
  .catch((error) => {
75
- console.error("❌ F-0145 globalUnique leak test suite failed:", error)
74
+ console.error("❌ globalUnique leak test suite failed:", error)
76
75
  process.exit(1)
77
76
  })
78
77
  }
@@ -27,7 +27,7 @@ const post = async (path: string, body: any, headers: Record<string, string> = {
27
27
  }
28
28
 
29
29
  /**
30
- * Regression test for F-0008 (security-audit/findings/F-0008-handle-incoming-communication-cross-tenant-enduser-lookup.md).
30
+ * Regression test: `handle_incoming_communication` tenant scoping.
31
31
  *
32
32
  * `journeys.handle_incoming_communication` previously used `buildAllQueries({ unrestricted: true, organizationIds: [] }).endusers.findById(enduserId)`,
33
33
  * permitting cross-tenant lookup of any enduser by id. The handler then called `handleIncomingCommunication(...)`
@@ -45,7 +45,7 @@ const post = async (path: string, body: any, headers: Record<string, string> = {
45
45
  * enduser — the post-fix code returns 404 before any side effects fire, and the assertion confirms that.
46
46
  */
47
47
  export const handle_incoming_communication_cross_tenant_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
48
- log_header("F-0008: handle_incoming_communication cross-tenant rejection")
48
+ log_header("handle_incoming_communication cross-tenant rejection")
49
49
 
50
50
  // ====================================================================
51
51
  // Assertion 1: nonexistent enduserId returns 404 (baseline; regression
@@ -58,19 +58,19 @@ export const handle_incoming_communication_cross_tenant_tests = async ({ sdk, sd
58
58
  { Authorization: `Bearer ${sdk.authToken}` },
59
59
  )
60
60
  await async_test(
61
- "F-0008: handle_incoming_communication with nonexistent enduserId returns 404",
61
+ "handle_incoming_communication with nonexistent enduserId returns 404",
62
62
  async () => ({ status: nonexistentRes.status }),
63
63
  { onResult: r => r.status === 404 },
64
64
  )
65
65
 
66
66
  // ====================================================================
67
- // Assertion 2: cross-tenant enduserId returns 404 (the actual F-0008 fix).
67
+ // Assertion 2: cross-tenant enduserId returns 404 (the actual fix).
68
68
  // Env-gated; skipped when cross-org infra isn't configured.
69
69
  // Safe to run post-fix because the tenant-scoped DB returns null for
70
70
  // cross-tenant lookups — no handleIncomingCommunication side effect fires.
71
71
  // ====================================================================
72
72
  if (!(CROSS_ORG_API_KEY && CROSS_ORG_TARGET_BUSINESS_ID)) {
73
- console.log(" [F-0008] Skipping cross-tenant rejection assertion — CROSS_ORG_* env vars not set")
73
+ console.log(" Skipping cross-tenant rejection assertion — CROSS_ORG_* env vars not set")
74
74
  return
75
75
  }
76
76
 
@@ -96,7 +96,7 @@ export const handle_incoming_communication_cross_tenant_tests = async ({ sdk, sd
96
96
  )
97
97
 
98
98
  await async_test(
99
- "F-0008: handle_incoming_communication with cross-tenant enduserId returns 404 (no side effect)",
99
+ "handle_incoming_communication with cross-tenant enduserId returns 404 (no side effect)",
100
100
  async () => ({
101
101
  status: crossRes.status,
102
102
  message: crossRes.data?.message ?? null,
@@ -120,11 +120,11 @@ if (require.main === module) {
120
120
 
121
121
  runTests()
122
122
  .then(() => {
123
- console.log("✅ F-0008 handle_incoming_communication cross-tenant test suite completed successfully")
123
+ console.log("✅ handle_incoming_communication cross-tenant test suite completed successfully")
124
124
  process.exit(0)
125
125
  })
126
126
  .catch((error) => {
127
- console.error("❌ F-0008 handle_incoming_communication cross-tenant test suite failed:", error)
127
+ console.error("❌ handle_incoming_communication cross-tenant test suite failed:", error)
128
128
  process.exit(1)
129
129
  })
130
130
  }