@tellescope/sdk 1.256.14 → 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 (283) 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 +1 -1
  10. package/lib/cjs/tests/api_tests/organization_signup.test.js +1 -1
  11. package/lib/cjs/tests/api_tests/purchase_made_trigger.test.d.ts.map +1 -1
  12. package/lib/cjs/tests/api_tests/purchase_made_trigger.test.js +103 -162
  13. package/lib/cjs/tests/api_tests/purchase_made_trigger.test.js.map +1 -1
  14. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts +33 -0
  15. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts.map +1 -0
  16. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.js +249 -0
  17. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.js.map +1 -0
  18. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts +42 -0
  19. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -0
  20. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +281 -0
  21. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -0
  22. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.d.ts +38 -0
  23. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.d.ts.map +1 -0
  24. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.js +390 -0
  25. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.js.map +1 -0
  26. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.d.ts +6 -0
  27. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.d.ts.map +1 -0
  28. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.js +1003 -0
  29. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.js.map +1 -0
  30. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.d.ts +42 -0
  31. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.d.ts.map +1 -0
  32. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.js +323 -0
  33. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.js.map +1 -0
  34. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts +29 -0
  35. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts.map +1 -0
  36. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.js +335 -0
  37. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.js.map +1 -0
  38. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts +32 -0
  39. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts.map +1 -0
  40. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js +237 -0
  41. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js.map +1 -0
  42. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts +28 -0
  43. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts.map +1 -0
  44. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.js +349 -0
  45. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.js.map +1 -0
  46. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts +30 -0
  47. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts.map +1 -0
  48. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js +314 -0
  49. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js.map +1 -0
  50. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.d.ts +21 -0
  51. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.d.ts.map +1 -0
  52. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.js +362 -0
  53. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.js.map +1 -0
  54. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.d.ts +21 -0
  55. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.d.ts.map +1 -0
  56. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.js +366 -0
  57. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.js.map +1 -0
  58. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.d.ts +32 -0
  59. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.d.ts.map +1 -0
  60. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.js +248 -0
  61. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.js.map +1 -0
  62. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts +19 -0
  63. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts.map +1 -0
  64. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.js +138 -0
  65. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.js.map +1 -0
  66. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts +24 -0
  67. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
  68. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js +201 -0
  69. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js.map +1 -0
  70. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.d.ts +29 -0
  71. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.d.ts.map +1 -0
  72. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.js +278 -0
  73. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.js.map +1 -0
  74. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.d.ts +17 -0
  75. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.d.ts.map +1 -0
  76. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.js +155 -0
  77. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.js.map +1 -0
  78. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.d.ts +2 -0
  79. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.d.ts.map +1 -0
  80. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.js +88 -0
  81. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.js.map +1 -0
  82. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts +34 -0
  83. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts.map +1 -0
  84. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.js +230 -0
  85. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.js.map +1 -0
  86. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts +2 -0
  87. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts.map +1 -0
  88. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js +242 -0
  89. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js.map +1 -0
  90. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.d.ts +2 -0
  91. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.d.ts.map +1 -0
  92. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.js +148 -0
  93. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.js.map +1 -0
  94. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts +45 -0
  95. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts.map +1 -0
  96. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.js +388 -0
  97. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.js.map +1 -0
  98. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.d.ts +38 -0
  99. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.d.ts.map +1 -0
  100. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.js +222 -0
  101. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.js.map +1 -0
  102. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts +6 -0
  103. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts.map +1 -0
  104. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js +354 -0
  105. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js.map +1 -0
  106. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts +28 -0
  107. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts.map +1 -0
  108. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.js +442 -0
  109. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.js.map +1 -0
  110. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.d.ts +19 -0
  111. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.d.ts.map +1 -0
  112. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.js +156 -0
  113. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.js.map +1 -0
  114. package/lib/cjs/tests/api_tests/webhook_error_handling.test.js +2 -2
  115. package/lib/cjs/tests/api_tests/webhook_error_handling.test.js.map +1 -1
  116. package/lib/cjs/tests/tests.d.ts.map +1 -1
  117. package/lib/cjs/tests/tests.js +58 -46
  118. package/lib/cjs/tests/tests.js.map +1 -1
  119. package/lib/cjs/tests/unit_tests/openapi_spec_freshness.test.d.ts +1 -1
  120. package/lib/cjs/tests/unit_tests/openapi_spec_freshness.test.js +1 -1
  121. package/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  122. package/lib/esm/enduser.d.ts +0 -1
  123. package/lib/esm/enduser.d.ts.map +1 -1
  124. package/lib/esm/sdk.d.ts +2 -3
  125. package/lib/esm/sdk.d.ts.map +1 -1
  126. package/lib/esm/session.d.ts +0 -1
  127. package/lib/esm/session.d.ts.map +1 -1
  128. package/lib/esm/tests/api_tests/auto_merge_form_submission.test.js +1 -1
  129. package/lib/esm/tests/api_tests/auto_merge_form_submission.test.js.map +1 -1
  130. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.d.ts +5 -0
  131. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.d.ts.map +1 -0
  132. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.js +383 -0
  133. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.js.map +1 -0
  134. package/lib/esm/tests/api_tests/integrations_redacted.test.js +3 -3
  135. package/lib/esm/tests/api_tests/integrations_redacted.test.js.map +1 -1
  136. package/lib/esm/tests/api_tests/organization_signup.test.d.ts +1 -1
  137. package/lib/esm/tests/api_tests/organization_signup.test.js +1 -1
  138. package/lib/esm/tests/api_tests/purchase_made_trigger.test.d.ts.map +1 -1
  139. package/lib/esm/tests/api_tests/purchase_made_trigger.test.js +104 -163
  140. package/lib/esm/tests/api_tests/purchase_made_trigger.test.js.map +1 -1
  141. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts +33 -0
  142. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts.map +1 -0
  143. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.js +244 -0
  144. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.js.map +1 -0
  145. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts +42 -0
  146. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -0
  147. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +276 -0
  148. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -0
  149. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.d.ts +38 -0
  150. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.d.ts.map +1 -0
  151. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.js +386 -0
  152. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.js.map +1 -0
  153. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.d.ts +6 -0
  154. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.d.ts.map +1 -0
  155. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.js +996 -0
  156. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.js.map +1 -0
  157. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.d.ts +42 -0
  158. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.d.ts.map +1 -0
  159. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.js +316 -0
  160. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.js.map +1 -0
  161. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts +29 -0
  162. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts.map +1 -0
  163. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.js +331 -0
  164. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.js.map +1 -0
  165. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts +32 -0
  166. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts.map +1 -0
  167. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js +233 -0
  168. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js.map +1 -0
  169. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts +28 -0
  170. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts.map +1 -0
  171. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.js +345 -0
  172. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.js.map +1 -0
  173. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts +30 -0
  174. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts.map +1 -0
  175. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js +310 -0
  176. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js.map +1 -0
  177. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.d.ts +21 -0
  178. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.d.ts.map +1 -0
  179. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.js +358 -0
  180. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.js.map +1 -0
  181. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.d.ts +21 -0
  182. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.d.ts.map +1 -0
  183. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.js +362 -0
  184. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.js.map +1 -0
  185. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.d.ts +32 -0
  186. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.d.ts.map +1 -0
  187. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.js +243 -0
  188. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.js.map +1 -0
  189. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts +19 -0
  190. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts.map +1 -0
  191. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.js +134 -0
  192. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.js.map +1 -0
  193. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts +24 -0
  194. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
  195. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js +194 -0
  196. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js.map +1 -0
  197. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.d.ts +29 -0
  198. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.d.ts.map +1 -0
  199. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.js +271 -0
  200. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.js.map +1 -0
  201. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.d.ts +17 -0
  202. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.d.ts.map +1 -0
  203. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.js +151 -0
  204. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.js.map +1 -0
  205. package/lib/esm/tests/api_tests/security/prototype-pollution.test.d.ts +2 -0
  206. package/lib/esm/tests/api_tests/security/prototype-pollution.test.d.ts.map +1 -0
  207. package/lib/esm/tests/api_tests/security/prototype-pollution.test.js +84 -0
  208. package/lib/esm/tests/api_tests/security/prototype-pollution.test.js.map +1 -0
  209. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts +34 -0
  210. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts.map +1 -0
  211. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.js +223 -0
  212. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.js.map +1 -0
  213. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts +2 -0
  214. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts.map +1 -0
  215. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.js +238 -0
  216. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.js.map +1 -0
  217. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.d.ts +2 -0
  218. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.d.ts.map +1 -0
  219. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.js +144 -0
  220. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.js.map +1 -0
  221. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts +45 -0
  222. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts.map +1 -0
  223. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.js +381 -0
  224. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.js.map +1 -0
  225. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.d.ts +38 -0
  226. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.d.ts.map +1 -0
  227. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.js +218 -0
  228. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.js.map +1 -0
  229. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts +6 -0
  230. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts.map +1 -0
  231. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js +350 -0
  232. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js.map +1 -0
  233. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts +28 -0
  234. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts.map +1 -0
  235. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.js +435 -0
  236. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.js.map +1 -0
  237. package/lib/esm/tests/api_tests/security/webhook-timeout.test.d.ts +19 -0
  238. package/lib/esm/tests/api_tests/security/webhook-timeout.test.d.ts.map +1 -0
  239. package/lib/esm/tests/api_tests/security/webhook-timeout.test.js +149 -0
  240. package/lib/esm/tests/api_tests/security/webhook-timeout.test.js.map +1 -0
  241. package/lib/esm/tests/api_tests/webhook_error_handling.test.js +2 -2
  242. package/lib/esm/tests/api_tests/webhook_error_handling.test.js.map +1 -1
  243. package/lib/esm/tests/tests.d.ts.map +1 -1
  244. package/lib/esm/tests/tests.js +36 -24
  245. package/lib/esm/tests/tests.js.map +1 -1
  246. package/lib/esm/tests/unit_tests/openapi_spec_freshness.test.d.ts +1 -1
  247. package/lib/esm/tests/unit_tests/openapi_spec_freshness.test.js +1 -1
  248. package/lib/tsconfig.tsbuildinfo +1 -1
  249. package/package.json +10 -10
  250. package/src/tests/api_tests/auto_merge_form_submission.test.ts +1 -1
  251. package/src/tests/api_tests/enduser_observations_auto_review.test.ts +358 -0
  252. package/src/tests/api_tests/integrations_redacted.test.ts +1 -1
  253. package/src/tests/api_tests/organization_signup.test.ts +2 -2
  254. package/src/tests/api_tests/purchase_made_trigger.test.ts +29 -41
  255. package/src/tests/api_tests/security/{F-0196-add-to-journey-foreign-enduserid.test.ts → add-to-journey-foreign-enduserid.test.ts} +6 -7
  256. package/src/tests/api_tests/security/{F-0005-ai-conversations-rbac.test.ts → ai-conversations-rbac.test.ts} +14 -14
  257. package/src/tests/api_tests/security/{F-0166-allowed-paths-wildcard-bypass.test.ts → allowed-paths-confinement.test.ts} +11 -11
  258. package/src/tests/api_tests/security/{F-0192-automated-actions-process-gate.test.ts → automated-actions-process-gate.test.ts} +6 -7
  259. package/src/tests/api_tests/security/{F-0179-booking-info-idor-token-mint.test.ts → booking-info-idor-token-mint.test.ts} +5 -6
  260. package/src/tests/api_tests/security/{F-0053-cascade-role-rename-cross-tenant.test.ts → cascade-role-rename-cross-tenant.test.ts} +10 -10
  261. package/src/tests/api_tests/security/{F-0001-data-sync-redaction-bypass.test.ts → data-sync-redaction-bypass.test.ts} +9 -9
  262. package/src/tests/api_tests/security/{F-0006-develop-health-benefit-verification-rbac.test.ts → develop-health-benefit-verification-rbac.test.ts} +7 -8
  263. package/src/tests/api_tests/security/{F-0116-F-0119-enduser-cross-create.test.ts → enduser-cross-create.test.ts} +25 -25
  264. package/src/tests/api_tests/security/{F-0106-F-0110-enduser-write-restrictions.test.ts → enduser-write-restrictions.test.ts} +12 -14
  265. package/src/tests/api_tests/security/form-logic-js-execution.test.ts +183 -0
  266. package/src/tests/api_tests/security/{F-0145-globalunique-leak.test.ts → globalunique-conflict-redaction.test.ts} +5 -6
  267. package/src/tests/api_tests/security/{F-0008-handle-incoming-communication-cross-tenant.test.ts → handle-incoming-communication-cross-tenant.test.ts} +8 -8
  268. package/src/tests/api_tests/security/{F-0007-invite-user-enumeration.test.ts → invite-user-enumeration.test.ts} +8 -8
  269. package/src/tests/api_tests/security/{F-0151-load-inbox-redaction.test.ts → load-inbox-redaction.test.ts} +5 -6
  270. package/src/tests/api_tests/security/{F-0016-prototype-pollution.test.ts → prototype-pollution.test.ts} +4 -4
  271. package/src/tests/api_tests/security/{F-0025-proxy-image-unauth-ssrf.test.ts → proxy-image-unauth-ssrf.test.ts} +11 -12
  272. package/src/tests/api_tests/security/{F-0013-sanitize-user-html-with-iframes.test.ts → sanitize-user-html-with-iframes.test.ts} +5 -5
  273. package/src/tests/api_tests/security/{F-0013-sanitize-user-html.test.ts → sanitize-user-html.test.ts} +4 -4
  274. package/src/tests/api_tests/security/{F-0191-schema-adminonly-enforcement.test.ts → schema-adminonly-enforcement.test.ts} +6 -7
  275. package/src/tests/api_tests/security/{F-0076-self-admin-role-assignment.test.ts → self-admin-role-assignment.test.ts} +13 -13
  276. package/src/tests/api_tests/security/{F-0185-startlinktoken-enduser-staff-escalation.test.ts → startlinktoken-enduser-staff-escalation.test.ts} +6 -6
  277. package/src/tests/api_tests/security/{F-0015-webhook-outbound-ssrf.test.ts → webhook-outbound-ssrf.test.ts} +13 -14
  278. package/src/tests/api_tests/security/{F-0155-webhook-timeout.test.ts → webhook-timeout.test.ts} +6 -7
  279. package/src/tests/api_tests/webhook_error_handling.test.ts +1 -1
  280. package/src/tests/tests.ts +41 -24
  281. package/src/tests/unit_tests/openapi_spec_freshness.test.ts +1 -1
  282. package/test_generated.pdf +0 -0
  283. package/src/tests/api_tests/security/readonly-enduser-preview.test.ts +0 -301
@@ -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
  }
@@ -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) {
@@ -24,8 +24,7 @@ type Check = {
24
24
  }
25
25
 
26
26
  /**
27
- * Regression test for F-0191
28
- * (security-audit/findings/F-0191-schema-adminonly-not-enforced.md).
27
+ * Regression test: `adminOnly` custom actions must be enforced at runtime, not merely declared.
29
28
  *
30
29
  * `adminOnly: true` on a CUSTOM action in schema.ts was documentation-only. The runtime gate
31
30
  * (routing.ts:944) reads the flag off the options object built by getCustomEndpointFields, and
@@ -64,7 +63,7 @@ type Check = {
64
63
  * GREEN (post-fix): all six return 401 "Admin access only"; the group-A controls are unchanged.
65
64
  */
66
65
  export const schema_adminonly_enforcement_tests = async ({ sdk } : { sdk: Session, sdkNonAdmin: Session }) => {
67
- log_header("F-0191: schema-declared adminOnly must be enforced on custom actions")
66
+ log_header("schema-declared adminOnly must be enforced on custom actions")
68
67
 
69
68
  const checks: Check[] = []
70
69
  const record = (label: string, pass: boolean, detail: string) => checks.push({ label, pass, detail })
@@ -225,7 +224,7 @@ export const schema_adminonly_enforcement_tests = async ({ sdk } : { sdk: Sessio
225
224
  {
226
225
  label: 'organizations.sync_note_to_canvas',
227
226
  method: 'post', path: '/organizations/sync-note-to-canvas',
228
- data: { enduserId: ABSENT_ID, note: 'F-0191 control' }, // 404 Enduser not found
227
+ data: { enduserId: ABSENT_ID, note: 'control' }, // 404 Enduser not found
229
228
  },
230
229
  {
231
230
  label: 'background_errors.mark_read',
@@ -249,7 +248,7 @@ export const schema_adminonly_enforcement_tests = async ({ sdk } : { sdk: Sessio
249
248
  }
250
249
 
251
250
  /* ===== report: print full table first, then assert (harness exits on first failure) ===== */
252
- console.log('\n F-0191 check summary:')
251
+ console.log('\n check summary:')
253
252
  for (const c of checks) {
254
253
  console.log(` ${c.pass ? 'PASS' : 'FAIL'} ${c.label} — ${c.detail}`)
255
254
  }
@@ -278,11 +277,11 @@ if (require.main === module) {
278
277
 
279
278
  runTests()
280
279
  .then(() => {
281
- console.log("✅ F-0191 schema adminOnly enforcement test suite completed successfully")
280
+ console.log("✅ schema adminOnly enforcement test suite completed successfully")
282
281
  process.exit(0)
283
282
  })
284
283
  .catch((error) => {
285
- console.error("❌ F-0191 schema adminOnly enforcement test suite failed:", error)
284
+ console.error("❌ schema adminOnly enforcement test suite failed:", error)
286
285
  process.exit(1)
287
286
  })
288
287
  }