@tellescope/sdk 1.256.14 → 1.256.16

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 (293) hide show
  1. package/lib/cjs/sdk.d.ts +2 -2
  2. package/lib/cjs/tests/api_tests/auto_merge_form_submission.test.js +1 -1
  3. package/lib/cjs/tests/api_tests/auto_merge_form_submission.test.js.map +1 -1
  4. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.d.ts +5 -0
  5. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.d.ts.map +1 -0
  6. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.js +388 -0
  7. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.js.map +1 -0
  8. package/lib/cjs/tests/api_tests/integrations_redacted.test.js +3 -3
  9. package/lib/cjs/tests/api_tests/integrations_redacted.test.js.map +1 -1
  10. package/lib/cjs/tests/api_tests/organization_signup.test.d.ts +1 -1
  11. package/lib/cjs/tests/api_tests/organization_signup.test.js +1 -1
  12. package/lib/cjs/tests/api_tests/purchase_made_trigger.test.d.ts.map +1 -1
  13. package/lib/cjs/tests/api_tests/purchase_made_trigger.test.js +103 -162
  14. package/lib/cjs/tests/api_tests/purchase_made_trigger.test.js.map +1 -1
  15. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts +33 -0
  16. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts.map +1 -0
  17. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.js +249 -0
  18. package/lib/cjs/tests/api_tests/security/F-0200-form-logic-js-execution.test.js.map +1 -0
  19. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts +42 -0
  20. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -0
  21. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +281 -0
  22. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -0
  23. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.d.ts +38 -0
  24. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.d.ts.map +1 -0
  25. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.js +390 -0
  26. package/lib/cjs/tests/api_tests/security/ai-conversations-rbac.test.js.map +1 -0
  27. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.d.ts +6 -0
  28. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.d.ts.map +1 -0
  29. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.js +1003 -0
  30. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.js.map +1 -0
  31. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.d.ts +42 -0
  32. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.d.ts.map +1 -0
  33. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.js +323 -0
  34. package/lib/cjs/tests/api_tests/security/automated-actions-process-gate.test.js.map +1 -0
  35. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts +29 -0
  36. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts.map +1 -0
  37. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.js +335 -0
  38. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.js.map +1 -0
  39. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts +32 -0
  40. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts.map +1 -0
  41. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js +237 -0
  42. package/lib/cjs/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js.map +1 -0
  43. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts +28 -0
  44. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts.map +1 -0
  45. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.js +349 -0
  46. package/lib/cjs/tests/api_tests/security/data-sync-redaction-bypass.test.js.map +1 -0
  47. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts +30 -0
  48. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts.map +1 -0
  49. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js +314 -0
  50. package/lib/cjs/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js.map +1 -0
  51. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.d.ts +21 -0
  52. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.d.ts.map +1 -0
  53. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.js +362 -0
  54. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.js.map +1 -0
  55. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.d.ts +21 -0
  56. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.d.ts.map +1 -0
  57. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.js +366 -0
  58. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.js.map +1 -0
  59. package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.d.ts +5 -0
  60. package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.d.ts.map +1 -0
  61. package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.js +357 -0
  62. package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.js.map +1 -0
  63. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.d.ts +32 -0
  64. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.d.ts.map +1 -0
  65. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.js +248 -0
  66. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.js.map +1 -0
  67. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts +19 -0
  68. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts.map +1 -0
  69. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.js +138 -0
  70. package/lib/cjs/tests/api_tests/security/globalunique-conflict-redaction.test.js.map +1 -0
  71. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts +24 -0
  72. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
  73. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js +201 -0
  74. package/lib/cjs/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js.map +1 -0
  75. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.d.ts +29 -0
  76. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.d.ts.map +1 -0
  77. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.js +278 -0
  78. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.js.map +1 -0
  79. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.d.ts +17 -0
  80. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.d.ts.map +1 -0
  81. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.js +155 -0
  82. package/lib/cjs/tests/api_tests/security/load-inbox-redaction.test.js.map +1 -0
  83. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.d.ts +2 -0
  84. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.d.ts.map +1 -0
  85. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.js +88 -0
  86. package/lib/cjs/tests/api_tests/security/prototype-pollution.test.js.map +1 -0
  87. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts +34 -0
  88. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts.map +1 -0
  89. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.js +230 -0
  90. package/lib/cjs/tests/api_tests/security/proxy-image-unauth-ssrf.test.js.map +1 -0
  91. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts +2 -0
  92. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts.map +1 -0
  93. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js +242 -0
  94. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js.map +1 -0
  95. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.d.ts +2 -0
  96. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.d.ts.map +1 -0
  97. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.js +148 -0
  98. package/lib/cjs/tests/api_tests/security/sanitize-user-html.test.js.map +1 -0
  99. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts +45 -0
  100. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts.map +1 -0
  101. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.js +388 -0
  102. package/lib/cjs/tests/api_tests/security/schema-adminonly-enforcement.test.js.map +1 -0
  103. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.d.ts +38 -0
  104. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.d.ts.map +1 -0
  105. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.js +222 -0
  106. package/lib/cjs/tests/api_tests/security/self-admin-role-assignment.test.js.map +1 -0
  107. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts +6 -0
  108. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts.map +1 -0
  109. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js +354 -0
  110. package/lib/cjs/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js.map +1 -0
  111. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts +28 -0
  112. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts.map +1 -0
  113. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.js +442 -0
  114. package/lib/cjs/tests/api_tests/security/webhook-outbound-ssrf.test.js.map +1 -0
  115. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.d.ts +19 -0
  116. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.d.ts.map +1 -0
  117. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.js +156 -0
  118. package/lib/cjs/tests/api_tests/security/webhook-timeout.test.js.map +1 -0
  119. package/lib/cjs/tests/api_tests/webhook_error_handling.test.js +2 -2
  120. package/lib/cjs/tests/api_tests/webhook_error_handling.test.js.map +1 -1
  121. package/lib/cjs/tests/tests.d.ts.map +1 -1
  122. package/lib/cjs/tests/tests.js +60 -46
  123. package/lib/cjs/tests/tests.js.map +1 -1
  124. package/lib/cjs/tests/unit_tests/openapi_spec_freshness.test.d.ts +1 -1
  125. package/lib/cjs/tests/unit_tests/openapi_spec_freshness.test.js +1 -1
  126. package/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  127. package/lib/esm/enduser.d.ts +0 -1
  128. package/lib/esm/enduser.d.ts.map +1 -1
  129. package/lib/esm/sdk.d.ts +4 -5
  130. package/lib/esm/sdk.d.ts.map +1 -1
  131. package/lib/esm/session.d.ts +0 -1
  132. package/lib/esm/session.d.ts.map +1 -1
  133. package/lib/esm/tests/api_tests/auto_merge_form_submission.test.js +1 -1
  134. package/lib/esm/tests/api_tests/auto_merge_form_submission.test.js.map +1 -1
  135. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.d.ts +5 -0
  136. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.d.ts.map +1 -0
  137. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.js +383 -0
  138. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.js.map +1 -0
  139. package/lib/esm/tests/api_tests/integrations_redacted.test.js +3 -3
  140. package/lib/esm/tests/api_tests/integrations_redacted.test.js.map +1 -1
  141. package/lib/esm/tests/api_tests/organization_signup.test.d.ts +1 -1
  142. package/lib/esm/tests/api_tests/organization_signup.test.js +1 -1
  143. package/lib/esm/tests/api_tests/purchase_made_trigger.test.d.ts.map +1 -1
  144. package/lib/esm/tests/api_tests/purchase_made_trigger.test.js +104 -163
  145. package/lib/esm/tests/api_tests/purchase_made_trigger.test.js.map +1 -1
  146. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts +33 -0
  147. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.d.ts.map +1 -0
  148. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.js +244 -0
  149. package/lib/esm/tests/api_tests/security/F-0200-form-logic-js-execution.test.js.map +1 -0
  150. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts +42 -0
  151. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -0
  152. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +276 -0
  153. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -0
  154. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.d.ts +38 -0
  155. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.d.ts.map +1 -0
  156. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.js +386 -0
  157. package/lib/esm/tests/api_tests/security/ai-conversations-rbac.test.js.map +1 -0
  158. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.d.ts +6 -0
  159. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.d.ts.map +1 -0
  160. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.js +996 -0
  161. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.js.map +1 -0
  162. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.d.ts +42 -0
  163. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.d.ts.map +1 -0
  164. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.js +316 -0
  165. package/lib/esm/tests/api_tests/security/automated-actions-process-gate.test.js.map +1 -0
  166. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts +29 -0
  167. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.d.ts.map +1 -0
  168. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.js +331 -0
  169. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.js.map +1 -0
  170. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts +32 -0
  171. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.d.ts.map +1 -0
  172. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js +233 -0
  173. package/lib/esm/tests/api_tests/security/cascade-role-rename-cross-tenant.test.js.map +1 -0
  174. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts +28 -0
  175. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.d.ts.map +1 -0
  176. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.js +345 -0
  177. package/lib/esm/tests/api_tests/security/data-sync-redaction-bypass.test.js.map +1 -0
  178. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts +30 -0
  179. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.d.ts.map +1 -0
  180. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js +310 -0
  181. package/lib/esm/tests/api_tests/security/develop-health-benefit-verification-rbac.test.js.map +1 -0
  182. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.d.ts +21 -0
  183. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.d.ts.map +1 -0
  184. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.js +358 -0
  185. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.js.map +1 -0
  186. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.d.ts +21 -0
  187. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.d.ts.map +1 -0
  188. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.js +362 -0
  189. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.js.map +1 -0
  190. package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.d.ts +5 -0
  191. package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.d.ts.map +1 -0
  192. package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.js +349 -0
  193. package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.js.map +1 -0
  194. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.d.ts +32 -0
  195. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.d.ts.map +1 -0
  196. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.js +243 -0
  197. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.js.map +1 -0
  198. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts +19 -0
  199. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.d.ts.map +1 -0
  200. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.js +134 -0
  201. package/lib/esm/tests/api_tests/security/globalunique-conflict-redaction.test.js.map +1 -0
  202. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts +24 -0
  203. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
  204. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js +194 -0
  205. package/lib/esm/tests/api_tests/security/handle-incoming-communication-cross-tenant.test.js.map +1 -0
  206. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.d.ts +29 -0
  207. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.d.ts.map +1 -0
  208. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.js +271 -0
  209. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.js.map +1 -0
  210. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.d.ts +17 -0
  211. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.d.ts.map +1 -0
  212. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.js +151 -0
  213. package/lib/esm/tests/api_tests/security/load-inbox-redaction.test.js.map +1 -0
  214. package/lib/esm/tests/api_tests/security/prototype-pollution.test.d.ts +2 -0
  215. package/lib/esm/tests/api_tests/security/prototype-pollution.test.d.ts.map +1 -0
  216. package/lib/esm/tests/api_tests/security/prototype-pollution.test.js +84 -0
  217. package/lib/esm/tests/api_tests/security/prototype-pollution.test.js.map +1 -0
  218. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts +34 -0
  219. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.d.ts.map +1 -0
  220. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.js +223 -0
  221. package/lib/esm/tests/api_tests/security/proxy-image-unauth-ssrf.test.js.map +1 -0
  222. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts +2 -0
  223. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts.map +1 -0
  224. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.js +238 -0
  225. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.js.map +1 -0
  226. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.d.ts +2 -0
  227. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.d.ts.map +1 -0
  228. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.js +144 -0
  229. package/lib/esm/tests/api_tests/security/sanitize-user-html.test.js.map +1 -0
  230. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts +45 -0
  231. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.d.ts.map +1 -0
  232. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.js +381 -0
  233. package/lib/esm/tests/api_tests/security/schema-adminonly-enforcement.test.js.map +1 -0
  234. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.d.ts +38 -0
  235. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.d.ts.map +1 -0
  236. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.js +218 -0
  237. package/lib/esm/tests/api_tests/security/self-admin-role-assignment.test.js.map +1 -0
  238. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts +6 -0
  239. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.d.ts.map +1 -0
  240. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js +350 -0
  241. package/lib/esm/tests/api_tests/security/startlinktoken-enduser-staff-escalation.test.js.map +1 -0
  242. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts +28 -0
  243. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.d.ts.map +1 -0
  244. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.js +435 -0
  245. package/lib/esm/tests/api_tests/security/webhook-outbound-ssrf.test.js.map +1 -0
  246. package/lib/esm/tests/api_tests/security/webhook-timeout.test.d.ts +19 -0
  247. package/lib/esm/tests/api_tests/security/webhook-timeout.test.d.ts.map +1 -0
  248. package/lib/esm/tests/api_tests/security/webhook-timeout.test.js +149 -0
  249. package/lib/esm/tests/api_tests/security/webhook-timeout.test.js.map +1 -0
  250. package/lib/esm/tests/api_tests/webhook_error_handling.test.js +2 -2
  251. package/lib/esm/tests/api_tests/webhook_error_handling.test.js.map +1 -1
  252. package/lib/esm/tests/tests.d.ts.map +1 -1
  253. package/lib/esm/tests/tests.js +38 -24
  254. package/lib/esm/tests/tests.js.map +1 -1
  255. package/lib/esm/tests/unit_tests/openapi_spec_freshness.test.d.ts +1 -1
  256. package/lib/esm/tests/unit_tests/openapi_spec_freshness.test.js +1 -1
  257. package/lib/tsconfig.tsbuildinfo +1 -1
  258. package/package.json +10 -10
  259. package/src/tests/api_tests/auto_merge_form_submission.test.ts +1 -1
  260. package/src/tests/api_tests/enduser_observations_auto_review.test.ts +358 -0
  261. package/src/tests/api_tests/integrations_redacted.test.ts +1 -1
  262. package/src/tests/api_tests/organization_signup.test.ts +2 -2
  263. package/src/tests/api_tests/purchase_made_trigger.test.ts +29 -41
  264. package/src/tests/api_tests/security/{F-0196-add-to-journey-foreign-enduserid.test.ts → add-to-journey-foreign-enduserid.test.ts} +6 -7
  265. package/src/tests/api_tests/security/{F-0005-ai-conversations-rbac.test.ts → ai-conversations-rbac.test.ts} +14 -14
  266. package/src/tests/api_tests/security/{F-0166-allowed-paths-wildcard-bypass.test.ts → allowed-paths-confinement.test.ts} +11 -11
  267. package/src/tests/api_tests/security/{F-0192-automated-actions-process-gate.test.ts → automated-actions-process-gate.test.ts} +6 -7
  268. package/src/tests/api_tests/security/{F-0179-booking-info-idor-token-mint.test.ts → booking-info-idor-token-mint.test.ts} +5 -6
  269. package/src/tests/api_tests/security/{F-0053-cascade-role-rename-cross-tenant.test.ts → cascade-role-rename-cross-tenant.test.ts} +10 -10
  270. package/src/tests/api_tests/security/{F-0001-data-sync-redaction-bypass.test.ts → data-sync-redaction-bypass.test.ts} +9 -9
  271. package/src/tests/api_tests/security/{F-0006-develop-health-benefit-verification-rbac.test.ts → develop-health-benefit-verification-rbac.test.ts} +7 -8
  272. package/src/tests/api_tests/security/{F-0116-F-0119-enduser-cross-create.test.ts → enduser-cross-create.test.ts} +25 -25
  273. package/src/tests/api_tests/security/{F-0106-F-0110-enduser-write-restrictions.test.ts → enduser-write-restrictions.test.ts} +12 -14
  274. package/src/tests/api_tests/security/file-link-session-confinement.test.ts +291 -0
  275. package/src/tests/api_tests/security/form-logic-js-execution.test.ts +183 -0
  276. package/src/tests/api_tests/security/{F-0145-globalunique-leak.test.ts → globalunique-conflict-redaction.test.ts} +5 -6
  277. package/src/tests/api_tests/security/{F-0008-handle-incoming-communication-cross-tenant.test.ts → handle-incoming-communication-cross-tenant.test.ts} +8 -8
  278. package/src/tests/api_tests/security/{F-0007-invite-user-enumeration.test.ts → invite-user-enumeration.test.ts} +8 -8
  279. package/src/tests/api_tests/security/{F-0151-load-inbox-redaction.test.ts → load-inbox-redaction.test.ts} +5 -6
  280. package/src/tests/api_tests/security/{F-0016-prototype-pollution.test.ts → prototype-pollution.test.ts} +4 -4
  281. package/src/tests/api_tests/security/{F-0025-proxy-image-unauth-ssrf.test.ts → proxy-image-unauth-ssrf.test.ts} +11 -12
  282. package/src/tests/api_tests/security/{F-0013-sanitize-user-html-with-iframes.test.ts → sanitize-user-html-with-iframes.test.ts} +5 -5
  283. package/src/tests/api_tests/security/{F-0013-sanitize-user-html.test.ts → sanitize-user-html.test.ts} +4 -4
  284. package/src/tests/api_tests/security/{F-0191-schema-adminonly-enforcement.test.ts → schema-adminonly-enforcement.test.ts} +6 -7
  285. package/src/tests/api_tests/security/{F-0076-self-admin-role-assignment.test.ts → self-admin-role-assignment.test.ts} +13 -13
  286. package/src/tests/api_tests/security/{F-0185-startlinktoken-enduser-staff-escalation.test.ts → startlinktoken-enduser-staff-escalation.test.ts} +6 -6
  287. package/src/tests/api_tests/security/{F-0015-webhook-outbound-ssrf.test.ts → webhook-outbound-ssrf.test.ts} +13 -14
  288. package/src/tests/api_tests/security/{F-0155-webhook-timeout.test.ts → webhook-timeout.test.ts} +6 -7
  289. package/src/tests/api_tests/webhook_error_handling.test.ts +1 -1
  290. package/src/tests/tests.ts +43 -24
  291. package/src/tests/unit_tests/openapi_spec_freshness.test.ts +1 -1
  292. package/test_generated.pdf +0 -0
  293. package/src/tests/api_tests/security/readonly-enduser-preview.test.ts +0 -301
@@ -112,33 +112,34 @@ import { nutrition_tracking_tests } from "./api_tests/nutrition_tracking.test";
112
112
  import { no_access_permission_checks_tests } from "./api_tests/no_access_permission_checks.test";
113
113
  import { resource_access_tags_tests } from "./api_tests/resource_access_tags.test";
114
114
  import { field_redaction_tests } from "./api_tests/field_redaction.test";
115
- import { data_sync_redaction_bypass_tests } from "./api_tests/security/F-0001-data-sync-redaction-bypass.test";
116
- import { enduser_write_restrictions_tests } from "./api_tests/security/F-0106-F-0110-enduser-write-restrictions.test";
117
- import { ai_conversations_rbac_tests } from "./api_tests/security/F-0005-ai-conversations-rbac.test";
118
- import { develop_health_benefit_verification_rbac_tests } from "./api_tests/security/F-0006-develop-health-benefit-verification-rbac.test";
119
- import { cascade_role_rename_cross_tenant_tests } from "./api_tests/security/F-0053-cascade-role-rename-cross-tenant.test";
120
- import { self_admin_role_assignment_tests } from "./api_tests/security/F-0076-self-admin-role-assignment.test";
121
- import { invite_user_enumeration_tests } from "./api_tests/security/F-0007-invite-user-enumeration.test";
115
+ import { data_sync_redaction_bypass_tests } from "./api_tests/security/data-sync-redaction-bypass.test";
116
+ import { enduser_write_restrictions_tests } from "./api_tests/security/enduser-write-restrictions.test";
117
+ import { ai_conversations_rbac_tests } from "./api_tests/security/ai-conversations-rbac.test";
118
+ import { develop_health_benefit_verification_rbac_tests } from "./api_tests/security/develop-health-benefit-verification-rbac.test";
119
+ import { cascade_role_rename_cross_tenant_tests } from "./api_tests/security/cascade-role-rename-cross-tenant.test";
120
+ import { self_admin_role_assignment_tests } from "./api_tests/security/self-admin-role-assignment.test";
121
+ import { invite_user_enumeration_tests } from "./api_tests/security/invite-user-enumeration.test";
122
122
  import { register_business_id_injection_tests } from "./api_tests/security/register_business_id_injection.test";
123
- import { handle_incoming_communication_cross_tenant_tests } from "./api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test";
124
- import { sanitize_user_html_xss_tests } from "./api_tests/security/F-0013-sanitize-user-html.test";
125
- import { sanitize_user_html_with_iframes_tests } from "./api_tests/security/F-0013-sanitize-user-html-with-iframes.test";
126
- import { prototype_pollution_tests } from "./api_tests/security/F-0016-prototype-pollution.test";
127
- import { enduser_cross_create_tests } from "./api_tests/security/F-0116-F-0119-enduser-cross-create.test";
128
- import { globalunique_leak_tests } from "./api_tests/security/F-0145-globalunique-leak.test";
129
- import { load_inbox_redaction_tests } from "./api_tests/security/F-0151-load-inbox-redaction.test";
123
+ import { handle_incoming_communication_cross_tenant_tests } from "./api_tests/security/handle-incoming-communication-cross-tenant.test";
124
+ import { sanitize_user_html_xss_tests } from "./api_tests/security/sanitize-user-html.test";
125
+ import { sanitize_user_html_with_iframes_tests } from "./api_tests/security/sanitize-user-html-with-iframes.test";
126
+ import { prototype_pollution_tests } from "./api_tests/security/prototype-pollution.test";
127
+ import { enduser_cross_create_tests } from "./api_tests/security/enduser-cross-create.test";
128
+ import { globalunique_leak_tests } from "./api_tests/security/globalunique-conflict-redaction.test";
129
+ import { load_inbox_redaction_tests } from "./api_tests/security/load-inbox-redaction.test";
130
130
  import { suggested_reply_redaction_tests } from "./api_tests/security/suggested-reply-redaction.test";
131
- import { webhook_timeout_tests } from "./api_tests/security/F-0155-webhook-timeout.test";
131
+ import { webhook_timeout_tests } from "./api_tests/security/webhook-timeout.test";
132
132
  import { enduser_ai_summary_trust_gate_tests } from "./api_tests/security/enduser-ai-summary-trust-gate.test";
133
- import { allowed_paths_confinement_tests } from "./api_tests/security/F-0166-allowed-paths-wildcard-bypass.test";
134
- import { proxy_image_ssrf_tests } from "./api_tests/security/F-0025-proxy-image-unauth-ssrf.test";
135
- import { webhook_outbound_ssrf_tests } from "./api_tests/security/F-0015-webhook-outbound-ssrf.test";
133
+ import { allowed_paths_confinement_tests } from "./api_tests/security/allowed-paths-confinement.test";
134
+ import { proxy_image_ssrf_tests } from "./api_tests/security/proxy-image-unauth-ssrf.test";
135
+ import { webhook_outbound_ssrf_tests } from "./api_tests/security/webhook-outbound-ssrf.test";
136
136
  import { public_endpoint_auth_field_lock_tests } from "./api_tests/security/public_endpoint_auth_field_lock.test";
137
137
  import { formsort_webhook_auth_field_lock_tests } from "./api_tests/security/formsort_webhook_auth_field_lock.test";
138
- import { booking_info_idor_tests } from "./api_tests/security/F-0179-booking-info-idor-token-mint.test";
139
- import { automated_actions_process_gate_tests } from "./api_tests/security/F-0192-automated-actions-process-gate.test";
140
- import { schema_adminonly_enforcement_tests } from "./api_tests/security/F-0191-schema-adminonly-enforcement.test";
141
- import { startlinktoken_escalation_tests } from "./api_tests/security/F-0185-startlinktoken-enduser-staff-escalation.test";
138
+ import { booking_info_idor_tests } from "./api_tests/security/booking-info-idor-token-mint.test";
139
+ import { automated_actions_process_gate_tests } from "./api_tests/security/automated-actions-process-gate.test";
140
+ import { schema_adminonly_enforcement_tests } from "./api_tests/security/schema-adminonly-enforcement.test";
141
+ import { startlinktoken_escalation_tests } from "./api_tests/security/startlinktoken-enduser-staff-escalation.test";
142
+ import { form_logic_js_execution_checks } from "./api_tests/security/form-logic-js-execution.test";
142
143
  import { bulk_assignment_tests } from "./api_tests/bulk_assignment.test";
143
144
  import { tickets_bulk_assign_care_team_tests } from "./api_tests/tickets_bulk_assign_care_team.test";
144
145
  import { managed_content_enduser_access_tests } from "./api_tests/managed_content_enduser_access.test";
@@ -159,8 +160,10 @@ import { phone_validation_unit_tests } from "./unit_tests/phone_validation.test"
159
160
  import { openapi_spec_freshness_unit_tests } from "./unit_tests/openapi_spec_freshness.test";
160
161
  import { do_not_send_address_unit_tests } from "./unit_tests/do_not_send_address.test";
161
162
  import { organization_signup_checks } from "./api_tests/organization_signup.test";
162
- import { add_to_journey_foreign_enduserid_checks } from "./api_tests/security/F-0196-add-to-journey-foreign-enduserid.test";
163
+ import { add_to_journey_foreign_enduserid_checks } from "./api_tests/security/add-to-journey-foreign-enduserid.test";
163
164
  import { tickets_bulk_assign_from_queue_checks } from "./api_tests/tickets_bulk_assign_from_queue.test";
165
+ import { enduser_observations_auto_review_checks } from "./api_tests/enduser_observations_auto_review.test";
166
+ import { file_link_session_confinement_checks } from "./api_tests/security/file-link-session-confinement.test";
164
167
  import { run_isolated_in_parallel } from "./setup_isolated";
165
168
  import { elation_user_id_tests } from "./api_tests/elation_user_id.test";
166
169
  import { organization_settings_duplicates_tests } from "./api_tests/organization_settings_duplicates.test";
@@ -10903,6 +10906,19 @@ export const form_conditional_logic_tests = async () => {
10903
10906
  run_conditional_form_test({ $and: [{ condition: { [FORM_LOGIC_CALCULATED_FIELDS[0]]: { $exists: true } } }] }, true)
10904
10907
  run_conditional_form_test({ $and: [{ condition: { [FORM_LOGIC_CALCULATED_FIELDS[0]]: { $gt: 25 } } }] }, true)
10905
10908
  run_conditional_form_test({ $and: [{ condition: { [FORM_LOGIC_CALCULATED_FIELDS[0]]: { $lt: 25 } } }] }, false)
10909
+
10910
+ // A $JS(...) condition value was previously compiled and executed with new Function().
10911
+ // These must evaluate to false (parseInt -> NaN -> no match), and must never be executed.
10912
+ // The values are typed `number` on BasicFilter but are strings in stored data, hence the casts.
10913
+ delete (globalThis as any).__F0200
10914
+ run_conditional_form_test({ $and: [{ condition: { '3': { $gt: '$JS(return 0)' as any } } }] }, false, '$gt $JS not evaluated')
10915
+ run_conditional_form_test({ $and: [{ condition: { '3': { $lt: '$JS(return 99999)' as any } } }] }, false, '$lt $JS not evaluated')
10916
+ run_conditional_form_test({ $and: [{ condition: { '3': { $gt: '$JS(globalThis.__F0200 = 1; return 0)' as any } } }] }, false, '$JS side effect not evaluated')
10917
+ assert(
10918
+ (globalThis as any).__F0200 === undefined,
10919
+ 'a $JS(...) condition value was executed',
10920
+ '$JS payload never executed',
10921
+ )
10906
10922
  }
10907
10923
 
10908
10924
  export const enduser_conditional_logic_tests = async () => {
@@ -15386,8 +15402,11 @@ const ip_address_form_tests = async () => {
15386
15402
  // process.exit, which would otherwise strand the other suite's tenants.
15387
15403
  await run_isolated_in_parallel([
15388
15404
  { name: 'Organization signup', run: organization_signup_checks },
15389
- { name: 'F-0196 add_to_journey foreign enduserId', run: add_to_journey_foreign_enduserid_checks },
15405
+ { name: 'add_to_journey foreign enduserId', run: add_to_journey_foreign_enduserid_checks },
15390
15406
  { name: 'Tickets bulk assign from queue', run: tickets_bulk_assign_from_queue_checks },
15407
+ { name: 'Vital auto-review on create', run: enduser_observations_auto_review_checks },
15408
+ { name: '$JS in stored conditional logic', run: form_logic_js_execution_checks },
15409
+ { name: 'Shared file link session confinement', run: file_link_session_confinement_checks },
15391
15410
  ])
15392
15411
  await embeddables_auth_token_tests({ sdk, sdkNonAdmin })
15393
15412
  await proxy_image_ssrf_tests({ sdk, sdkNonAdmin })
@@ -17,7 +17,7 @@ import {
17
17
  * .npmignore covers only set_vars.sh), but nothing in the build or CI regenerates it. It had
18
18
  * therefore drifted several commits behind schema.ts — which mattered because `adminOnly` is
19
19
  * rendered into the spec as an "**Admin only.**" description prefix, so the published docs were
20
- * advertising gates that had changed. That drift is the doc half of F-0191; the runtime half was
20
+ * advertising gates that had changed. That drift is the documentation half of the problem; the runtime half was
21
21
  * fixed by making getCustomEndpointFields fall back to the schema flag.
22
22
  *
23
23
  * The generator is byte-deterministic (date `getExample`s are pinned in validation.ts precisely so
Binary file
@@ -1,301 +0,0 @@
1
- require('source-map-support').install();
2
-
3
- import axios from "axios"
4
-
5
- import { Session, EnduserSession } from "../../../sdk"
6
- import {
7
- assert,
8
- log_header,
9
- } from "@tellescope/testing"
10
- import { PROVIDER_PERMISSIONS, NO_ACCESS } 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 READ_ONLY = { create: NO_ACCESS, read: ALL, update: NO_ACCESS, delete: NO_ACCESS }
19
- const FULL_ACCESS = { create: ALL, read: ALL, update: ALL, delete: ALL }
20
- const ASSIGNED_UPDATE = { create: NO_ACCESS, read: ALL, update: 'Assigned' as const, delete: NO_ACCESS }
21
-
22
- const PORTAL_PREVIEW_SCOPE = 'portal-preview'
23
-
24
- type ProbeMethod = 'get' | 'post' | 'patch' | 'put' | 'delete'
25
-
26
- // A single collected check. Everything is gathered first and asserted at the end, because the
27
- // testing harness exits the process on the first failed assert — collecting first means a RED run
28
- // prints the full evidence table before the first vulnerability assert trips the exit.
29
- type Check = {
30
- label: string,
31
- pass: boolean,
32
- detail: string,
33
- }
34
-
35
- /**
36
- * Regression test for F-0138
37
- * (security-audit/findings/F-0138-endusers-generate-auth-token-no-admin-gate.md).
38
- *
39
- * `endusers.generate_auth_token` (the "View portal as patient" preview flow) requires only
40
- * `endusers.read`, yet mints a FULLY-PRIVILEGED enduser session. A staff user who cannot update a
41
- * patient can therefore act AS that patient: edit the record, submit forms, send chats, book
42
- * appointments, even set the portal password.
43
- *
44
- * The fix mints the preview token with `sessionScopes: ['portal-preview']` whenever the calling
45
- * staff user lacks update access to that specific enduser (record-level, honoring `Assigned`
46
- * scoping). The scope's allowlist (api/modules/session_scopes.ts) grants exactly the portal's read
47
- * surface plus session maintenance; every write path 403s via existing path confinement.
48
- *
49
- * RED (pre-fix): section A fails — the response carries no sessionScopes and every write in A2
50
- * SUCCEEDS. Sections D/E (controls) pass pre-fix. GREEN (post-fix): all sections pass.
51
- *
52
- * Probes use raw axios rather than the SDK: parseError (sdk/src/session.ts) discards the status
53
- * code, and a path-confinement denial (403 "Inaccessible") is byte-identical in message to a
54
- * permissions denial. Write/blocked-read probes additionally confirm an UNCONFINED enduser token
55
- * gets a non-403 on the same path in the same run, so a 403 can only be confinement, never bad
56
- * permissions or a bad body.
57
- */
58
- export const readonly_enduser_preview_tests = async ({ sdk } : { sdk: Session, sdkNonAdmin: Session }) => {
59
- log_header("F-0138: portal-preview scope for read-only staff generate_auth_token")
60
-
61
- const checks: Check[] = []
62
- const record = (label: string, pass: boolean, detail: string) => checks.push({ label, pass, detail })
63
-
64
- const request = async (token: string, method: ProbeMethod, path: string, data?: any) => {
65
- const r = await axios.request({
66
- method,
67
- url: `${host}/v1${path}`,
68
- ...method === 'get' ? { params: data } : { data },
69
- headers: { Authorization: `Bearer ${token}` },
70
- validateStatus: () => true,
71
- })
72
- return { status: r.status, body: r.data }
73
- }
74
-
75
- const isPathDenial = (r: { status: number, body: any }) => (
76
- r.status === 403 && r.body?.message === 'Inaccessible'
77
- )
78
-
79
- // The confined token must be denied `path` by confinement, while an unconfined baseline is not.
80
- const expectDenied = async (
81
- label: string, confinedToken: string, baselineToken: string,
82
- method: ProbeMethod, path: string, data?: any,
83
- ) => {
84
- const baseline = await request(baselineToken, method, path, data)
85
- const confined = await request(confinedToken, method, path, data)
86
- const badProbe = baseline.status === 403
87
- record(
88
- label,
89
- !badProbe && isPathDenial(confined),
90
- `${method}:${path} confined=${confined.status} baseline=${baseline.status}` + (badProbe ? ' BAD PROBE: baseline also 403' : ''),
91
- )
92
- }
93
-
94
- // The path must not be blocked by confinement (neither 403 nor 401).
95
- const expectAllowed = async (
96
- label: string, token: string, method: ProbeMethod, path: string, data?: any,
97
- ) => {
98
- const r = await request(token, method, path, data)
99
- record(label, r.status !== 403 && r.status !== 401, `${method}:${path} status=${r.status}`)
100
- }
101
-
102
- const hasScope = (enduser: any) => !!enduser?.sessionScopes?.includes?.(PORTAL_PREVIEW_SCOPE)
103
-
104
- const readonlyRole = `f0138-readonly-${RAND()}`
105
- const fullUpdateRole = `f0138-full-${RAND()}`
106
- const assignedUpdateRole = `f0138-assigned-${RAND()}`
107
- const roleIds: string[] = []
108
- const userIds: string[] = []
109
- const enduserIds: string[] = []
110
-
111
- try {
112
- /* ================= fixtures ================= */
113
-
114
- for (const [role, endusersPerm] of [
115
- [readonlyRole, READ_ONLY],
116
- [fullUpdateRole, FULL_ACCESS],
117
- [assignedUpdateRole, ASSIGNED_UPDATE],
118
- ] as const) {
119
- const rbap = await sdk.api.role_based_access_permissions.createOne({
120
- role,
121
- permissions: { ...PROVIDER_PERMISSIONS, endusers: endusersPerm },
122
- } as any)
123
- roleIds.push(rbap.id)
124
- }
125
-
126
- // Throwaway staff users. verifiedEmail must be set at create (rejected on update).
127
- const mkUser = async (role: string) => {
128
- const u = await sdk.api.users.createOne({
129
- email: `f0138-${role}-${RAND()}@tellescope.example`,
130
- fname: 'F0138', lname: 'Staff',
131
- verifiedEmail: true,
132
- notificationEmailsDisabled: true,
133
- roles: [role],
134
- } as any)
135
- userIds.push(u.id)
136
- return u
137
- }
138
- const readonlyUser = await mkUser(readonlyRole)
139
- const fullUpdateUser = await mkUser(fullUpdateRole)
140
- const assignedUpdateUser = await mkUser(assignedUpdateRole)
141
-
142
- // Staff sessions from admin-minted tokens (avoids the password / login-rate-limit dance).
143
- const staffSession = async (userId: string) => {
144
- const { authToken } = await sdk.api.users.generate_auth_token({ id: userId })
145
- return new Session({ host, authToken })
146
- }
147
- const readonlyStaff = await staffSession(readonlyUser.id)
148
- const fullUpdateStaff = await staffSession(fullUpdateUser.id)
149
- const assignedUpdateStaff = await staffSession(assignedUpdateUser.id)
150
-
151
- // Endusers: unassigned patient, a bystander, and one assigned to the assigned-update user.
152
- const enduser = await sdk.api.endusers.createOne({
153
- email: `f0138-patient-${RAND()}@tellescope.example`, fname: 'F0138', lname: 'Patient',
154
- })
155
- enduserIds.push(enduser.id)
156
- const assignedEnduser = await sdk.api.endusers.createOne({
157
- email: `f0138-assigned-${RAND()}@tellescope.example`, fname: 'F0138', lname: 'Assigned',
158
- assignedTo: [assignedUpdateUser.id],
159
- } as any)
160
- enduserIds.push(assignedEnduser.id)
161
-
162
- // A form_response the patient owns, for the submit-form-response write probe.
163
- const form = await sdk.api.forms.createOne({ title: `F-0138 preview form ${RAND()}` })
164
- const { response: formResponse } = await sdk.api.form_responses.prepare_form_response({
165
- formId: form.id, enduserId: enduser.id,
166
- })
167
-
168
- /* ===== A1: read-only staff mints a scoped preview token ===== */
169
-
170
- const previewMint = await readonlyStaff.api.endusers.generate_auth_token({ id: enduser.id })
171
- const previewToken = previewMint.authToken
172
- record('A1: read-only staff receives an authToken', !!previewToken, `authToken present=${!!previewToken}`)
173
- record(
174
- 'A1: read-only staff mint is scoped to portal-preview',
175
- hasScope(previewMint.enduser),
176
- `sessionScopes=${JSON.stringify((previewMint.enduser as any)?.sessionScopes)} (F-0138 vuln if absent)`,
177
- )
178
- record(
179
- 'A1(E): scoped preview token carries denySocket',
180
- (previewMint.enduser as any)?.denySocket === true,
181
- `denySocket=${(previewMint.enduser as any)?.denySocket}`,
182
- )
183
-
184
- // Unconfined enduser baseline (admin-minted) — proves the scoped token's 403s are confinement.
185
- const { authToken: baselineEnduserToken } = await sdk.api.endusers.generate_auth_token({ id: enduser.id })
186
-
187
- /* ===== A2: writes blocked for the scoped session ===== */
188
-
189
- await expectDenied('A2: cannot self-update the patient record', previewToken, baselineEnduserToken,
190
- 'patch', `/enduser/${enduser.id}`, { updates: { fname: 'Hacked' } })
191
- await expectDenied('A2: cannot set the patient portal password', previewToken, baselineEnduserToken,
192
- 'post', '/set-enduser-password', { id: enduser.id, password: `F0138Pw!${RAND()}` })
193
- await expectDenied('A2: cannot send a chat as the patient', previewToken, baselineEnduserToken,
194
- 'post', '/chat', { message: 'hi from preview' })
195
- await expectDenied('A2: cannot submit a form as the patient', previewToken, baselineEnduserToken,
196
- 'patch', '/submit-form-response', { id: formResponse.id, responses: [] })
197
- await expectDenied('A2: cannot book an appointment as the patient', previewToken, baselineEnduserToken,
198
- 'post', '/book-appointment', {})
199
- await expectDenied('A2: cannot start a file upload as the patient', previewToken, baselineEnduserToken,
200
- 'post', '/prepare-file-upload', { name: 'x.pdf', type: 'application/pdf', enduserId: enduser.id })
201
-
202
- /* ===== B: no laundering via refresh ===== */
203
-
204
- const refreshed = await request(previewToken, 'post', '/refresh-enduser-session', {})
205
- const refreshedToken = refreshed.body?.authToken as string | undefined
206
- record('B: refresh succeeds', refreshed.status === 200 && !!refreshedToken, `status=${refreshed.status} token=${!!refreshedToken}`)
207
- record(
208
- 'B: refreshed session still carries portal-preview scope',
209
- hasScope(refreshed.body?.enduser),
210
- `sessionScopes=${JSON.stringify(refreshed.body?.enduser?.sessionScopes)} (laundering if absent)`,
211
- )
212
- if (refreshedToken) {
213
- await expectDenied('B: refreshed token still cannot write', refreshedToken, baselineEnduserToken,
214
- 'patch', `/enduser/${enduser.id}`, { updates: { fname: 'HackedAfterRefresh' } })
215
- }
216
- await expectAllowed('B: logout allowed', previewToken, 'post', '/logout-enduser')
217
-
218
- /* ===== C: ungranted mutating "reads" blocked ===== */
219
-
220
- // Re-mint (the previous token was just logged out).
221
- const cMint = await readonlyStaff.api.endusers.generate_auth_token({ id: enduser.id })
222
- const cToken = cMint.authToken
223
- await expectDenied('C: proxy_read blocked', cToken, baselineEnduserToken,
224
- 'get', '/integrations/proxy-read', { integration: 'Stripe', type: 'subscriptions' })
225
- await expectDenied('C: booking_info (mints a token) blocked', cToken, baselineEnduserToken,
226
- 'get', '/form-fields/booking-info', { bookingPageId: 'x' })
227
- await expectDenied('C: form_responses stripe_details blocked', cToken, baselineEnduserToken,
228
- 'get', '/form-responses/stripe-details', {})
229
- await expectDenied('C: products stripe-portal-session blocked', cToken, baselineEnduserToken,
230
- 'get', '/products/stripe-portal-session', {})
231
-
232
- /* ===== D: granted portal reads still work ===== */
233
-
234
- await expectAllowed('D: portal-customizations', cToken, 'get', '/portal-customizations')
235
- await expectAllowed('D: calendar-events', cToken, 'get', '/calendar-events')
236
- await expectAllowed('D: my-meetings', cToken, 'get', '/my-meetings')
237
- await expectAllowed('D: chat-rooms', cToken, 'get', '/chat-rooms')
238
- await expectAllowed('D: care-plans', cToken, 'get', '/care-plans')
239
- await expectAllowed('D: form-responses', cToken, 'get', '/form-responses')
240
- await expectAllowed('D: self enduser read', cToken, 'get', `/enduser/${enduser.id}`)
241
- await expectAllowed('D: file-download-URL', cToken, 'get', '/file-download-URL', { secureName: 'nonexistent' })
242
- await expectAllowed('D: enduser-session-info', cToken, 'get', '/enduser-session-info')
243
-
244
- /* ===== E: zero behavior change controls ===== */
245
-
246
- const adminMint = await sdk.api.endusers.generate_auth_token({ id: enduser.id })
247
- record('E: admin-minted token is NOT scoped', !hasScope(adminMint.enduser),
248
- `sessionScopes=${JSON.stringify((adminMint.enduser as any)?.sessionScopes)}`)
249
- await expectAllowed('E: admin-minted token can write', adminMint.authToken, 'patch',
250
- `/enduser/${enduser.id}`, { updates: { fname: 'AdminEditOk' } })
251
-
252
- const fullMint = await fullUpdateStaff.api.endusers.generate_auth_token({ id: enduser.id })
253
- record('E: update:All staff mints an UNSCOPED token', !hasScope(fullMint.enduser),
254
- `sessionScopes=${JSON.stringify((fullMint.enduser as any)?.sessionScopes)}`)
255
-
256
- const assignedMint = await assignedUpdateStaff.api.endusers.generate_auth_token({ id: assignedEnduser.id })
257
- record('E: assigned-update staff UNSCOPED for an assigned patient', !hasScope(assignedMint.enduser),
258
- `sessionScopes=${JSON.stringify((assignedMint.enduser as any)?.sessionScopes)}`)
259
-
260
- const assignedMintUnassigned = await assignedUpdateStaff.api.endusers.generate_auth_token({ id: enduser.id })
261
- record('E: assigned-update staff SCOPED for an unassigned patient', hasScope(assignedMintUnassigned.enduser),
262
- `sessionScopes=${JSON.stringify((assignedMintUnassigned.enduser as any)?.sessionScopes)}`)
263
-
264
- /* ===== report: print full table first, then assert (harness exits on first failure) ===== */
265
- console.log('\n F-0138 check summary:')
266
- for (const c of checks) {
267
- console.log(` ${c.pass ? 'PASS' : 'FAIL'} ${c.label} — ${c.detail}`)
268
- }
269
- console.log('')
270
-
271
- for (const c of checks) {
272
- assert(c.pass, `${c.label} — ${c.detail}`, c.label)
273
- }
274
- } finally {
275
- for (const id of enduserIds) { try { await sdk.api.endusers.deleteOne(id) } catch {} }
276
- for (const id of userIds) { try { await sdk.api.users.deleteOne(id) } catch {} }
277
- for (const id of roleIds) { try { await sdk.api.role_based_access_permissions.deleteOne(id) } catch {} }
278
- }
279
- }
280
-
281
- // Allow running this test file independently
282
- if (require.main === module) {
283
- console.log(`🌐 Using API URL: ${host}`)
284
- const sdk = new Session({ host })
285
- const sdkNonAdmin = new Session({ host })
286
-
287
- const runTests = async () => {
288
- await setup_tests(sdk, sdkNonAdmin)
289
- await readonly_enduser_preview_tests({ sdk, sdkNonAdmin })
290
- }
291
-
292
- runTests()
293
- .then(() => {
294
- console.log("✅ F-0138 portal-preview scope test suite completed successfully")
295
- process.exit(0)
296
- })
297
- .catch((error) => {
298
- console.error("❌ F-0138 portal-preview scope test suite failed:", error)
299
- process.exit(1)
300
- })
301
- }