@tellescope/sdk 1.256.16 → 2.0.0-beta.1

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 (310) hide show
  1. package/CLAUDE.md +5 -0
  2. package/env.example +39 -0
  3. package/lib/cjs/enduser.d.ts +1 -0
  4. package/lib/cjs/enduser.d.ts.map +1 -1
  5. package/lib/cjs/sdk.d.ts +6 -1
  6. package/lib/cjs/sdk.d.ts.map +1 -1
  7. package/lib/cjs/sdk.js +2 -0
  8. package/lib/cjs/sdk.js.map +1 -1
  9. package/lib/cjs/session.d.ts +1 -0
  10. package/lib/cjs/session.d.ts.map +1 -1
  11. package/lib/cjs/tests/api_tests/active_patient_count.test.js +1 -1
  12. package/lib/cjs/tests/api_tests/active_patient_count.test.js.map +1 -1
  13. package/lib/cjs/tests/api_tests/appointment_rescheduled_trigger.test.js +1 -1
  14. package/lib/cjs/tests/api_tests/appointment_rescheduled_trigger.test.js.map +1 -1
  15. package/lib/cjs/tests/api_tests/calendar_event_limits.test.js +5 -5
  16. package/lib/cjs/tests/api_tests/calendar_event_limits.test.js.map +1 -1
  17. package/lib/cjs/tests/api_tests/calendar_event_references_update.test.js +1 -1
  18. package/lib/cjs/tests/api_tests/calendar_event_references_update.test.js.map +1 -1
  19. package/lib/cjs/tests/api_tests/enduser_cross_access_isolation.test.js +1 -1
  20. package/lib/cjs/tests/api_tests/enduser_cross_access_isolation.test.js.map +1 -1
  21. package/lib/cjs/tests/api_tests/enduser_fields_sync.test.d.ts +21 -0
  22. package/lib/cjs/tests/api_tests/enduser_fields_sync.test.d.ts.map +1 -0
  23. package/lib/cjs/tests/api_tests/enduser_fields_sync.test.js +215 -0
  24. package/lib/cjs/tests/api_tests/enduser_fields_sync.test.js.map +1 -0
  25. package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.js +6 -6
  26. package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.js.map +1 -1
  27. package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.js +3 -3
  28. package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.js.map +1 -1
  29. package/lib/cjs/tests/api_tests/load_threads_care_team.test.d.ts +32 -0
  30. package/lib/cjs/tests/api_tests/load_threads_care_team.test.d.ts.map +1 -0
  31. package/lib/cjs/tests/api_tests/load_threads_care_team.test.js +257 -0
  32. package/lib/cjs/tests/api_tests/load_threads_care_team.test.js.map +1 -0
  33. package/lib/cjs/tests/api_tests/managed_content_enduser_access.test.js +1 -1
  34. package/lib/cjs/tests/api_tests/managed_content_enduser_access.test.js.map +1 -1
  35. package/lib/cjs/tests/api_tests/managed_content_file_access.test.js +1 -1
  36. package/lib/cjs/tests/api_tests/managed_content_file_access.test.js.map +1 -1
  37. package/lib/cjs/tests/api_tests/mdi_case_offerings.test.d.ts.map +1 -1
  38. package/lib/cjs/tests/api_tests/mdi_case_offerings.test.js +139 -9
  39. package/lib/cjs/tests/api_tests/mdi_case_offerings.test.js.map +1 -1
  40. package/lib/cjs/tests/api_tests/mdi_webhooks.test.d.ts.map +1 -1
  41. package/lib/cjs/tests/api_tests/mdi_webhooks.test.js +21 -8
  42. package/lib/cjs/tests/api_tests/mdi_webhooks.test.js.map +1 -1
  43. package/lib/cjs/tests/api_tests/nutrition_tracking.test.js +1 -1
  44. package/lib/cjs/tests/api_tests/nutrition_tracking.test.js.map +1 -1
  45. package/lib/cjs/tests/api_tests/openloop_webhooks.test.js +1 -1
  46. package/lib/cjs/tests/api_tests/openloop_webhooks.test.js.map +1 -1
  47. package/lib/cjs/tests/api_tests/programs.test.d.ts +5 -0
  48. package/lib/cjs/tests/api_tests/programs.test.d.ts.map +1 -0
  49. package/lib/cjs/tests/api_tests/programs.test.js +370 -0
  50. package/lib/cjs/tests/api_tests/programs.test.js.map +1 -0
  51. package/lib/cjs/tests/api_tests/programs_trigger_filters.test.d.ts +5 -0
  52. package/lib/cjs/tests/api_tests/programs_trigger_filters.test.d.ts.map +1 -0
  53. package/lib/cjs/tests/api_tests/programs_trigger_filters.test.js +295 -0
  54. package/lib/cjs/tests/api_tests/programs_trigger_filters.test.js.map +1 -0
  55. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -1
  56. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +55 -47
  57. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -1
  58. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.js +1 -1
  59. package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.js.map +1 -1
  60. package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts +42 -0
  61. package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts.map +1 -0
  62. package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.js +484 -0
  63. package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.js.map +1 -0
  64. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.js +1 -1
  65. package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.js.map +1 -1
  66. package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js +1 -1
  67. package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js.map +1 -1
  68. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.js +1 -1
  69. package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.js.map +1 -1
  70. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.js +1 -1
  71. package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.js.map +1 -1
  72. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.js +2 -2
  73. package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.js.map +1 -1
  74. package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts +32 -0
  75. package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts.map +1 -0
  76. package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js +297 -0
  77. package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js.map +1 -0
  78. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts.map +1 -1
  79. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js +4 -1
  80. package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js.map +1 -1
  81. package/lib/cjs/tests/api_tests/templated_message_date_fields.test.d.ts +3 -0
  82. package/lib/cjs/tests/api_tests/templated_message_date_fields.test.d.ts.map +1 -0
  83. package/lib/cjs/tests/api_tests/templated_message_date_fields.test.js +202 -0
  84. package/lib/cjs/tests/api_tests/templated_message_date_fields.test.js.map +1 -0
  85. package/lib/cjs/tests/api_tests/templated_message_link_in_href.test.d.ts +3 -0
  86. package/lib/cjs/tests/api_tests/templated_message_link_in_href.test.d.ts.map +1 -0
  87. package/lib/cjs/tests/api_tests/templated_message_link_in_href.test.js +233 -0
  88. package/lib/cjs/tests/api_tests/templated_message_link_in_href.test.js.map +1 -0
  89. package/lib/cjs/tests/api_tests/templated_message_links.test.d.ts +3 -0
  90. package/lib/cjs/tests/api_tests/templated_message_links.test.d.ts.map +1 -0
  91. package/lib/cjs/tests/api_tests/templated_message_links.test.js +235 -0
  92. package/lib/cjs/tests/api_tests/templated_message_links.test.js.map +1 -0
  93. package/lib/cjs/tests/api_tests/time_tracks.test.js +1 -1
  94. package/lib/cjs/tests/api_tests/time_tracks.test.js.map +1 -1
  95. package/lib/cjs/tests/api_tests/trigger_contains_matching.test.d.ts +5 -0
  96. package/lib/cjs/tests/api_tests/trigger_contains_matching.test.d.ts.map +1 -0
  97. package/lib/cjs/tests/api_tests/trigger_contains_matching.test.js +395 -0
  98. package/lib/cjs/tests/api_tests/trigger_contains_matching.test.js.map +1 -0
  99. package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.d.ts +5 -0
  100. package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.d.ts.map +1 -0
  101. package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.js +471 -0
  102. package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.js.map +1 -0
  103. package/lib/cjs/tests/api_tests/user_portal_settings.test.js +1 -1
  104. package/lib/cjs/tests/api_tests/user_portal_settings.test.js.map +1 -1
  105. package/lib/cjs/tests/api_tests/validation_behavior_locks.test.d.ts +2 -0
  106. package/lib/cjs/tests/api_tests/validation_behavior_locks.test.d.ts.map +1 -0
  107. package/lib/cjs/tests/api_tests/validation_behavior_locks.test.js +233 -0
  108. package/lib/cjs/tests/api_tests/validation_behavior_locks.test.js.map +1 -0
  109. package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.d.ts +5 -0
  110. package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.d.ts.map +1 -0
  111. package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.js +569 -0
  112. package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.js.map +1 -0
  113. package/lib/cjs/tests/public_endpoint_tests.js +3 -2
  114. package/lib/cjs/tests/public_endpoint_tests.js.map +1 -1
  115. package/lib/cjs/tests/setup.d.ts +16 -0
  116. package/lib/cjs/tests/setup.d.ts.map +1 -1
  117. package/lib/cjs/tests/setup.js +55 -8
  118. package/lib/cjs/tests/setup.js.map +1 -1
  119. package/lib/cjs/tests/setup_isolated.d.ts +9 -0
  120. package/lib/cjs/tests/setup_isolated.d.ts.map +1 -1
  121. package/lib/cjs/tests/setup_isolated.js +23 -2
  122. package/lib/cjs/tests/setup_isolated.js.map +1 -1
  123. package/lib/cjs/tests/socket_tests.d.ts.map +1 -1
  124. package/lib/cjs/tests/socket_tests.js +3 -2
  125. package/lib/cjs/tests/socket_tests.js.map +1 -1
  126. package/lib/cjs/tests/tests.d.ts.map +1 -1
  127. package/lib/cjs/tests/tests.js +244 -216
  128. package/lib/cjs/tests/tests.js.map +1 -1
  129. package/lib/cjs/tests/unit_tests/trigger_title_partials.test.d.ts +3 -0
  130. package/lib/cjs/tests/unit_tests/trigger_title_partials.test.d.ts.map +1 -0
  131. package/lib/cjs/tests/unit_tests/trigger_title_partials.test.js +118 -0
  132. package/lib/cjs/tests/unit_tests/trigger_title_partials.test.js.map +1 -0
  133. package/lib/cjs/tests/webhooks_tests.js +3 -2
  134. package/lib/cjs/tests/webhooks_tests.js.map +1 -1
  135. package/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  136. package/lib/esm/enduser.d.ts +2 -0
  137. package/lib/esm/enduser.d.ts.map +1 -1
  138. package/lib/esm/sdk.d.ts +9 -3
  139. package/lib/esm/sdk.d.ts.map +1 -1
  140. package/lib/esm/sdk.js +2 -0
  141. package/lib/esm/sdk.js.map +1 -1
  142. package/lib/esm/session.d.ts +2 -0
  143. package/lib/esm/session.d.ts.map +1 -1
  144. package/lib/esm/tests/api_tests/active_patient_count.test.js +1 -1
  145. package/lib/esm/tests/api_tests/active_patient_count.test.js.map +1 -1
  146. package/lib/esm/tests/api_tests/appointment_rescheduled_trigger.test.js +1 -1
  147. package/lib/esm/tests/api_tests/appointment_rescheduled_trigger.test.js.map +1 -1
  148. package/lib/esm/tests/api_tests/calendar_event_limits.test.js +5 -5
  149. package/lib/esm/tests/api_tests/calendar_event_limits.test.js.map +1 -1
  150. package/lib/esm/tests/api_tests/calendar_event_references_update.test.js +1 -1
  151. package/lib/esm/tests/api_tests/calendar_event_references_update.test.js.map +1 -1
  152. package/lib/esm/tests/api_tests/enduser_cross_access_isolation.test.js +1 -1
  153. package/lib/esm/tests/api_tests/enduser_cross_access_isolation.test.js.map +1 -1
  154. package/lib/esm/tests/api_tests/enduser_fields_sync.test.d.ts +21 -0
  155. package/lib/esm/tests/api_tests/enduser_fields_sync.test.d.ts.map +1 -0
  156. package/lib/esm/tests/api_tests/enduser_fields_sync.test.js +210 -0
  157. package/lib/esm/tests/api_tests/enduser_fields_sync.test.js.map +1 -0
  158. package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.js +7 -7
  159. package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.js.map +1 -1
  160. package/lib/esm/tests/api_tests/enduser_session_invalidation.test.js +4 -4
  161. package/lib/esm/tests/api_tests/enduser_session_invalidation.test.js.map +1 -1
  162. package/lib/esm/tests/api_tests/load_threads_care_team.test.d.ts +32 -0
  163. package/lib/esm/tests/api_tests/load_threads_care_team.test.d.ts.map +1 -0
  164. package/lib/esm/tests/api_tests/load_threads_care_team.test.js +252 -0
  165. package/lib/esm/tests/api_tests/load_threads_care_team.test.js.map +1 -0
  166. package/lib/esm/tests/api_tests/managed_content_enduser_access.test.js +1 -1
  167. package/lib/esm/tests/api_tests/managed_content_enduser_access.test.js.map +1 -1
  168. package/lib/esm/tests/api_tests/managed_content_file_access.test.js +1 -1
  169. package/lib/esm/tests/api_tests/managed_content_file_access.test.js.map +1 -1
  170. package/lib/esm/tests/api_tests/mdi_case_offerings.test.d.ts.map +1 -1
  171. package/lib/esm/tests/api_tests/mdi_case_offerings.test.js +139 -9
  172. package/lib/esm/tests/api_tests/mdi_case_offerings.test.js.map +1 -1
  173. package/lib/esm/tests/api_tests/mdi_webhooks.test.d.ts.map +1 -1
  174. package/lib/esm/tests/api_tests/mdi_webhooks.test.js +21 -8
  175. package/lib/esm/tests/api_tests/mdi_webhooks.test.js.map +1 -1
  176. package/lib/esm/tests/api_tests/nutrition_tracking.test.js +1 -1
  177. package/lib/esm/tests/api_tests/nutrition_tracking.test.js.map +1 -1
  178. package/lib/esm/tests/api_tests/openloop_webhooks.test.js +1 -1
  179. package/lib/esm/tests/api_tests/openloop_webhooks.test.js.map +1 -1
  180. package/lib/esm/tests/api_tests/programs.test.d.ts +5 -0
  181. package/lib/esm/tests/api_tests/programs.test.d.ts.map +1 -0
  182. package/lib/esm/tests/api_tests/programs.test.js +365 -0
  183. package/lib/esm/tests/api_tests/programs.test.js.map +1 -0
  184. package/lib/esm/tests/api_tests/programs_trigger_filters.test.d.ts +5 -0
  185. package/lib/esm/tests/api_tests/programs_trigger_filters.test.d.ts.map +1 -0
  186. package/lib/esm/tests/api_tests/programs_trigger_filters.test.js +290 -0
  187. package/lib/esm/tests/api_tests/programs_trigger_filters.test.js.map +1 -0
  188. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -1
  189. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +55 -47
  190. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -1
  191. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.js +1 -1
  192. package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.js.map +1 -1
  193. package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts +42 -0
  194. package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts.map +1 -0
  195. package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.js +479 -0
  196. package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.js.map +1 -0
  197. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.js +1 -1
  198. package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.js.map +1 -1
  199. package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js +1 -1
  200. package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js.map +1 -1
  201. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.js +1 -1
  202. package/lib/esm/tests/api_tests/security/enduser-cross-create.test.js.map +1 -1
  203. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.js +1 -1
  204. package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.js.map +1 -1
  205. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.js +3 -3
  206. package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.js.map +1 -1
  207. package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts +32 -0
  208. package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts.map +1 -0
  209. package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js +292 -0
  210. package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js.map +1 -0
  211. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts.map +1 -1
  212. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.js +4 -1
  213. package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.js.map +1 -1
  214. package/lib/esm/tests/api_tests/templated_message_date_fields.test.d.ts +3 -0
  215. package/lib/esm/tests/api_tests/templated_message_date_fields.test.d.ts.map +1 -0
  216. package/lib/esm/tests/api_tests/templated_message_date_fields.test.js +198 -0
  217. package/lib/esm/tests/api_tests/templated_message_date_fields.test.js.map +1 -0
  218. package/lib/esm/tests/api_tests/templated_message_link_in_href.test.d.ts +3 -0
  219. package/lib/esm/tests/api_tests/templated_message_link_in_href.test.d.ts.map +1 -0
  220. package/lib/esm/tests/api_tests/templated_message_link_in_href.test.js +229 -0
  221. package/lib/esm/tests/api_tests/templated_message_link_in_href.test.js.map +1 -0
  222. package/lib/esm/tests/api_tests/templated_message_links.test.d.ts +3 -0
  223. package/lib/esm/tests/api_tests/templated_message_links.test.d.ts.map +1 -0
  224. package/lib/esm/tests/api_tests/templated_message_links.test.js +231 -0
  225. package/lib/esm/tests/api_tests/templated_message_links.test.js.map +1 -0
  226. package/lib/esm/tests/api_tests/time_tracks.test.js +1 -1
  227. package/lib/esm/tests/api_tests/time_tracks.test.js.map +1 -1
  228. package/lib/esm/tests/api_tests/trigger_contains_matching.test.d.ts +5 -0
  229. package/lib/esm/tests/api_tests/trigger_contains_matching.test.d.ts.map +1 -0
  230. package/lib/esm/tests/api_tests/trigger_contains_matching.test.js +390 -0
  231. package/lib/esm/tests/api_tests/trigger_contains_matching.test.js.map +1 -0
  232. package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.d.ts +5 -0
  233. package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.d.ts.map +1 -0
  234. package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.js +466 -0
  235. package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.js.map +1 -0
  236. package/lib/esm/tests/api_tests/user_portal_settings.test.js +1 -1
  237. package/lib/esm/tests/api_tests/user_portal_settings.test.js.map +1 -1
  238. package/lib/esm/tests/api_tests/validation_behavior_locks.test.d.ts +2 -0
  239. package/lib/esm/tests/api_tests/validation_behavior_locks.test.d.ts.map +1 -0
  240. package/lib/esm/tests/api_tests/validation_behavior_locks.test.js +229 -0
  241. package/lib/esm/tests/api_tests/validation_behavior_locks.test.js.map +1 -0
  242. package/lib/esm/tests/api_tests/vital_review_trigger_action.test.d.ts +5 -0
  243. package/lib/esm/tests/api_tests/vital_review_trigger_action.test.d.ts.map +1 -0
  244. package/lib/esm/tests/api_tests/vital_review_trigger_action.test.js +564 -0
  245. package/lib/esm/tests/api_tests/vital_review_trigger_action.test.js.map +1 -0
  246. package/lib/esm/tests/public_endpoint_tests.js +3 -2
  247. package/lib/esm/tests/public_endpoint_tests.js.map +1 -1
  248. package/lib/esm/tests/setup.d.ts +16 -0
  249. package/lib/esm/tests/setup.d.ts.map +1 -1
  250. package/lib/esm/tests/setup.js +53 -7
  251. package/lib/esm/tests/setup.js.map +1 -1
  252. package/lib/esm/tests/setup_isolated.d.ts +9 -0
  253. package/lib/esm/tests/setup_isolated.d.ts.map +1 -1
  254. package/lib/esm/tests/setup_isolated.js +21 -1
  255. package/lib/esm/tests/setup_isolated.js.map +1 -1
  256. package/lib/esm/tests/socket_tests.d.ts.map +1 -1
  257. package/lib/esm/tests/socket_tests.js +3 -2
  258. package/lib/esm/tests/socket_tests.js.map +1 -1
  259. package/lib/esm/tests/tests.d.ts.map +1 -1
  260. package/lib/esm/tests/tests.js +244 -216
  261. package/lib/esm/tests/tests.js.map +1 -1
  262. package/lib/esm/tests/unit_tests/trigger_title_partials.test.d.ts +3 -0
  263. package/lib/esm/tests/unit_tests/trigger_title_partials.test.d.ts.map +1 -0
  264. package/lib/esm/tests/unit_tests/trigger_title_partials.test.js +115 -0
  265. package/lib/esm/tests/unit_tests/trigger_title_partials.test.js.map +1 -0
  266. package/lib/esm/tests/webhooks_tests.js +3 -2
  267. package/lib/esm/tests/webhooks_tests.js.map +1 -1
  268. package/lib/tsconfig.tsbuildinfo +1 -1
  269. package/package.json +22 -19
  270. package/src/sdk.ts +11 -1
  271. package/src/tests/api_tests/active_patient_count.test.ts +1 -1
  272. package/src/tests/api_tests/appointment_rescheduled_trigger.test.ts +1 -1
  273. package/src/tests/api_tests/calendar_event_references_update.test.ts +1 -1
  274. package/src/tests/api_tests/enduser_cross_access_isolation.test.ts +1 -1
  275. package/src/tests/api_tests/enduser_fields_sync.test.ts +150 -0
  276. package/src/tests/api_tests/enduser_login_rate_limits.test.ts +7 -7
  277. package/src/tests/api_tests/enduser_session_invalidation.test.ts +4 -4
  278. package/src/tests/api_tests/load_threads_care_team.test.ts +210 -0
  279. package/src/tests/api_tests/managed_content_enduser_access.test.ts +1 -1
  280. package/src/tests/api_tests/managed_content_file_access.test.ts +1 -1
  281. package/src/tests/api_tests/mdi_case_offerings.test.ts +138 -0
  282. package/src/tests/api_tests/mdi_webhooks.test.ts +9 -0
  283. package/src/tests/api_tests/nutrition_tracking.test.ts +1 -1
  284. package/src/tests/api_tests/openloop_webhooks.test.ts +1 -1
  285. package/src/tests/api_tests/security/add-to-journey-foreign-enduserid.test.ts +33 -26
  286. package/src/tests/api_tests/security/allowed-paths-confinement.test.ts +1 -1
  287. package/src/tests/api_tests/security/appointment-reschedule-ownership.test.ts +432 -0
  288. package/src/tests/api_tests/security/booking-info-idor-token-mint.test.ts +1 -1
  289. package/src/tests/api_tests/security/enduser-ai-summary-trust-gate.test.ts +1 -1
  290. package/src/tests/api_tests/security/enduser-cross-create.test.ts +1 -1
  291. package/src/tests/api_tests/security/enduser-write-restrictions.test.ts +1 -1
  292. package/src/tests/api_tests/security/invite-user-enumeration.test.ts +3 -3
  293. package/src/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.ts +197 -0
  294. package/src/tests/api_tests/security/sanitize-user-html-with-iframes.test.ts +4 -1
  295. package/src/tests/api_tests/templated_message_date_fields.test.ts +146 -0
  296. package/src/tests/api_tests/templated_message_links.test.ts +192 -0
  297. package/src/tests/api_tests/time_tracks.test.ts +1 -1
  298. package/src/tests/api_tests/trigger_contains_matching.test.ts +345 -0
  299. package/src/tests/api_tests/user_logs_restore_deleted.test.ts +415 -0
  300. package/src/tests/api_tests/user_portal_settings.test.ts +1 -1
  301. package/src/tests/api_tests/validation_behavior_locks.test.ts +204 -0
  302. package/src/tests/public_endpoint_tests.ts +3 -2
  303. package/src/tests/setup.ts +43 -7
  304. package/src/tests/setup_isolated.ts +10 -0
  305. package/src/tests/socket_tests.ts +3 -2
  306. package/src/tests/tests.ts +22 -2
  307. package/src/tests/unit_tests/trigger_title_partials.test.ts +174 -0
  308. package/src/tests/webhooks_tests.ts +4 -2
  309. package/test_generated.pdf +0 -0
  310. package/tsconfig.cjs.json +17 -0
@@ -91,10 +91,41 @@ const resolve_displayed_options = (
91
91
  ) ? field.options.choices : undefined
92
92
  }
93
93
 
94
+ // Local replica of the API's mdiIgnore handling (md_integrations.ts): the same field lookup
95
+ // (_id first, externalId fallback — Formsort / form-ingestion answers carry no fieldId), with
96
+ // patient-mapped fields exempt. Used to filter both case_questions and case file uploads.
97
+ type IgnorableField = { _id: string, externalId?: string, mdiIgnore?: boolean }
98
+ type IgnorableResponse = { fieldId?: string, externalId?: string, answer: { type?: string } }
99
+
100
+ const is_mdi_ignored = (response: IgnorableResponse, formFields: IgnorableField[]): boolean => {
101
+ if (response.externalId && PATIENT_MAPPED_EXTERNAL_IDS.has(response.externalId)) return false
102
+ const field = (
103
+ formFields.find(f => f._id.toString() === response.fieldId)
104
+ || formFields.find(f => response.externalId && f.externalId === response.externalId)
105
+ )
106
+ return !!field?.mdiIgnore
107
+ }
108
+
109
+ const case_question_responses = (responses: IgnorableResponse[], formFields: IgnorableField[]) => (
110
+ responses.filter(r =>
111
+ r.answer.type !== 'file' && r.answer.type !== 'files'
112
+ && !(r.externalId && PATIENT_MAPPED_EXTERNAL_IDS.has(r.externalId))
113
+ && !is_mdi_ignored(r, formFields)
114
+ )
115
+ )
116
+
117
+ const uploadable_file_responses = (responses: IgnorableResponse[], formFields: IgnorableField[]) => (
118
+ responses.filter(r =>
119
+ (r.answer.type === 'file' || r.answer.type === 'files')
120
+ && !is_mdi_ignored(r, formFields)
121
+ )
122
+ )
123
+
94
124
  export const mdi_case_offerings_tests = async ({ sdk, sdkNonAdmin }: { sdk: Session, sdkNonAdmin: Session }) => {
95
125
  log_header("MDI Case Offerings Tests")
96
126
 
97
127
  let testFormId: string | undefined
128
+ let testFieldId: string | undefined
98
129
 
99
130
  try {
100
131
  // --- Schema round-trip tests ---
@@ -385,7 +416,114 @@ export const mdi_case_offerings_tests = async ({ sdk, sdkNonAdmin }: { sdk: Sess
385
416
  },
386
417
  { expectedResult: true }
387
418
  )
419
+
420
+ // --- mdiIgnore tests ---
421
+
422
+ await async_test(
423
+ "Form field mdiIgnore round-trips through create and update",
424
+ async () => {
425
+ if (!testFormId) throw new Error("No test form")
426
+
427
+ const field = await sdk.api.form_fields.createOne({
428
+ formId: testFormId,
429
+ title: 'Offering IDs',
430
+ type: 'string',
431
+ externalId: 'offeringIds',
432
+ mdiIgnore: true,
433
+ previousFields: [{ type: 'root', info: {} }],
434
+ })
435
+ testFieldId = field.id
436
+ const created = await sdk.api.form_fields.getOne(field.id)
437
+
438
+ await sdk.api.form_fields.updateOne(field.id, { mdiIgnore: false })
439
+ const updated = await sdk.api.form_fields.getOne(field.id)
440
+
441
+ return created.mdiIgnore === true && updated.mdiIgnore === false
442
+ },
443
+ { expectedResult: true }
444
+ )
445
+
446
+ const IGNORE_FIELDS: IgnorableField[] = [
447
+ { _id: 'field-ignored', externalId: 'internal_note', mdiIgnore: true },
448
+ { _id: 'field-offerings', externalId: 'offeringIds', mdiIgnore: true },
449
+ { _id: 'field-kept', externalId: 'symptoms' },
450
+ { _id: 'field-kept-explicit', externalId: 'duration', mdiIgnore: false },
451
+ { _id: 'field-allergies', externalId: 'allergies', mdiIgnore: true }, // patient-mapped → exempt
452
+ { _id: 'field-ignored-upload', externalId: 'internal_upload', mdiIgnore: true },
453
+ { _id: 'field-kept-upload', externalId: 'mdi:lab-result' },
454
+ ]
455
+
456
+ await async_test(
457
+ "mdiIgnore drops native form answers (matched by fieldId) from case_questions",
458
+ async () => {
459
+ const kept = case_question_responses([
460
+ { fieldId: 'field-ignored', answer: { type: 'string' } },
461
+ { fieldId: 'field-kept', answer: { type: 'string' } },
462
+ { fieldId: 'field-kept-explicit', answer: { type: 'string' } },
463
+ ], IGNORE_FIELDS)
464
+ return kept.length === 2 && kept.every(r => r.fieldId !== 'field-ignored')
465
+ },
466
+ { expectedResult: true }
467
+ )
468
+
469
+ await async_test(
470
+ "mdiIgnore drops Formsort / form-ingestion answers (matched by externalId) from case_questions",
471
+ async () => {
472
+ const kept = case_question_responses([
473
+ { fieldId: '', externalId: 'offeringIds', answer: { type: 'string' } },
474
+ { fieldId: '', externalId: 'symptoms', answer: { type: 'string' } },
475
+ { fieldId: '', externalId: 'unconfigured_key', answer: { type: 'string' } }, // no field → kept
476
+ ], IGNORE_FIELDS)
477
+ return (
478
+ kept.length === 2
479
+ && !kept.some(r => r.externalId === 'offeringIds')
480
+ && kept.some(r => r.externalId === 'unconfigured_key')
481
+ )
482
+ },
483
+ { expectedResult: true }
484
+ )
485
+
486
+ await async_test(
487
+ "mdiIgnore does not affect patient-mapped fields",
488
+ async () => (
489
+ !is_mdi_ignored({ fieldId: 'field-allergies', externalId: 'allergies', answer: { type: 'string' } }, IGNORE_FIELDS)
490
+ ),
491
+ { expectedResult: true }
492
+ )
493
+
494
+ await async_test(
495
+ "mdiIgnore skips file uploads for ignored fields only",
496
+ async () => {
497
+ const uploadable = uploadable_file_responses([
498
+ { fieldId: 'field-ignored-upload', answer: { type: 'file' } },
499
+ { fieldId: '', externalId: 'internal_upload', answer: { type: 'files' } },
500
+ { fieldId: 'field-kept-upload', answer: { type: 'file' } },
501
+ ], IGNORE_FIELDS)
502
+ return uploadable.length === 1 && uploadable[0].fieldId === 'field-kept-upload'
503
+ },
504
+ { expectedResult: true }
505
+ )
506
+
507
+ await async_test(
508
+ "mdiIgnore does not stop offering conditions from reading the answer",
509
+ async () => {
510
+ const offerings: MDIOffering[] = [
511
+ { offering_id: "03b7", conditions: { condition: { offeringIds: { $contains: "03b7" } as any } } },
512
+ ]
513
+ const responses = [{ externalId: 'offeringIds', value: '1d15,03b7,03b7' }]
514
+ const resolved = resolve_case_offerings(offerings, responses)
515
+ const questions = case_question_responses(
516
+ [{ fieldId: '', externalId: 'offeringIds', answer: { type: 'string' } }],
517
+ IGNORE_FIELDS,
518
+ )
519
+ return resolved.length === 1 && questions.length === 0
520
+ },
521
+ { expectedResult: true }
522
+ )
388
523
  } finally {
524
+ if (testFieldId) {
525
+ await sdk.api.form_fields.deleteOne(testFieldId).catch(console.error)
526
+ }
389
527
  if (testFormId) {
390
528
  await sdk.api.forms.deleteOne(testFormId).catch(console.error)
391
529
  }
@@ -75,6 +75,15 @@ export const mdi_webhooks_tests = async ({ sdk, sdkNonAdmin }: { sdk: Session, s
75
75
  )
76
76
  assert(status === 401, `message_created with bad auth should 401 (got ${status})`, "MDI webhook authenticates before patient lookup")
77
77
  }
78
+
79
+ // 5. case_order_created / case_order_updated with bogus auth -> still 401.
80
+ for (const event_type of ['case_order_created', 'case_order_updated']) {
81
+ const { status } = await postMDI(
82
+ { event_type, case_id: 'mdi-case-test-1', case_order_id: 'mdi-order-test-1', order_status: 'ready' },
83
+ { 'Authorization': `Bearer not-a-real-mdi-token-${Date.now()}` },
84
+ )
85
+ assert(status === 401, `${event_type} with bad auth should 401 (got ${status})`, `MDI webhook authenticates before ${event_type} dispatch`)
86
+ }
78
87
  }
79
88
 
80
89
  // Allow running this test file independently
@@ -9,7 +9,7 @@ import { ObservationComponent } from "@tellescope/types-models"
9
9
  import { authenticate_enduser_via_token, setup_tests } from "../setup"
10
10
 
11
11
  const host = process.env.API_URL || 'http://localhost:8080' as const
12
- const businessId = '60398b1131a295e64f084ff6'
12
+ const businessId = process.env.TEST_BUSINESS_ID || '60398b1131a295e64f084ff6'
13
13
 
14
14
  const ENDUSER_PASSWORD = 'NutritionTestPassword!123'
15
15
 
@@ -10,7 +10,7 @@ import {
10
10
  import { setup_tests } from "../setup"
11
11
 
12
12
  const host = process.env.API_URL || 'http://localhost:8080' as const
13
- const businessId = '60398b1131a295e64f084ff6'
13
+ const businessId = process.env.TEST_BUSINESS_ID || '60398b1131a295e64f084ff6'
14
14
 
15
15
  const v1Url = `${host}/v1/webhooks/openloop/${businessId}`
16
16
  const v2Url = `${host}/v1/webhooks/openloop-v2/${businessId}`
@@ -5,6 +5,7 @@ import {
5
5
  Check,
6
6
  setup_isolated_tenant,
7
7
  } from "../../setup_isolated"
8
+ import { poll_for_results } from "@tellescope/testing"
8
9
 
9
10
  const host = process.env.API_URL || 'http://localhost:8080' as const
10
11
 
@@ -97,6 +98,11 @@ export const add_to_journey_foreign_enduserid_checks = async (): Promise<Check[]
97
98
  await attacker!.sdk.api.automated_actions.getSome({ filter: { journeyId } } as any)
98
99
  )
99
100
  const enduserIdsFor = async (journeyId: string) => (await rowsFor(journeyId)).map((r: any) => r.enduserId)
101
+ // add_to_journey's automated_actions.insertMany is fire-and-forget on both branches, so the 204
102
+ // can arrive before the rows exist: poll until the expected id shows (last read on timeout)
103
+ const enduserIdsForOnceContains = (journeyId: string, enduserId: string) => (
104
+ poll_for_results(() => enduserIdsFor(journeyId), ids => ids.includes(enduserId))
105
+ )
100
106
 
101
107
  /* ===== A: the foreign id must never be planted, on EITHER branch ===== */
102
108
 
@@ -108,13 +114,6 @@ export const add_to_journey_foreign_enduserid_checks = async (): Promise<Check[]
108
114
  startAt: FUTURE_START(),
109
115
  } as any).then(() => 'resolved').catch((e: any) => `rejected: ${e?.message || e}`)
110
116
 
111
- const inlineIds = await enduserIdsFor(inline.journey.id)
112
- record(
113
- 'A1: inline branch (automationStepId) does not plant a foreign enduserId',
114
- !inlineIds.includes(victim.id),
115
- `call=${inlineResult}; automated_actions enduserIds=${JSON.stringify(inlineIds)} (must not contain ${victim.id})`,
116
- )
117
-
118
117
  // A2 — module branch: no automationStepId, so it routes through handle_automation_event
119
118
  const moduleResult = await attacker.sdk.api.endusers.add_to_journey({
120
119
  enduserIds: [victim.id],
@@ -122,22 +121,6 @@ export const add_to_journey_foreign_enduserid_checks = async (): Promise<Check[]
122
121
  startAt: FUTURE_START(),
123
122
  } as any).then(() => 'resolved').catch((e: any) => `rejected: ${e?.message || e}`)
124
123
 
125
- const moduleIds = await enduserIdsFor(modulePath.journey.id)
126
- record(
127
- 'A2: module branch (no automationStepId) does not plant a foreign enduserId',
128
- !moduleIds.includes(victim.id),
129
- `call=${moduleResult}; automated_actions enduserIds=${JSON.stringify(moduleIds)} (must not contain ${victim.id})`,
130
- )
131
-
132
- // A3 — the victim's own record must be untouched (the scoped updateMany should already ensure it)
133
- const victimAfter = await victimTenant.sdk.api.endusers.getOne(victim.id)
134
- const victimJourneys = (victimAfter as any)?.journeys ?? {}
135
- record(
136
- 'A3: the victim enduser was not enrolled in the attacker\'s journey',
137
- !victimJourneys[inline.journey.id] && !victimJourneys[modulePath.journey.id],
138
- `victim journeys=${JSON.stringify(victimJourneys)}`,
139
- )
140
-
141
124
  /* ===== B: legitimate use must keep working ===== */
142
125
 
143
126
  // B1 — positive control on both branches, so a blanket failure can't masquerade as a fix
@@ -153,8 +136,32 @@ export const add_to_journey_foreign_enduserid_checks = async (): Promise<Check[]
153
136
  startAt: FUTURE_START(),
154
137
  } as any)
155
138
 
156
- const inlineOwn = await enduserIdsFor(inline.journey.id)
157
- const moduleOwn = await enduserIdsFor(modulePath.journey.id)
139
+ const inlineOwn = await enduserIdsForOnceContains(inline.journey.id, own.id)
140
+ const moduleOwn = await enduserIdsForOnceContains(modulePath.journey.id, own.id)
141
+
142
+ // A1/A2 are judged against the post-B1 reads: those include every row for the journey, and the
143
+ // legitimate insert having landed is what makes the victim's absence meaningful rather than
144
+ // "not written yet"
145
+ record(
146
+ 'A1: inline branch (automationStepId) does not plant a foreign enduserId',
147
+ !inlineOwn.includes(victim.id),
148
+ `call=${inlineResult}; automated_actions enduserIds=${JSON.stringify(inlineOwn)} (must not contain ${victim.id})`,
149
+ )
150
+ record(
151
+ 'A2: module branch (no automationStepId) does not plant a foreign enduserId',
152
+ !moduleOwn.includes(victim.id),
153
+ `call=${moduleResult}; automated_actions enduserIds=${JSON.stringify(moduleOwn)} (must not contain ${victim.id})`,
154
+ )
155
+
156
+ // A3 — the victim's own record must be untouched (the scoped updateMany should already ensure it)
157
+ const victimAfter = await victimTenant.sdk.api.endusers.getOne(victim.id)
158
+ const victimJourneys = (victimAfter as any)?.journeys ?? {}
159
+ record(
160
+ 'A3: the victim enduser was not enrolled in the attacker\'s journey',
161
+ !victimJourneys[inline.journey.id] && !victimJourneys[modulePath.journey.id],
162
+ `victim journeys=${JSON.stringify(victimJourneys)}`,
163
+ )
164
+
158
165
  record(
159
166
  'B1: the caller\'s OWN enduser still enrolls on both branches',
160
167
  inlineOwn.includes(own.id) && moduleOwn.includes(own.id),
@@ -170,7 +177,7 @@ export const add_to_journey_foreign_enduserid_checks = async (): Promise<Check[]
170
177
  startAt: FUTURE_START(),
171
178
  } as any).then(() => 'resolved').catch((e: any) => `rejected: ${e?.message || e}`)
172
179
 
173
- const mixedIds = await enduserIdsFor(mixed.journey.id)
180
+ const mixedIds = await enduserIdsForOnceContains(mixed.journey.id, own.id)
174
181
  record(
175
182
  'B2: a mixed list enrolls the visible enduser and drops only the foreign one',
176
183
  mixedIds.includes(own.id) && !mixedIds.includes(victim.id),
@@ -631,7 +631,7 @@ export const allowed_paths_confinement_tests = async ({ sdk } : { sdk: Session,
631
631
  // record. `allowedPaths` is a JWT claim only (WithAllowedPaths in types-models is used solely on
632
632
  // the session type; there is no schema validator for it), so an API-key session can never carry
633
633
  // one and is never path-confined. Assert that rather than reason about it.
634
- const apiKeySDK = new Session({ host, apiKey: '3n5q0SCBT_iUvZz-b9BJtX7o7HQUVJ9v132PgHJNJsg.' })
634
+ const apiKeySDK = new Session({ host, apiKey: process.env.TEST_API_KEY || '3n5q0SCBT_iUvZz-b9BJtX7o7HQUVJ9v132PgHJNJsg.' })
635
635
  for (const path of ['/journeys', '/form-responses', '/endusers', '/calendar-events', '/files']) {
636
636
  const r = await axios.request({
637
637
  method: 'get',