@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
@@ -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-0007 (security-audit/findings/F-0007-invite-user-cross-tenant-email-enumeration.md).
30
+ * Regression test: `invite_user` cross-tenant enumeration.
31
31
  *
32
32
  * `users.invite_user` previously used `buildAllQueries({ unrestricted: true, organizationIds: [] }).users.findOne({ email })`
33
33
  * to enforce platform-wide email uniqueness and threw the distinctive `"A user with this email already exists"`
@@ -50,7 +50,7 @@ const post = async (path: string, body: any, headers: Record<string, string> = {
50
50
  * env vars are not set, mirroring cross_org_api_key.test.ts convention.
51
51
  */
52
52
  export const invite_user_enumeration_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
53
- log_header("F-0007: users.invite_user cross-tenant enumeration regression")
53
+ log_header("users.invite_user cross-tenant enumeration regression")
54
54
 
55
55
  // Reset state so prior tests' rate-limit accounting doesn't leak in.
56
56
  await sdk.reset_db()
@@ -85,7 +85,7 @@ export const invite_user_enumeration_tests = async ({ sdk, sdkNonAdmin } : { sdk
85
85
  }
86
86
 
87
87
  await async_test(
88
- "F-0007: invite_user rate-limits within ~12 rapid requests (defense-in-depth; no invites sent)",
88
+ "invite_user rate-limits within ~12 rapid requests (defense-in-depth; no invites sent)",
89
89
  async () => ({ rateLimitedAt }),
90
90
  { onResult: r => r.rateLimitedAt >= 0 && r.rateLimitedAt <= 12 },
91
91
  )
@@ -111,7 +111,7 @@ export const invite_user_enumeration_tests = async ({ sdk, sdkNonAdmin } : { sdk
111
111
  )
112
112
 
113
113
  await async_test(
114
- "F-0007: invite_user same-tenant duplicate returns 400 'already exists' (unchanged)",
114
+ "invite_user same-tenant duplicate returns 400 'already exists' (unchanged)",
115
115
  async () => ({
116
116
  status: sameTenantRes.status,
117
117
  message: sameTenantRes.data?.message ?? '',
@@ -124,7 +124,7 @@ export const invite_user_enumeration_tests = async ({ sdk, sdkNonAdmin } : { sdk
124
124
  // Env-gated; skipped when cross-org infra not configured.
125
125
  // ====================================================================
126
126
  if (!(CROSS_ORG_API_KEY && CROSS_ORG_TARGET_BUSINESS_ID)) {
127
- console.log(" [F-0007] Skipping cross-tenant silent no-op assertion — CROSS_ORG_* env vars not set")
127
+ console.log(" Skipping cross-tenant silent no-op assertion — CROSS_ORG_* env vars not set")
128
128
  return
129
129
  }
130
130
 
@@ -160,7 +160,7 @@ export const invite_user_enumeration_tests = async ({ sdk, sdkNonAdmin } : { sdk
160
160
  )
161
161
 
162
162
  await async_test(
163
- "F-0007: cross-tenant invite of existing email must NOT return 'already exists' (no enumeration)",
163
+ "cross-tenant invite of existing email must NOT return 'already exists' (no enumeration)",
164
164
  async () => ({
165
165
  status: crossRes.status,
166
166
  message: crossRes.data?.message ?? '',
@@ -188,11 +188,11 @@ if (require.main === module) {
188
188
 
189
189
  runTests()
190
190
  .then(() => {
191
- console.log("✅ F-0007 invite_user enumeration test suite completed successfully")
191
+ console.log("✅ invite_user enumeration test suite completed successfully")
192
192
  process.exit(0)
193
193
  })
194
194
  .catch((error) => {
195
- console.error("❌ F-0007 invite_user enumeration test suite failed:", error)
195
+ console.error("❌ invite_user enumeration test suite failed:", error)
196
196
  process.exit(1)
197
197
  })
198
198
  }
@@ -12,8 +12,7 @@ const host = process.env.API_URL || 'http://localhost:8080' as const
12
12
  const ENDUSER_PASSWORD = 'F0151TestPassword!123'
13
13
 
14
14
  /**
15
- * Regression test for F-0151
16
- * (security-audit/findings/F-0151-load-inbox-data-endusers-unredacted.md).
15
+ * Regression test: `load_inbox_data` must apply enduser field redactions.
17
16
  *
18
17
  * load_inbox_data serialized $lookup'ed endusers via convert_id_name only (NOT applyRedactions),
19
18
  * so endusers.hashedPassword (redactions:['all']) leaked to staff sessions — while the sibling
@@ -24,7 +23,7 @@ const ENDUSER_PASSWORD = 'F0151TestPassword!123'
24
23
  * assert the returned enduser entry has NO hashedPassword.
25
24
  */
26
25
  export const load_inbox_redaction_tests = async ({ sdk } : { sdk: Session, sdkNonAdmin: Session }) => {
27
- log_header("F-0151: load_inbox_data enduser redaction")
26
+ log_header("load_inbox_data enduser redaction")
28
27
 
29
28
  let enduserId: string | undefined
30
29
  let emailId: string | undefined
@@ -42,7 +41,7 @@ export const load_inbox_redaction_tests = async ({ sdk } : { sdk: Session, sdkNo
42
41
  emailId = seeded.id
43
42
 
44
43
  await async_test(
45
- 'F-0151: load_inbox_data does not leak enduser.hashedPassword to staff',
44
+ 'load_inbox_data does not leak enduser.hashedPassword to staff',
46
45
  () => sdk.api.endusers.load_inbox_data({ enduserIds: [enduser.id] } as any),
47
46
  {
48
47
  onResult: (r: any) => {
@@ -71,11 +70,11 @@ if (require.main === module) {
71
70
 
72
71
  runTests()
73
72
  .then(() => {
74
- console.log("✅ F-0151 load_inbox_data redaction test suite completed successfully")
73
+ console.log("✅ load_inbox_data redaction test suite completed successfully")
75
74
  process.exit(0)
76
75
  })
77
76
  .catch((error) => {
78
- console.error("❌ F-0151 load_inbox_data redaction test suite failed:", error)
77
+ console.error("❌ load_inbox_data redaction test suite failed:", error)
79
78
  process.exit(1)
80
79
  })
81
80
  }
@@ -1,16 +1,16 @@
1
1
  import { add_value_for_dotted_key } from "@tellescope/utilities"
2
2
 
3
- // Regression test for F-0016 (pattern 17 — prototype pollution).
3
+ // Regression test: prototype pollution via dotted-key assignment.
4
4
  // add_value_for_dotted_key must NOT write through __proto__/constructor/prototype path segments
5
5
  // (which would pollute Object.prototype process-wide), while still performing legitimate dotted assignment.
6
6
  //
7
7
  // Pure-function test — no Session needed. Runs in the main suite and standalone:
8
- // ./build_cjs.sh && cd packages/public/sdk && node -r dotenv/config lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.js
8
+ // ./build_cjs.sh && cd packages/public/sdk && node -r dotenv/config lib/cjs/tests/api_tests/security/prototype-pollution.test.js
9
9
 
10
10
  const fail = (msg: string) => { throw new Error(msg) }
11
11
 
12
12
  export const prototype_pollution_tests = async () => {
13
- console.log("Running F-0016 prototype-pollution regression tests")
13
+ console.log("Running prototype-pollution regression tests")
14
14
 
15
15
  // 1. __proto__ path must not pollute Object.prototype
16
16
  add_value_for_dotted_key({ insurance: {} } as any, 'insurance.__proto__.__pp_a__', 'polluted')
@@ -40,7 +40,7 @@ export const prototype_pollution_tests = async () => {
40
40
  add_value_for_dotted_key(flat, 'name', 'ok')
41
41
  if (flat.name !== 'ok') fail('single-key assignment broke')
42
42
 
43
- console.log("✅ F-0016 prototype-pollution regression tests passed")
43
+ console.log("✅ prototype-pollution regression tests passed")
44
44
  }
45
45
 
46
46
  if (require.main === module) {
@@ -22,15 +22,14 @@ const assert_local_api = () => {
22
22
  const hostname = new URL(host).hostname
23
23
  if (!LOCAL_HOSTNAMES.includes(hostname)) {
24
24
  throw new Error(
25
- `F-0025 SSRF tests must run against a local API (got ${host}). `
25
+ `SSRF tests must run against a local API (got ${host}). `
26
26
  + `127.0.0.1 would resolve to the API server rather than this machine, so the tests would be meaningless.`
27
27
  )
28
28
  }
29
29
  }
30
30
 
31
31
  /**
32
- * Regression tests for F-0025
33
- * (security-audit/findings/F-0025-proxy-image-unauth-ssrf.md).
32
+ * Regression tests: `/v1/proxy-image` must refuse internal and non-image destinations.
34
33
  *
35
34
  * GET /v1/proxy-image accepted an arbitrary ?url= and streamed the upstream response body straight
36
35
  * back with Access-Control-Allow-Origin: *, with no authentication, no destination validation and no
@@ -58,7 +57,7 @@ const assert_local_api = () => {
58
57
  * the vulnerability proof.
59
58
  */
60
59
  export const proxy_image_ssrf_tests = async ({ sdk } : { sdk: Session, sdkNonAdmin: Session }) => {
61
- log_header("F-0025: proxy-image unauthenticated SSRF")
60
+ log_header("proxy-image unauthenticated SSRF")
62
61
  assert_local_api()
63
62
 
64
63
  const SENTINEL = `f0025-sentinel-${Date.now()}-${Math.random().toString(36).slice(2)}`
@@ -95,7 +94,7 @@ export const proxy_image_ssrf_tests = async ({ sdk } : { sdk: Session, sdkNonAdm
95
94
 
96
95
  // T1 — the core SSRF: an unauthenticated caller must not be able to read an internal resource.
97
96
  await async_test(
98
- 'F-0025: proxy-image does not stream an internal non-image resource to an unauthenticated caller',
97
+ 'proxy-image does not stream an internal non-image resource to an unauthenticated caller',
99
98
  call_unauthenticated,
100
99
  {
101
100
  // Positive control: a numeric status proves we actually reached our API rather than failing to
@@ -111,7 +110,7 @@ export const proxy_image_ssrf_tests = async ({ sdk } : { sdk: Session, sdkNonAdm
111
110
  // T2 — the unauthenticated surface itself: the request must be refused outright, and the
112
111
  // destination must never be contacted (no SSRF-as-a-side-effect even when the body is withheld).
113
112
  await async_test(
114
- 'F-0025: proxy-image refuses an unauthenticated request without contacting the destination',
113
+ 'proxy-image refuses an unauthenticated request without contacting the destination',
115
114
  call_unauthenticated,
116
115
  { onResult: (r: any) => r.status >= 400 && r.status < 500 && r.sentinelHits === 0 },
117
116
  )
@@ -129,26 +128,26 @@ export const proxy_image_ssrf_tests = async ({ sdk } : { sdk: Session, sdkNonAdm
129
128
  }
130
129
 
131
130
  await async_test(
132
- 'F-0025: proxy-image refuses a private destination even for an authenticated staff session',
131
+ 'proxy-image refuses a private destination even for an authenticated staff session',
133
132
  () => call_authenticated(sentinelURL),
134
133
  { onResult: (r: any) => r.status === 400 && r.sentinelHits === 0 },
135
134
  )
136
135
 
137
136
  await async_test(
138
- 'F-0025: proxy-image refuses cloud metadata for an authenticated staff session',
137
+ 'proxy-image refuses cloud metadata for an authenticated staff session',
139
138
  () => call_authenticated('https://169.254.169.254/latest/meta-data/'),
140
139
  { onResult: (r: any) => r.status === 400 },
141
140
  )
142
141
 
143
142
  // Scheme and port are pinned: only https on 443, which is all the PDF export ever needs.
144
143
  await async_test(
145
- 'F-0025: proxy-image refuses a plain http destination',
144
+ 'proxy-image refuses a plain http destination',
146
145
  () => call_authenticated('http://example.com/logo.png'),
147
146
  { onResult: (r: any) => r.status === 400 },
148
147
  )
149
148
 
150
149
  await async_test(
151
- 'F-0025: proxy-image refuses a non-443 port',
150
+ 'proxy-image refuses a non-443 port',
152
151
  () => call_authenticated('https://example.com:8443/logo.png'),
153
152
  { onResult: (r: any) => r.status === 400 },
154
153
  )
@@ -169,11 +168,11 @@ if (require.main === module) {
169
168
 
170
169
  runTests()
171
170
  .then(() => {
172
- console.log("✅ F-0025 proxy-image SSRF test suite completed successfully")
171
+ console.log("✅ proxy-image SSRF test suite completed successfully")
173
172
  process.exit(0)
174
173
  })
175
174
  .catch((error) => {
176
- console.error("❌ F-0025 proxy-image SSRF test suite failed:", error)
175
+ console.error("❌ proxy-image SSRF test suite failed:", error)
177
176
  process.exit(1)
178
177
  })
179
178
  }
@@ -1,22 +1,22 @@
1
1
  import { DEFAULT_IFRAME_SANDBOX, replace_form_field_template_values, sanitize_user_html, sanitize_user_html_with_iframes } from "@tellescope/utilities"
2
2
 
3
- // Companion to F-0013-sanitize-user-html.test.ts (pattern 06 — XSS via dangerouslySetInnerHTML).
3
+ // Companion to sanitize-user-html.test.ts (pattern 06 — XSS via dangerouslySetInnerHTML).
4
4
  //
5
5
  // sanitize_user_html_with_iframes is the variant used by the live form's field description, so
6
6
  // admins can embed video / scheduling widgets. It permits <iframe> and NOTHING else beyond what
7
7
  // sanitize_user_html allows. This asserts:
8
- // 1. permitting iframe did not reopen any of the F-0013 vectors (the full payload list is re-run)
8
+ // 1. permitting iframe did not reopen any of the base vectors (the full payload list is re-run)
9
9
  // 2. only absolute https iframes survive — relative, protocol-relative, http, javascript:, data:
10
10
  // and srcdoc frames are dropped, along with their fallback content
11
11
  // 3. the restrictive sandbox is forced, but an author-supplied sandbox is honored
12
12
  // 4. sanitize_user_html itself still strips iframes (the boundary between the two functions)
13
13
  //
14
14
  // Pure-function test — no Session needed. Runs as part of the main suite and standalone:
15
- // ./build_cjs.sh && cd packages/public/sdk && node -r dotenv/config lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.js
15
+ // ./build_cjs.sh && cd packages/public/sdk && node -r dotenv/config lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js
16
16
 
17
17
  const fail = (msg: string) => { throw new Error(msg) }
18
18
 
19
- // Same as has_no_executable_vector in the F-0013 test, minus the '<iframe' clause (iframes are
19
+ // Same as has_no_executable_vector in the base sanitizer test, minus the '<iframe' clause (iframes are
20
20
  // expected in this function's output). Everything else must still be neutralized.
21
21
  const has_no_executable_vector_allowing_iframe = (out: string) => {
22
22
  const o = out.toLowerCase()
@@ -49,7 +49,7 @@ export const sanitize_user_html_with_iframes_tests = async () => {
49
49
  console.log("Running sanitize_user_html_with_iframes XSS regression tests")
50
50
 
51
51
  // ---------------------------------------------------------------------------------------------
52
- // 1. Re-run the full F-0013 payload set — permitting iframe must not be a general regression
52
+ // 1. Re-run the full base payload set — permitting iframe must not be a general regression
53
53
  // ---------------------------------------------------------------------------------------------
54
54
  const xssPayloads: [string, string][] = [
55
55
  ['img onerror', `<img src=x onerror="alert(document.domain)">`],
@@ -1,13 +1,13 @@
1
1
  import { sanitize_user_html } from "@tellescope/utilities"
2
2
 
3
- // Regression test for F-0013 / F-0014 (pattern 06 — XSS via dangerouslySetInnerHTML).
3
+ // Regression test: XSS via dangerouslySetInnerHTML.
4
4
  // sanitize_user_html is the canonical render-time sanitizer that replaced remove_script_tags
5
5
  // at every dangerouslySetInnerHTML sink. This asserts it neutralizes XSS vectors (incl. encoded /
6
6
  // whitespace / mixed-case / iframe-srcdoc bypass variants) while preserving legitimate
7
7
  // customization HTML (tables, headings, lists, links, images, inline styles).
8
8
  //
9
9
  // Pure-function test — no Session needed. Runs as part of the main suite and standalone:
10
- // ./build_cjs.sh && cd packages/public/sdk && node -r dotenv/config lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.js
10
+ // ./build_cjs.sh && cd packages/public/sdk && node -r dotenv/config lib/cjs/tests/api_tests/security/sanitize-user-html.test.js
11
11
 
12
12
  const fail = (msg: string) => { throw new Error(msg) }
13
13
 
@@ -31,7 +31,7 @@ const has_no_executable_vector = (out: string) => {
31
31
  }
32
32
 
33
33
  export const sanitize_user_html_xss_tests = async () => {
34
- console.log("Running F-0013/F-0014 sanitize_user_html XSS regression tests")
34
+ console.log("Running sanitize_user_html XSS regression tests")
35
35
 
36
36
  const xssPayloads: [string, string][] = [
37
37
  ['img onerror', `<img src=x onerror="alert(document.domain)">`],
@@ -99,7 +99,7 @@ export const sanitize_user_html_xss_tests = async () => {
99
99
  const mixed = sanitize_user_html(`<p>Hello <b>name</b></p><img src=x onerror="steal()">`)
100
100
  if (!(mixed.includes('<b>name</b>') && !/\son[a-z]+\s*=/.test(mixed.toLowerCase()))) fail(`mixed content not handled: ${mixed}`)
101
101
 
102
- console.log("✅ F-0013/F-0014 sanitize_user_html XSS regression tests passed")
102
+ console.log("✅ sanitize_user_html XSS regression tests passed")
103
103
  }
104
104
 
105
105
  if (require.main === module) {
@@ -0,0 +1,287 @@
1
+ require('source-map-support').install();
2
+
3
+ import axios from "axios"
4
+
5
+ import { Session } from "../../../sdk"
6
+ import {
7
+ assert,
8
+ log_header,
9
+ } from "@tellescope/testing"
10
+ import { PROVIDER_PERMISSIONS } from "@tellescope/constants"
11
+ import { setup_tests } from "../../setup"
12
+
13
+ const host = process.env.API_URL || 'http://localhost:8080' as const
14
+
15
+ const RAND = () => Math.random().toString(36).slice(2, 10)
16
+
17
+ const ALL = 'All' as const
18
+ const FULL_ACCESS = { create: ALL, read: ALL, update: ALL, delete: ALL }
19
+
20
+ type Check = {
21
+ label: string,
22
+ pass: boolean,
23
+ detail: string,
24
+ }
25
+
26
+ /**
27
+ * Regression test: `adminOnly` custom actions must be enforced at runtime, not merely declared.
28
+ *
29
+ * `adminOnly: true` on a CUSTOM action in schema.ts was documentation-only. The runtime gate
30
+ * (routing.ts:944) reads the flag off the options object built by getCustomEndpointFields, and
31
+ * api.ts:609 set `adminOnly: o.adminOnly` without ever consulting `action.adminOnly`. So every
32
+ * admin-only custom action had to declare the flag twice, and the copies desynced: 11 of 20
33
+ * declared custom actions were unenforced at runtime while both public doc artifacts
34
+ * (openapi.json and the unauthenticated GET /documentation feed, which read the SCHEMA flag)
35
+ * advertised "**Admin only.**".
36
+ *
37
+ * DEFAULT CRUD actions never had this bug — routing.ts:2434 etc. read
38
+ * model.defaultActions.<op>.adminOnly straight off the schema. The fix
39
+ * (`adminOnly: o.adminOnly ?? action.adminOnly`) makes custom actions behave the same way.
40
+ *
41
+ * Five of the 11 were de-flagged in the schema instead, because the flag itself was wrong and
42
+ * enforcing it would revert a deliberate decision: users.invite_user carries an explicit
43
+ * "no longer admin only, but controlled by users.create" and send_invitation_to_existing is its
44
+ * sibling; organizations.create_and_join is the self-service signup path and would 401 every new
45
+ * org (a fresh user has no roles — the handler is what grants Admin); sync_note_to_canvas is
46
+ * designed around `access: 'read'` for non-admin callers; background_errors.mark_read substitutes
47
+ * its own RBAC check that intentionally admits non-admins holding the verb.
48
+ *
49
+ * SAFETY: every probe fails EARLY inside its handler — after the adminOnly gate but before any
50
+ * vendor call. Pre-fix these requests really do reach the handler, and these handlers talk to
51
+ * Twilio, Athena and Canvas:
52
+ * - trigger_events : no `action` key + an absent triggerId => the loop `continue`s (inert)
53
+ * - athena-subscription: frequency 1 trips the `frequency < 5` guard on the handler's first line
54
+ * - sync-athena : 404s on the missing Athena integration (skipped if one exists)
55
+ * - link-twilio : takes NO parameters and can CREATE A REAL TWILIO SUBACCOUNT, so it is
56
+ * probed only when the org already has a twilioSID (handler short-circuits)
57
+ * - twilio-embed : no phoneNumberSid => 404 no-config or 400, both before any Twilio call
58
+ * - handle-autoreply : absent enduserId => `if (!enduser) return` (communications.ts:42)
59
+ * Input validation runs BEFORE the adminOnly gate (routing.ts:921 orders access, then validate),
60
+ * so every probe body must be schema-VALID or the test would prove nothing.
61
+ *
62
+ * RED (pre-fix): the six group-B rows fail — each reaches its handler and returns a non-401.
63
+ * GREEN (post-fix): all six return 401 "Admin access only"; the group-A controls are unchanged.
64
+ */
65
+ export const schema_adminonly_enforcement_tests = async ({ sdk } : { sdk: Session, sdkNonAdmin: Session }) => {
66
+ log_header("schema-declared adminOnly must be enforced on custom actions")
67
+
68
+ const checks: Check[] = []
69
+ const record = (label: string, pass: boolean, detail: string) => checks.push({ label, pass, detail })
70
+
71
+ // Raw axios: the SDK's parseError discards the HTTP status, and the status is the whole point.
72
+ const request = async (
73
+ authToken: string, method: 'get' | 'post', path: string, data?: any,
74
+ ) => {
75
+ const r = await axios.request({
76
+ method,
77
+ url: `${host}/v1${path}`,
78
+ ...method === 'get' ? { params: data } : { data },
79
+ headers: { Authorization: `Bearer ${authToken}` },
80
+ validateStatus: () => true,
81
+ })
82
+ return { status: r.status, body: r.data }
83
+ }
84
+
85
+ const isAdminDenial = (r: { status: number, body: any }) => (
86
+ r.status === 401 && r.body?.message === 'Admin access only'
87
+ )
88
+ const summarize = (r: { status: number, body: any }) => (
89
+ `${r.status} ${(JSON.stringify(r.body) ?? '').slice(0, 120)}`
90
+ )
91
+
92
+ let roleId = ''
93
+ let attackerId = ''
94
+ let enduserId = ''
95
+
96
+ try {
97
+ /* ================= fixtures ================= */
98
+
99
+ const role = `f0191-staff-${RAND()}`
100
+ const rbap = await sdk.api.role_based_access_permissions.createOne({
101
+ role,
102
+ permissions: {
103
+ ...PROVIDER_PERMISSIONS,
104
+ // grant exactly the verbs the actions under test declare, so a rejection proves the ADMIN
105
+ // gate fired rather than ordinary RBAC
106
+ automation_triggers: FULL_ACCESS,
107
+ organizations: FULL_ACCESS,
108
+ availability_blocks: FULL_ACCESS,
109
+ background_errors: FULL_ACCESS,
110
+ users: FULL_ACCESS,
111
+ },
112
+ } as any)
113
+ roleId = rbap.id
114
+
115
+ const attacker = await sdk.api.users.createOne({
116
+ email: `f0191-attacker-${RAND()}@tellescope.example`,
117
+ fname: 'F0191', lname: 'Staff',
118
+ verifiedEmail: true,
119
+ notificationEmailsDisabled: true,
120
+ roles: [role],
121
+ } as any)
122
+ attackerId = attacker.id
123
+
124
+ const attackerToken = (await sdk.api.users.generate_auth_token({ id: attackerId })).authToken
125
+ const adminToken = (await sdk.api.users.generate_auth_token({ id: sdk.userInfo.id })).authToken
126
+
127
+ const attackerSDK = new Session({ host, authToken: attackerToken })
128
+ await attackerSDK.refresh_session()
129
+ record(
130
+ 'setup: attacker is a non-admin holding every verb under test',
131
+ attackerSDK.userInfo.id === attackerId && !(attackerSDK.userInfo.roles ?? []).includes('Admin'),
132
+ `id=${attackerSDK.userInfo.id} roles=${JSON.stringify(attackerSDK.userInfo.roles)}`,
133
+ )
134
+
135
+ const enduser = await sdk.api.endusers.createOne({ fname: 'F0191', lname: 'Patient' })
136
+ enduserId = enduser.id
137
+
138
+ // A guaranteed-valid, guaranteed-absent id: create then delete, so probes hit the handler's
139
+ // "not found" branch rather than tripping input validation (which runs BEFORE the admin gate).
140
+ const doomed = await sdk.api.endusers.createOne({ fname: 'F0191', lname: 'Absent' })
141
+ const ABSENT_ID = doomed.id
142
+ await sdk.api.endusers.deleteOne(ABSENT_ID)
143
+
144
+ /* ===== environment guards for the two probes input alone cannot make safe ===== */
145
+
146
+ let athenaIntegrationExists = false
147
+ try {
148
+ const existing = await sdk.api.integrations.load_redacted({})
149
+ athenaIntegrationExists = !!existing.integrations.find((i: any) => /athena/i.test(i.title ?? ''))
150
+ } catch { /* load not permitted — assume absent */ }
151
+
152
+ let orgHasTwilioSID = false
153
+ try {
154
+ const org = await sdk.api.organizations.getOne(sdk.userInfo.businessId)
155
+ orgHasTwilioSID = !!(org as any)?.twilioSID
156
+ } catch { /* ignore */ }
157
+
158
+ /* ===== GROUP B: the six genuine gaps — each must become 401 ===== */
159
+
160
+ const groupB: {
161
+ label: string, method: 'get' | 'post', path: string, data?: any, skip?: string,
162
+ }[] = [
163
+ {
164
+ label: 'automation_triggers.trigger_events',
165
+ method: 'post', path: '/automation-triggers/trigger-events',
166
+ // no `action` key: stays off the arbitrary-action-execution branch entirely
167
+ data: { triggers: [{ enduserId, automationTriggerId: ABSENT_ID }] },
168
+ },
169
+ {
170
+ label: 'organizations.add_athena_subscription',
171
+ method: 'post', path: '/organizations/athena-subscription',
172
+ data: { type: 'patients', frequency: 1 }, // trips `frequency < 5` on the handler's first line
173
+ },
174
+ {
175
+ label: 'organizations.sync_athena_subscription',
176
+ method: 'post', path: '/organizations/sync-athena-subscription',
177
+ data: { type: 'patients' },
178
+ skip: athenaIntegrationExists
179
+ ? 'org HAS an Athena integration — probing would call Athena.process_subscription for real'
180
+ : undefined,
181
+ },
182
+ {
183
+ label: 'organizations.link_twilio',
184
+ method: 'post', path: '/organizations/link-twilio',
185
+ data: {},
186
+ skip: orgHasTwilioSID
187
+ ? undefined
188
+ : 'org has no twilioSID — probing would CREATE A REAL TWILIO SUBACCOUNT',
189
+ },
190
+ {
191
+ label: 'organizations.load_twilio_embed',
192
+ method: 'get', path: '/organizations/twilio-embed',
193
+ data: { type: 'tfn-verification' }, // no phoneNumberSid => rejected before any Twilio call
194
+ },
195
+ {
196
+ label: 'availability_blocks.handle_autoreply',
197
+ method: 'post', path: '/handle-out-of-office-autoreply',
198
+ data: { channel: 'Email', enduserId: ABSENT_ID }, // communications.ts:42 `if (!enduser) return`
199
+ },
200
+ ]
201
+
202
+ for (const probe of groupB) {
203
+ if (probe.skip) {
204
+ record(`B: ${probe.label} rejects a non-admin`, true, `SKIPPED (safety) — ${probe.skip}`)
205
+ continue
206
+ }
207
+
208
+ const attackerResult = await request(attackerToken, probe.method, probe.path, probe.data)
209
+ // baseline: an admin must NOT be admin-denied on the same path, so a blanket 401 can't pass
210
+ const baseline = await request(adminToken, probe.method, probe.path, probe.data)
211
+ const badProbe = isAdminDenial(baseline)
212
+
213
+ record(
214
+ `B: ${probe.label} rejects a non-admin`,
215
+ !badProbe && isAdminDenial(attackerResult),
216
+ `attacker=${summarize(attackerResult)} | admin baseline=${baseline.status}`
217
+ + (badProbe ? ' BAD PROBE: admin was also admin-denied' : ''),
218
+ )
219
+ }
220
+
221
+ /* ===== GROUP A: de-flagged actions must NOT become admin-only ===== */
222
+
223
+ const groupA: { label: string, method: 'get' | 'post', path: string, data?: any }[] = [
224
+ {
225
+ label: 'organizations.sync_note_to_canvas',
226
+ method: 'post', path: '/organizations/sync-note-to-canvas',
227
+ data: { enduserId: ABSENT_ID, note: 'control' }, // 404 Enduser not found
228
+ },
229
+ {
230
+ label: 'background_errors.mark_read',
231
+ method: 'post', path: '/background-errors/mark-read', data: {},
232
+ },
233
+ {
234
+ label: 'users.send_invitation_to_existing',
235
+ method: 'post', path: '/invite-existing-user-to-organization',
236
+ // takes userId (not email); an absent id hits RecordNotFoundError, well short of any invite
237
+ data: { userId: ABSENT_ID },
238
+ },
239
+ ]
240
+
241
+ for (const probe of groupA) {
242
+ const r = await request(attackerToken, probe.method, probe.path, probe.data)
243
+ record(
244
+ `A: ${probe.label} stays reachable by a non-admin (flag intentionally dropped)`,
245
+ !isAdminDenial(r),
246
+ `${summarize(r)} (expected a handler response, not 401 Admin access only)`,
247
+ )
248
+ }
249
+
250
+ /* ===== report: print full table first, then assert (harness exits on first failure) ===== */
251
+ console.log('\n check summary:')
252
+ for (const c of checks) {
253
+ console.log(` ${c.pass ? 'PASS' : 'FAIL'} ${c.label} — ${c.detail}`)
254
+ }
255
+ console.log('')
256
+
257
+ for (const c of checks) {
258
+ assert(c.pass, `${c.label} — ${c.detail}`, c.label)
259
+ }
260
+ } finally {
261
+ if (enduserId) { try { await sdk.api.endusers.deleteOne(enduserId) } catch {} }
262
+ if (attackerId) { try { await sdk.api.users.deleteOne(attackerId) } catch {} }
263
+ if (roleId) { try { await sdk.api.role_based_access_permissions.deleteOne(roleId) } catch {} }
264
+ }
265
+ }
266
+
267
+ // Allow running this test file independently
268
+ if (require.main === module) {
269
+ console.log(`🌐 Using API URL: ${host}`)
270
+ const sdk = new Session({ host })
271
+ const sdkNonAdmin = new Session({ host })
272
+
273
+ const runTests = async () => {
274
+ await setup_tests(sdk, sdkNonAdmin)
275
+ await schema_adminonly_enforcement_tests({ sdk, sdkNonAdmin })
276
+ }
277
+
278
+ runTests()
279
+ .then(() => {
280
+ console.log("✅ schema adminOnly enforcement test suite completed successfully")
281
+ process.exit(0)
282
+ })
283
+ .catch((error) => {
284
+ console.error("❌ schema adminOnly enforcement test suite failed:", error)
285
+ process.exit(1)
286
+ })
287
+ }