@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.
- package/CLAUDE.md +5 -0
- package/env.example +39 -0
- package/lib/cjs/enduser.d.ts +1 -0
- package/lib/cjs/enduser.d.ts.map +1 -1
- package/lib/cjs/sdk.d.ts +6 -1
- package/lib/cjs/sdk.d.ts.map +1 -1
- package/lib/cjs/sdk.js +2 -0
- package/lib/cjs/sdk.js.map +1 -1
- package/lib/cjs/session.d.ts +1 -0
- package/lib/cjs/session.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/active_patient_count.test.js +1 -1
- package/lib/cjs/tests/api_tests/active_patient_count.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/appointment_rescheduled_trigger.test.js +1 -1
- package/lib/cjs/tests/api_tests/appointment_rescheduled_trigger.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/calendar_event_limits.test.js +5 -5
- package/lib/cjs/tests/api_tests/calendar_event_limits.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/calendar_event_references_update.test.js +1 -1
- package/lib/cjs/tests/api_tests/calendar_event_references_update.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/enduser_cross_access_isolation.test.js +1 -1
- package/lib/cjs/tests/api_tests/enduser_cross_access_isolation.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/enduser_fields_sync.test.d.ts +21 -0
- package/lib/cjs/tests/api_tests/enduser_fields_sync.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_fields_sync.test.js +215 -0
- package/lib/cjs/tests/api_tests/enduser_fields_sync.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.js +6 -6
- package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.js +3 -3
- package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/load_threads_care_team.test.d.ts +32 -0
- package/lib/cjs/tests/api_tests/load_threads_care_team.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/load_threads_care_team.test.js +257 -0
- package/lib/cjs/tests/api_tests/load_threads_care_team.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/managed_content_enduser_access.test.js +1 -1
- package/lib/cjs/tests/api_tests/managed_content_enduser_access.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/managed_content_file_access.test.js +1 -1
- package/lib/cjs/tests/api_tests/managed_content_file_access.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.js +139 -9
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/mdi_webhooks.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/mdi_webhooks.test.js +21 -8
- package/lib/cjs/tests/api_tests/mdi_webhooks.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/nutrition_tracking.test.js +1 -1
- package/lib/cjs/tests/api_tests/nutrition_tracking.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.js +1 -1
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/programs.test.d.ts +5 -0
- package/lib/cjs/tests/api_tests/programs.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/programs.test.js +370 -0
- package/lib/cjs/tests/api_tests/programs.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/programs_trigger_filters.test.d.ts +5 -0
- package/lib/cjs/tests/api_tests/programs_trigger_filters.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/programs_trigger_filters.test.js +295 -0
- package/lib/cjs/tests/api_tests/programs_trigger_filters.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +55 -47
- package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.js +1 -1
- package/lib/cjs/tests/api_tests/security/allowed-paths-confinement.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts +42 -0
- package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.js +484 -0
- package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.js +1 -1
- package/lib/cjs/tests/api_tests/security/booking-info-idor-token-mint.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js +1 -1
- package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.js +1 -1
- package/lib/cjs/tests/api_tests/security/enduser-cross-create.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.js +1 -1
- package/lib/cjs/tests/api_tests/security/enduser-write-restrictions.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.js +2 -2
- package/lib/cjs/tests/api_tests/security/invite-user-enumeration.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts +32 -0
- package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js +297 -0
- package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js +4 -1
- package/lib/cjs/tests/api_tests/security/sanitize-user-html-with-iframes.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/templated_message_date_fields.test.d.ts +3 -0
- package/lib/cjs/tests/api_tests/templated_message_date_fields.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/templated_message_date_fields.test.js +202 -0
- package/lib/cjs/tests/api_tests/templated_message_date_fields.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/templated_message_link_in_href.test.d.ts +3 -0
- package/lib/cjs/tests/api_tests/templated_message_link_in_href.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/templated_message_link_in_href.test.js +233 -0
- package/lib/cjs/tests/api_tests/templated_message_link_in_href.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/templated_message_links.test.d.ts +3 -0
- package/lib/cjs/tests/api_tests/templated_message_links.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/templated_message_links.test.js +235 -0
- package/lib/cjs/tests/api_tests/templated_message_links.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/time_tracks.test.js +1 -1
- package/lib/cjs/tests/api_tests/time_tracks.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/trigger_contains_matching.test.d.ts +5 -0
- package/lib/cjs/tests/api_tests/trigger_contains_matching.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/trigger_contains_matching.test.js +395 -0
- package/lib/cjs/tests/api_tests/trigger_contains_matching.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.d.ts +5 -0
- package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.js +471 -0
- package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/user_portal_settings.test.js +1 -1
- package/lib/cjs/tests/api_tests/user_portal_settings.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/validation_behavior_locks.test.d.ts +2 -0
- package/lib/cjs/tests/api_tests/validation_behavior_locks.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/validation_behavior_locks.test.js +233 -0
- package/lib/cjs/tests/api_tests/validation_behavior_locks.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.d.ts +5 -0
- package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.js +569 -0
- package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.js.map +1 -0
- package/lib/cjs/tests/public_endpoint_tests.js +3 -2
- package/lib/cjs/tests/public_endpoint_tests.js.map +1 -1
- package/lib/cjs/tests/setup.d.ts +16 -0
- package/lib/cjs/tests/setup.d.ts.map +1 -1
- package/lib/cjs/tests/setup.js +55 -8
- package/lib/cjs/tests/setup.js.map +1 -1
- package/lib/cjs/tests/setup_isolated.d.ts +9 -0
- package/lib/cjs/tests/setup_isolated.d.ts.map +1 -1
- package/lib/cjs/tests/setup_isolated.js +23 -2
- package/lib/cjs/tests/setup_isolated.js.map +1 -1
- package/lib/cjs/tests/socket_tests.d.ts.map +1 -1
- package/lib/cjs/tests/socket_tests.js +3 -2
- package/lib/cjs/tests/socket_tests.js.map +1 -1
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +244 -216
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/cjs/tests/unit_tests/trigger_title_partials.test.d.ts +3 -0
- package/lib/cjs/tests/unit_tests/trigger_title_partials.test.d.ts.map +1 -0
- package/lib/cjs/tests/unit_tests/trigger_title_partials.test.js +118 -0
- package/lib/cjs/tests/unit_tests/trigger_title_partials.test.js.map +1 -0
- package/lib/cjs/tests/webhooks_tests.js +3 -2
- package/lib/cjs/tests/webhooks_tests.js.map +1 -1
- package/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/esm/enduser.d.ts +2 -0
- package/lib/esm/enduser.d.ts.map +1 -1
- package/lib/esm/sdk.d.ts +9 -3
- package/lib/esm/sdk.d.ts.map +1 -1
- package/lib/esm/sdk.js +2 -0
- package/lib/esm/sdk.js.map +1 -1
- package/lib/esm/session.d.ts +2 -0
- package/lib/esm/session.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/active_patient_count.test.js +1 -1
- package/lib/esm/tests/api_tests/active_patient_count.test.js.map +1 -1
- package/lib/esm/tests/api_tests/appointment_rescheduled_trigger.test.js +1 -1
- package/lib/esm/tests/api_tests/appointment_rescheduled_trigger.test.js.map +1 -1
- package/lib/esm/tests/api_tests/calendar_event_limits.test.js +5 -5
- package/lib/esm/tests/api_tests/calendar_event_limits.test.js.map +1 -1
- package/lib/esm/tests/api_tests/calendar_event_references_update.test.js +1 -1
- package/lib/esm/tests/api_tests/calendar_event_references_update.test.js.map +1 -1
- package/lib/esm/tests/api_tests/enduser_cross_access_isolation.test.js +1 -1
- package/lib/esm/tests/api_tests/enduser_cross_access_isolation.test.js.map +1 -1
- package/lib/esm/tests/api_tests/enduser_fields_sync.test.d.ts +21 -0
- package/lib/esm/tests/api_tests/enduser_fields_sync.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/enduser_fields_sync.test.js +210 -0
- package/lib/esm/tests/api_tests/enduser_fields_sync.test.js.map +1 -0
- package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.js +7 -7
- package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.js.map +1 -1
- package/lib/esm/tests/api_tests/enduser_session_invalidation.test.js +4 -4
- package/lib/esm/tests/api_tests/enduser_session_invalidation.test.js.map +1 -1
- package/lib/esm/tests/api_tests/load_threads_care_team.test.d.ts +32 -0
- package/lib/esm/tests/api_tests/load_threads_care_team.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/load_threads_care_team.test.js +252 -0
- package/lib/esm/tests/api_tests/load_threads_care_team.test.js.map +1 -0
- package/lib/esm/tests/api_tests/managed_content_enduser_access.test.js +1 -1
- package/lib/esm/tests/api_tests/managed_content_enduser_access.test.js.map +1 -1
- package/lib/esm/tests/api_tests/managed_content_file_access.test.js +1 -1
- package/lib/esm/tests/api_tests/managed_content_file_access.test.js.map +1 -1
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.js +139 -9
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.js.map +1 -1
- package/lib/esm/tests/api_tests/mdi_webhooks.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/mdi_webhooks.test.js +21 -8
- package/lib/esm/tests/api_tests/mdi_webhooks.test.js.map +1 -1
- package/lib/esm/tests/api_tests/nutrition_tracking.test.js +1 -1
- package/lib/esm/tests/api_tests/nutrition_tracking.test.js.map +1 -1
- package/lib/esm/tests/api_tests/openloop_webhooks.test.js +1 -1
- package/lib/esm/tests/api_tests/openloop_webhooks.test.js.map +1 -1
- package/lib/esm/tests/api_tests/programs.test.d.ts +5 -0
- package/lib/esm/tests/api_tests/programs.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/programs.test.js +365 -0
- package/lib/esm/tests/api_tests/programs.test.js.map +1 -0
- package/lib/esm/tests/api_tests/programs_trigger_filters.test.d.ts +5 -0
- package/lib/esm/tests/api_tests/programs_trigger_filters.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/programs_trigger_filters.test.js +290 -0
- package/lib/esm/tests/api_tests/programs_trigger_filters.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +55 -47
- package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.js +1 -1
- package/lib/esm/tests/api_tests/security/allowed-paths-confinement.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts +42 -0
- package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.js +479 -0
- package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.js +1 -1
- package/lib/esm/tests/api_tests/security/booking-info-idor-token-mint.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js +1 -1
- package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/enduser-cross-create.test.js +1 -1
- package/lib/esm/tests/api_tests/security/enduser-cross-create.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.js +1 -1
- package/lib/esm/tests/api_tests/security/enduser-write-restrictions.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.js +3 -3
- package/lib/esm/tests/api_tests/security/invite-user-enumeration.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts +32 -0
- package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js +292 -0
- package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.js +4 -1
- package/lib/esm/tests/api_tests/security/sanitize-user-html-with-iframes.test.js.map +1 -1
- package/lib/esm/tests/api_tests/templated_message_date_fields.test.d.ts +3 -0
- package/lib/esm/tests/api_tests/templated_message_date_fields.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/templated_message_date_fields.test.js +198 -0
- package/lib/esm/tests/api_tests/templated_message_date_fields.test.js.map +1 -0
- package/lib/esm/tests/api_tests/templated_message_link_in_href.test.d.ts +3 -0
- package/lib/esm/tests/api_tests/templated_message_link_in_href.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/templated_message_link_in_href.test.js +229 -0
- package/lib/esm/tests/api_tests/templated_message_link_in_href.test.js.map +1 -0
- package/lib/esm/tests/api_tests/templated_message_links.test.d.ts +3 -0
- package/lib/esm/tests/api_tests/templated_message_links.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/templated_message_links.test.js +231 -0
- package/lib/esm/tests/api_tests/templated_message_links.test.js.map +1 -0
- package/lib/esm/tests/api_tests/time_tracks.test.js +1 -1
- package/lib/esm/tests/api_tests/time_tracks.test.js.map +1 -1
- package/lib/esm/tests/api_tests/trigger_contains_matching.test.d.ts +5 -0
- package/lib/esm/tests/api_tests/trigger_contains_matching.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/trigger_contains_matching.test.js +390 -0
- package/lib/esm/tests/api_tests/trigger_contains_matching.test.js.map +1 -0
- package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.d.ts +5 -0
- package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.js +466 -0
- package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.js.map +1 -0
- package/lib/esm/tests/api_tests/user_portal_settings.test.js +1 -1
- package/lib/esm/tests/api_tests/user_portal_settings.test.js.map +1 -1
- package/lib/esm/tests/api_tests/validation_behavior_locks.test.d.ts +2 -0
- package/lib/esm/tests/api_tests/validation_behavior_locks.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/validation_behavior_locks.test.js +229 -0
- package/lib/esm/tests/api_tests/validation_behavior_locks.test.js.map +1 -0
- package/lib/esm/tests/api_tests/vital_review_trigger_action.test.d.ts +5 -0
- package/lib/esm/tests/api_tests/vital_review_trigger_action.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/vital_review_trigger_action.test.js +564 -0
- package/lib/esm/tests/api_tests/vital_review_trigger_action.test.js.map +1 -0
- package/lib/esm/tests/public_endpoint_tests.js +3 -2
- package/lib/esm/tests/public_endpoint_tests.js.map +1 -1
- package/lib/esm/tests/setup.d.ts +16 -0
- package/lib/esm/tests/setup.d.ts.map +1 -1
- package/lib/esm/tests/setup.js +53 -7
- package/lib/esm/tests/setup.js.map +1 -1
- package/lib/esm/tests/setup_isolated.d.ts +9 -0
- package/lib/esm/tests/setup_isolated.d.ts.map +1 -1
- package/lib/esm/tests/setup_isolated.js +21 -1
- package/lib/esm/tests/setup_isolated.js.map +1 -1
- package/lib/esm/tests/socket_tests.d.ts.map +1 -1
- package/lib/esm/tests/socket_tests.js +3 -2
- package/lib/esm/tests/socket_tests.js.map +1 -1
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +244 -216
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/esm/tests/unit_tests/trigger_title_partials.test.d.ts +3 -0
- package/lib/esm/tests/unit_tests/trigger_title_partials.test.d.ts.map +1 -0
- package/lib/esm/tests/unit_tests/trigger_title_partials.test.js +115 -0
- package/lib/esm/tests/unit_tests/trigger_title_partials.test.js.map +1 -0
- package/lib/esm/tests/webhooks_tests.js +3 -2
- package/lib/esm/tests/webhooks_tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -19
- package/src/sdk.ts +11 -1
- package/src/tests/api_tests/active_patient_count.test.ts +1 -1
- package/src/tests/api_tests/appointment_rescheduled_trigger.test.ts +1 -1
- package/src/tests/api_tests/calendar_event_references_update.test.ts +1 -1
- package/src/tests/api_tests/enduser_cross_access_isolation.test.ts +1 -1
- package/src/tests/api_tests/enduser_fields_sync.test.ts +150 -0
- package/src/tests/api_tests/enduser_login_rate_limits.test.ts +7 -7
- package/src/tests/api_tests/enduser_session_invalidation.test.ts +4 -4
- package/src/tests/api_tests/load_threads_care_team.test.ts +210 -0
- package/src/tests/api_tests/managed_content_enduser_access.test.ts +1 -1
- package/src/tests/api_tests/managed_content_file_access.test.ts +1 -1
- package/src/tests/api_tests/mdi_case_offerings.test.ts +138 -0
- package/src/tests/api_tests/mdi_webhooks.test.ts +9 -0
- package/src/tests/api_tests/nutrition_tracking.test.ts +1 -1
- package/src/tests/api_tests/openloop_webhooks.test.ts +1 -1
- package/src/tests/api_tests/security/add-to-journey-foreign-enduserid.test.ts +33 -26
- package/src/tests/api_tests/security/allowed-paths-confinement.test.ts +1 -1
- package/src/tests/api_tests/security/appointment-reschedule-ownership.test.ts +432 -0
- package/src/tests/api_tests/security/booking-info-idor-token-mint.test.ts +1 -1
- package/src/tests/api_tests/security/enduser-ai-summary-trust-gate.test.ts +1 -1
- package/src/tests/api_tests/security/enduser-cross-create.test.ts +1 -1
- package/src/tests/api_tests/security/enduser-write-restrictions.test.ts +1 -1
- package/src/tests/api_tests/security/invite-user-enumeration.test.ts +3 -3
- package/src/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.ts +197 -0
- package/src/tests/api_tests/security/sanitize-user-html-with-iframes.test.ts +4 -1
- package/src/tests/api_tests/templated_message_date_fields.test.ts +146 -0
- package/src/tests/api_tests/templated_message_links.test.ts +192 -0
- package/src/tests/api_tests/time_tracks.test.ts +1 -1
- package/src/tests/api_tests/trigger_contains_matching.test.ts +345 -0
- package/src/tests/api_tests/user_logs_restore_deleted.test.ts +415 -0
- package/src/tests/api_tests/user_portal_settings.test.ts +1 -1
- package/src/tests/api_tests/validation_behavior_locks.test.ts +204 -0
- package/src/tests/public_endpoint_tests.ts +3 -2
- package/src/tests/setup.ts +43 -7
- package/src/tests/setup_isolated.ts +10 -0
- package/src/tests/socket_tests.ts +3 -2
- package/src/tests/tests.ts +22 -2
- package/src/tests/unit_tests/trigger_title_partials.test.ts +174 -0
- package/src/tests/webhooks_tests.ts +4 -2
- package/test_generated.pdf +0 -0
- 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
|
|
157
|
-
const moduleOwn = await
|
|
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
|
|
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',
|