@tellescope/sdk 2.0.0-beta.0 → 2.0.0-beta.2
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 +24 -0
- package/env.example +6 -0
- package/lib/cjs/sdk.d.ts +376 -3
- package/lib/cjs/sdk.d.ts.map +1 -1
- package/lib/cjs/sdk.js +1 -0
- package/lib/cjs/sdk.js.map +1 -1
- package/lib/cjs/tests/api_tests/booking_prevent_upcoming_duplicate.test.d.ts +22 -0
- package/lib/cjs/tests/api_tests/booking_prevent_upcoming_duplicate.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/booking_prevent_upcoming_duplicate.test.js +506 -0
- package/lib/cjs/tests/api_tests/booking_prevent_upcoming_duplicate.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_fields_sync.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/enduser_fields_sync.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/enduser_fields_sync.test.js +3 -1
- package/lib/cjs/tests/api_tests/enduser_fields_sync.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.js +3 -1
- package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/form_vital_reading.test.d.ts +7 -0
- package/lib/cjs/tests/api_tests/form_vital_reading.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/form_vital_reading.test.js +461 -0
- package/lib/cjs/tests/api_tests/form_vital_reading.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/journey_statistics_cache.test.d.ts +26 -0
- package/lib/cjs/tests/api_tests/journey_statistics_cache.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/journey_statistics_cache.test.js +232 -0
- package/lib/cjs/tests/api_tests/journey_statistics_cache.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/journey_step_manual_count.test.d.ts +34 -0
- package/lib/cjs/tests/api_tests/journey_step_manual_count.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/journey_step_manual_count.test.js +243 -0
- package/lib/cjs/tests/api_tests/journey_step_manual_count.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/load_threads_care_team.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/load_threads_care_team.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/load_threads_care_team.test.js +3 -1
- package/lib/cjs/tests/api_tests/load_threads_care_team.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/organization_signup.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/organization_signup.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/organization_signup.test.js +3 -1
- package/lib/cjs/tests/api_tests/organization_signup.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/phone_embed_leave_message.test.d.ts +7 -0
- package/lib/cjs/tests/api_tests/phone_embed_leave_message.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/phone_embed_leave_message.test.js +571 -0
- package/lib/cjs/tests/api_tests/phone_embed_leave_message.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/programs.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/programs.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/programs.test.js +73 -17
- package/lib/cjs/tests/api_tests/programs.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/public_form_case_insensitive_match.test.d.ts +7 -0
- package/lib/cjs/tests/api_tests/public_form_case_insensitive_match.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/public_form_case_insensitive_match.test.js +733 -0
- package/lib/cjs/tests/api_tests/public_form_case_insensitive_match.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts +3 -1
- 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 +58 -48
- package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.js +3 -1
- package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.js +3 -1
- package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.js +3 -1
- package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/formsort_webhook_auth_field_lock.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js +424 -39
- package/lib/cjs/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/register_business_id_injection.test.js +2 -2
- package/lib/cjs/tests/api_tests/security/register_business_id_injection.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js +3 -1
- package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/session_for_join_link.test.d.ts +10 -0
- package/lib/cjs/tests/api_tests/session_for_join_link.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/session_for_join_link.test.js +147 -0
- package/lib/cjs/tests/api_tests/session_for_join_link.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/set_fields_order_templates.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/set_fields_order_templates.test.js +191 -88
- package/lib/cjs/tests/api_tests/set_fields_order_templates.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/stripe_checkout_items.test.d.ts +17 -0
- package/lib/cjs/tests/api_tests/stripe_checkout_items.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/stripe_checkout_items.test.js +219 -0
- package/lib/cjs/tests/api_tests/stripe_checkout_items.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/stripe_multiple_customer_ids.test.d.ts +5 -0
- package/lib/cjs/tests/api_tests/stripe_multiple_customer_ids.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/stripe_multiple_customer_ids.test.js +396 -0
- package/lib/cjs/tests/api_tests/stripe_multiple_customer_ids.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.js +3 -1
- package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/totp_mfa.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/totp_mfa.test.js +37 -31
- package/lib/cjs/tests/api_tests/totp_mfa.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/trigger_contains_matching.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/trigger_contains_matching.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/trigger_contains_matching.test.js +3 -1
- package/lib/cjs/tests/api_tests/trigger_contains_matching.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.js +3 -1
- package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.d.ts +3 -1
- package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.js +3 -1
- package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/vitl_push.test.d.ts +7 -0
- package/lib/cjs/tests/api_tests/vitl_push.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/vitl_push.test.js +341 -0
- package/lib/cjs/tests/api_tests/vitl_push.test.js.map +1 -0
- package/lib/cjs/tests/setup_isolated.d.ts +48 -0
- package/lib/cjs/tests/setup_isolated.d.ts.map +1 -1
- package/lib/cjs/tests/setup_isolated.js +119 -1
- package/lib/cjs/tests/setup_isolated.js.map +1 -1
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +378 -282
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/cjs/tests/unit_tests/isolated_suite_discovery.test.d.ts +2 -0
- package/lib/cjs/tests/unit_tests/isolated_suite_discovery.test.d.ts.map +1 -0
- package/lib/cjs/tests/unit_tests/isolated_suite_discovery.test.js +201 -0
- package/lib/cjs/tests/unit_tests/isolated_suite_discovery.test.js.map +1 -0
- package/lib/cjs/tests/unit_tests/programs_conditional_logic.test.d.ts +3 -0
- package/lib/cjs/tests/unit_tests/programs_conditional_logic.test.d.ts.map +1 -0
- package/lib/cjs/tests/unit_tests/programs_conditional_logic.test.js +120 -0
- package/lib/cjs/tests/unit_tests/programs_conditional_logic.test.js.map +1 -0
- package/lib/cjs/tests/webhooks_tests.js +44 -34
- package/lib/cjs/tests/webhooks_tests.js.map +1 -1
- package/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/esm/sdk.d.ts +376 -3
- package/lib/esm/sdk.d.ts.map +1 -1
- package/lib/esm/sdk.js +1 -0
- package/lib/esm/sdk.js.map +1 -1
- package/lib/esm/tests/api_tests/booking_prevent_upcoming_duplicate.test.d.ts +22 -0
- package/lib/esm/tests/api_tests/booking_prevent_upcoming_duplicate.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/booking_prevent_upcoming_duplicate.test.js +501 -0
- package/lib/esm/tests/api_tests/booking_prevent_upcoming_duplicate.test.js.map +1 -0
- package/lib/esm/tests/api_tests/enduser_fields_sync.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/enduser_fields_sync.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/enduser_fields_sync.test.js +2 -0
- package/lib/esm/tests/api_tests/enduser_fields_sync.test.js.map +1 -1
- package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.js +2 -0
- package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.js.map +1 -1
- package/lib/esm/tests/api_tests/form_vital_reading.test.d.ts +7 -0
- package/lib/esm/tests/api_tests/form_vital_reading.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/form_vital_reading.test.js +456 -0
- package/lib/esm/tests/api_tests/form_vital_reading.test.js.map +1 -0
- package/lib/esm/tests/api_tests/journey_statistics_cache.test.d.ts +26 -0
- package/lib/esm/tests/api_tests/journey_statistics_cache.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/journey_statistics_cache.test.js +227 -0
- package/lib/esm/tests/api_tests/journey_statistics_cache.test.js.map +1 -0
- package/lib/esm/tests/api_tests/journey_step_manual_count.test.d.ts +34 -0
- package/lib/esm/tests/api_tests/journey_step_manual_count.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/journey_step_manual_count.test.js +238 -0
- package/lib/esm/tests/api_tests/journey_step_manual_count.test.js.map +1 -0
- package/lib/esm/tests/api_tests/load_threads_care_team.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/load_threads_care_team.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/load_threads_care_team.test.js +2 -0
- package/lib/esm/tests/api_tests/load_threads_care_team.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/organization_signup.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/organization_signup.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/organization_signup.test.js +2 -0
- package/lib/esm/tests/api_tests/organization_signup.test.js.map +1 -1
- package/lib/esm/tests/api_tests/phone_embed_leave_message.test.d.ts +7 -0
- package/lib/esm/tests/api_tests/phone_embed_leave_message.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/phone_embed_leave_message.test.js +566 -0
- package/lib/esm/tests/api_tests/phone_embed_leave_message.test.js.map +1 -0
- package/lib/esm/tests/api_tests/programs.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/programs.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/programs.test.js +72 -16
- package/lib/esm/tests/api_tests/programs.test.js.map +1 -1
- package/lib/esm/tests/api_tests/public_form_case_insensitive_match.test.d.ts +7 -0
- package/lib/esm/tests/api_tests/public_form_case_insensitive_match.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/public_form_case_insensitive_match.test.js +728 -0
- package/lib/esm/tests/api_tests/public_form_case_insensitive_match.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts +3 -1
- 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 +57 -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/appointment-reschedule-ownership.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.js +2 -0
- package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.js +2 -0
- package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.js +2 -0
- package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/formsort_webhook_auth_field_lock.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js +424 -39
- package/lib/esm/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/register_business_id_injection.test.js +2 -2
- package/lib/esm/tests/api_tests/security/register_business_id_injection.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js +2 -0
- package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js.map +1 -1
- package/lib/esm/tests/api_tests/session_for_join_link.test.d.ts +10 -0
- package/lib/esm/tests/api_tests/session_for_join_link.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/session_for_join_link.test.js +142 -0
- package/lib/esm/tests/api_tests/session_for_join_link.test.js.map +1 -0
- package/lib/esm/tests/api_tests/set_fields_order_templates.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/set_fields_order_templates.test.js +191 -88
- package/lib/esm/tests/api_tests/set_fields_order_templates.test.js.map +1 -1
- package/lib/esm/tests/api_tests/stripe_checkout_items.test.d.ts +17 -0
- package/lib/esm/tests/api_tests/stripe_checkout_items.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/stripe_checkout_items.test.js +214 -0
- package/lib/esm/tests/api_tests/stripe_checkout_items.test.js.map +1 -0
- package/lib/esm/tests/api_tests/stripe_multiple_customer_ids.test.d.ts +5 -0
- package/lib/esm/tests/api_tests/stripe_multiple_customer_ids.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/stripe_multiple_customer_ids.test.js +388 -0
- package/lib/esm/tests/api_tests/stripe_multiple_customer_ids.test.js.map +1 -0
- package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.js +2 -0
- package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.js.map +1 -1
- package/lib/esm/tests/api_tests/totp_mfa.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/totp_mfa.test.js +37 -31
- package/lib/esm/tests/api_tests/totp_mfa.test.js.map +1 -1
- package/lib/esm/tests/api_tests/trigger_contains_matching.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/trigger_contains_matching.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/trigger_contains_matching.test.js +2 -0
- package/lib/esm/tests/api_tests/trigger_contains_matching.test.js.map +1 -1
- package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.js +2 -0
- package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.js.map +1 -1
- package/lib/esm/tests/api_tests/vital_review_trigger_action.test.d.ts +3 -1
- package/lib/esm/tests/api_tests/vital_review_trigger_action.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/vital_review_trigger_action.test.js +2 -0
- package/lib/esm/tests/api_tests/vital_review_trigger_action.test.js.map +1 -1
- package/lib/esm/tests/api_tests/vitl_push.test.d.ts +7 -0
- package/lib/esm/tests/api_tests/vitl_push.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/vitl_push.test.js +333 -0
- package/lib/esm/tests/api_tests/vitl_push.test.js.map +1 -0
- package/lib/esm/tests/setup_isolated.d.ts +48 -0
- package/lib/esm/tests/setup_isolated.d.ts.map +1 -1
- package/lib/esm/tests/setup_isolated.js +114 -0
- package/lib/esm/tests/setup_isolated.js.map +1 -1
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +379 -283
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/esm/tests/unit_tests/isolated_suite_discovery.test.d.ts +2 -0
- package/lib/esm/tests/unit_tests/isolated_suite_discovery.test.d.ts.map +1 -0
- package/lib/esm/tests/unit_tests/isolated_suite_discovery.test.js +174 -0
- package/lib/esm/tests/unit_tests/isolated_suite_discovery.test.js.map +1 -0
- package/lib/esm/tests/unit_tests/programs_conditional_logic.test.d.ts +3 -0
- package/lib/esm/tests/unit_tests/programs_conditional_logic.test.d.ts.map +1 -0
- package/lib/esm/tests/unit_tests/programs_conditional_logic.test.js +117 -0
- package/lib/esm/tests/unit_tests/programs_conditional_logic.test.js.map +1 -0
- package/lib/esm/tests/webhooks_tests.js +44 -34
- package/lib/esm/tests/webhooks_tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -11
- package/src/sdk.ts +9 -2
- package/src/tests/api_tests/booking_prevent_upcoming_duplicate.test.ts +541 -0
- package/src/tests/api_tests/enduser_fields_sync.test.ts +154 -0
- package/src/tests/api_tests/enduser_observations_auto_review.test.ts +4 -0
- package/src/tests/api_tests/form_vital_reading.test.ts +393 -0
- package/src/tests/api_tests/journey_statistics_cache.test.ts +237 -0
- package/src/tests/api_tests/journey_step_manual_count.test.ts +220 -0
- package/src/tests/api_tests/load_threads_care_team.test.ts +214 -0
- package/src/tests/api_tests/mdi_case_offerings.test.ts +138 -0
- package/src/tests/api_tests/organization_signup.test.ts +4 -0
- package/src/tests/api_tests/phone_embed_leave_message.test.ts +541 -0
- package/src/tests/api_tests/programs.test.ts +351 -0
- package/src/tests/api_tests/public_form_case_insensitive_match.test.ts +632 -0
- package/src/tests/api_tests/security/add-to-journey-foreign-enduserid.test.ts +37 -26
- package/src/tests/api_tests/security/appointment-reschedule-ownership.test.ts +436 -0
- package/src/tests/api_tests/security/file-link-session-confinement.test.ts +4 -0
- package/src/tests/api_tests/security/form-logic-js-execution.test.ts +4 -0
- package/src/tests/api_tests/security/formsort_webhook_auth_field_lock.test.ts +225 -0
- package/src/tests/api_tests/security/register_business_id_injection.test.ts +2 -2
- package/src/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.ts +4 -0
- package/src/tests/api_tests/session_for_join_link.test.ts +99 -0
- package/src/tests/api_tests/set_fields_order_templates.test.ts +94 -9
- package/src/tests/api_tests/stripe_checkout_items.test.ts +186 -0
- package/src/tests/api_tests/tickets_bulk_assign_from_queue.test.ts +4 -0
- package/src/tests/api_tests/totp_mfa.test.ts +10 -5
- package/src/tests/api_tests/trigger_contains_matching.test.ts +349 -0
- package/src/tests/api_tests/user_logs_restore_deleted.test.ts +419 -0
- package/src/tests/api_tests/vital_review_trigger_action.test.ts +455 -0
- package/src/tests/api_tests/vitl_push.test.ts +323 -0
- package/src/tests/setup_isolated.ts +140 -0
- package/src/tests/tests.ts +126 -20
- package/src/tests/unit_tests/isolated_suite_discovery.test.ts +178 -0
- package/src/tests/unit_tests/programs_conditional_logic.test.ts +189 -0
- package/src/tests/unit_tests/trigger_title_partials.test.ts +174 -0
- package/src/tests/webhooks_tests.ts +6 -1
- package/test_generated.pdf +0 -0
|
@@ -105,6 +105,19 @@ var host = process.env.API_URL || 'http://localhost:8080';
|
|
|
105
105
|
* R14 both grace markers are load-bearing: neither source nor stripeCustomerId alone opens it
|
|
106
106
|
* R15 the grace is per-request — it does not clear the stored flag
|
|
107
107
|
*
|
|
108
|
+
* ?alwaysSetPhone=true (CU-86e3k4ptv) is a second per-request override, narrower than ?enduserId=:
|
|
109
|
+
* it allows PHONE ONLY through the lock, on every finalized webhook, overwriting an existing and
|
|
110
|
+
* different number. Email — the password-reset channel this lock exists to protect — stays blocked.
|
|
111
|
+
* G16 (GREEN) the flag overwrites an existing, different phone on a guessed match
|
|
112
|
+
* G17 (GREEN) ...and in that same request the submitted email is still dropped
|
|
113
|
+
* R16 (RED) the identical request WITHOUT the flag leaves both phone and email blocked
|
|
114
|
+
* R17 (RED) the flag does not open email on a phone match either
|
|
115
|
+
* R18 (RED) only the literal string 'true' enables it — ?alwaysSetPhone=1 keeps the lock
|
|
116
|
+
* G18 (GREEN) a flagged webhook still stamps authFieldIntakeDisabled on the response, so later
|
|
117
|
+
* writes through save_enduser_updates_for_form_response stay blocked
|
|
118
|
+
* R19 (RED) it is request-scoped: a flag passed on an earlier webhook for the same
|
|
119
|
+
* responder_uuid does not unlock a later one that omits it
|
|
120
|
+
*
|
|
108
121
|
* The Stripe grace is deliberately confined to THIS endpoint, which is API-key authenticated. The
|
|
109
122
|
* anonymous public-form path gets no exemption; that boundary is pinned by G28 in
|
|
110
123
|
* public_endpoint_auth_field_lock.test.ts.
|
|
@@ -192,6 +205,8 @@ export var formsort_webhook_auth_field_lock_tests = function (_a) {
|
|
|
192
205
|
url.searchParams.set('enduserId', o.enduserId);
|
|
193
206
|
if (o.createNewEnduser)
|
|
194
207
|
url.searchParams.set('createNewEnduser', 'true');
|
|
208
|
+
if (o.alwaysSetPhone !== undefined)
|
|
209
|
+
url.searchParams.set('alwaysSetPhone', o.alwaysSetPhone);
|
|
195
210
|
return [4 /*yield*/, axios.post(url.toString(), { answers: o.answers, responder_uuid: uuidFor(o.label), finalized: o.finalized }, { validateStatus: function () { return true; } })
|
|
196
211
|
// In-progress webhooks always return a bare 200 (the handler returns before the returnJSON
|
|
197
212
|
// block), so `data` is only populated for finalized calls.
|
|
@@ -1064,7 +1079,10 @@ export var formsort_webhook_auth_field_lock_tests = function (_a) {
|
|
|
1064
1079
|
});
|
|
1065
1080
|
}); })
|
|
1066
1081
|
// ---------------------------------------------------------------------------------------------
|
|
1067
|
-
//
|
|
1082
|
+
// G16 — ?alwaysSetPhone=true: the opt-in allows phone through the lock on a GUESSED match (the
|
|
1083
|
+
// path R2 blocks), overwriting a phone that is already stored and different. Phone is also the
|
|
1084
|
+
// only field this submission changes, which exercises the "at least one update provided" guard —
|
|
1085
|
+
// if the delete happened before that guard, nothing would be written at all.
|
|
1068
1086
|
// ---------------------------------------------------------------------------------------------
|
|
1069
1087
|
];
|
|
1070
1088
|
case 20:
|
|
@@ -1075,6 +1093,373 @@ export var formsort_webhook_auth_field_lock_tests = function (_a) {
|
|
|
1075
1093
|
// after the window closes) stays protected.
|
|
1076
1094
|
// ---------------------------------------------------------------------------------------------
|
|
1077
1095
|
_h.sent();
|
|
1096
|
+
// ---------------------------------------------------------------------------------------------
|
|
1097
|
+
// G16 — ?alwaysSetPhone=true: the opt-in allows phone through the lock on a GUESSED match (the
|
|
1098
|
+
// path R2 blocks), overwriting a phone that is already stored and different. Phone is also the
|
|
1099
|
+
// only field this submission changes, which exercises the "at least one update provided" guard —
|
|
1100
|
+
// if the delete happened before that guard, nothing would be written at all.
|
|
1101
|
+
// ---------------------------------------------------------------------------------------------
|
|
1102
|
+
return [4 /*yield*/, runScenario('G16', 'alwaysSetPhone=true overwrites an existing phone on a guessed match', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1103
|
+
var email, originalPhone, victim, intakePhone, data, enduser;
|
|
1104
|
+
return __generator(this, function (_a) {
|
|
1105
|
+
switch (_a.label) {
|
|
1106
|
+
case 0:
|
|
1107
|
+
email = emailFor('g16');
|
|
1108
|
+
originalPhone = nextPhone();
|
|
1109
|
+
return [4 /*yield*/, makeVictim('g16', { email: email, phone: originalPhone })];
|
|
1110
|
+
case 1:
|
|
1111
|
+
victim = _a.sent();
|
|
1112
|
+
intakePhone = nextPhone();
|
|
1113
|
+
return [4 /*yield*/, postWebhook({
|
|
1114
|
+
label: 'g16',
|
|
1115
|
+
finalized: true,
|
|
1116
|
+
alwaysSetPhone: 'true',
|
|
1117
|
+
answers: [{ key: 'email', value: email }, { key: 'phone', value: intakePhone }],
|
|
1118
|
+
})];
|
|
1119
|
+
case 2:
|
|
1120
|
+
data = (_a.sent()).data;
|
|
1121
|
+
if (!matched('G16', 'alwaysSetPhone=true overwrites an existing phone on a guessed match', data, victim.id))
|
|
1122
|
+
return [2 /*return*/];
|
|
1123
|
+
return [4 /*yield*/, pollEnduser(victim.id, function (e) { return e.phone === intakePhone; })];
|
|
1124
|
+
case 3:
|
|
1125
|
+
enduser = _a.sent();
|
|
1126
|
+
record('G16', 'alwaysSetPhone=true overwrites an existing phone on a guessed match', (enduser === null || enduser === void 0 ? void 0 : enduser.phone) === intakePhone, "phone=".concat((enduser === null || enduser === void 0 ? void 0 : enduser.phone) || '(unset)', " expected=").concat(intakePhone));
|
|
1127
|
+
return [2 /*return*/];
|
|
1128
|
+
}
|
|
1129
|
+
});
|
|
1130
|
+
}); })
|
|
1131
|
+
// ---------------------------------------------------------------------------------------------
|
|
1132
|
+
// G17 — the same request, with BOTH a new phone and a different email, so the two halves of the
|
|
1133
|
+
// rule are observed together: phone lands, email does not. Shaped like R3 (a draft formed by a
|
|
1134
|
+
// guess, finalized through the sticky flag) because that is the only resolution path where the
|
|
1135
|
+
// submitted email can differ from the stored one while the patient still matches.
|
|
1136
|
+
// ---------------------------------------------------------------------------------------------
|
|
1137
|
+
];
|
|
1138
|
+
case 21:
|
|
1139
|
+
// ---------------------------------------------------------------------------------------------
|
|
1140
|
+
// G16 — ?alwaysSetPhone=true: the opt-in allows phone through the lock on a GUESSED match (the
|
|
1141
|
+
// path R2 blocks), overwriting a phone that is already stored and different. Phone is also the
|
|
1142
|
+
// only field this submission changes, which exercises the "at least one update provided" guard —
|
|
1143
|
+
// if the delete happened before that guard, nothing would be written at all.
|
|
1144
|
+
// ---------------------------------------------------------------------------------------------
|
|
1145
|
+
_h.sent();
|
|
1146
|
+
// ---------------------------------------------------------------------------------------------
|
|
1147
|
+
// G17 — the same request, with BOTH a new phone and a different email, so the two halves of the
|
|
1148
|
+
// rule are observed together: phone lands, email does not. Shaped like R3 (a draft formed by a
|
|
1149
|
+
// guess, finalized through the sticky flag) because that is the only resolution path where the
|
|
1150
|
+
// submitted email can differ from the stored one while the patient still matches.
|
|
1151
|
+
// ---------------------------------------------------------------------------------------------
|
|
1152
|
+
return [4 /*yield*/, runScenario('G17', 'alwaysSetPhone=true writes phone and still drops email', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1153
|
+
var originalEmail, originalPhone, victim, attackerEmail, intakePhone, data, enduser;
|
|
1154
|
+
return __generator(this, function (_a) {
|
|
1155
|
+
switch (_a.label) {
|
|
1156
|
+
case 0:
|
|
1157
|
+
originalEmail = emailFor('g17');
|
|
1158
|
+
originalPhone = nextPhone();
|
|
1159
|
+
return [4 /*yield*/, makeVictim('g17', { email: originalEmail, phone: originalPhone })];
|
|
1160
|
+
case 1:
|
|
1161
|
+
victim = _a.sent();
|
|
1162
|
+
attackerEmail = emailFor('g17-attacker');
|
|
1163
|
+
intakePhone = nextPhone();
|
|
1164
|
+
// draft matches the pre-existing patient by phone -> authFieldIntakeDisabled is stamped on it
|
|
1165
|
+
return [4 /*yield*/, postWebhook({ label: 'g17', finalized: false, answers: [{ key: 'phone', value: originalPhone }] })];
|
|
1166
|
+
case 2:
|
|
1167
|
+
// draft matches the pre-existing patient by phone -> authFieldIntakeDisabled is stamped on it
|
|
1168
|
+
_a.sent();
|
|
1169
|
+
return [4 /*yield*/, postWebhook({
|
|
1170
|
+
label: 'g17',
|
|
1171
|
+
finalized: true,
|
|
1172
|
+
alwaysSetPhone: 'true',
|
|
1173
|
+
answers: [{ key: 'phone', value: intakePhone }, { key: 'email', value: attackerEmail }],
|
|
1174
|
+
})];
|
|
1175
|
+
case 3:
|
|
1176
|
+
data = (_a.sent()).data;
|
|
1177
|
+
if (!matched('G17', 'alwaysSetPhone=true writes phone and still drops email', data, victim.id))
|
|
1178
|
+
return [2 /*return*/];
|
|
1179
|
+
return [4 /*yield*/, pollEnduser(victim.id, function (e) { return e.phone === intakePhone; })];
|
|
1180
|
+
case 4:
|
|
1181
|
+
enduser = _a.sent();
|
|
1182
|
+
record('G17', 'alwaysSetPhone=true writes phone through the sticky flag', (enduser === null || enduser === void 0 ? void 0 : enduser.phone) === intakePhone, "phone=".concat((enduser === null || enduser === void 0 ? void 0 : enduser.phone) || '(unset)', " expected=").concat(intakePhone));
|
|
1183
|
+
record('G17', 'alwaysSetPhone=true leaves email blocked in the same request', (enduser === null || enduser === void 0 ? void 0 : enduser.email) === originalEmail, "email=".concat((enduser === null || enduser === void 0 ? void 0 : enduser.email) || '(unset)', " expected=").concat(originalEmail));
|
|
1184
|
+
return [2 /*return*/];
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1187
|
+
}); })
|
|
1188
|
+
// ---------------------------------------------------------------------------------------------
|
|
1189
|
+
// R16 — the control for G17: byte-identical request without the flag. Both fields stay blocked,
|
|
1190
|
+
// i.e. the default behavior is unchanged.
|
|
1191
|
+
// ---------------------------------------------------------------------------------------------
|
|
1192
|
+
];
|
|
1193
|
+
case 22:
|
|
1194
|
+
// ---------------------------------------------------------------------------------------------
|
|
1195
|
+
// G17 — the same request, with BOTH a new phone and a different email, so the two halves of the
|
|
1196
|
+
// rule are observed together: phone lands, email does not. Shaped like R3 (a draft formed by a
|
|
1197
|
+
// guess, finalized through the sticky flag) because that is the only resolution path where the
|
|
1198
|
+
// submitted email can differ from the stored one while the patient still matches.
|
|
1199
|
+
// ---------------------------------------------------------------------------------------------
|
|
1200
|
+
_h.sent();
|
|
1201
|
+
// ---------------------------------------------------------------------------------------------
|
|
1202
|
+
// R16 — the control for G17: byte-identical request without the flag. Both fields stay blocked,
|
|
1203
|
+
// i.e. the default behavior is unchanged.
|
|
1204
|
+
// ---------------------------------------------------------------------------------------------
|
|
1205
|
+
return [4 /*yield*/, runScenario('R16', 'without the flag the same request blocks phone and email', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1206
|
+
var originalEmail, originalPhone, victim, attackerEmail, intakePhone, data, enduser;
|
|
1207
|
+
return __generator(this, function (_a) {
|
|
1208
|
+
switch (_a.label) {
|
|
1209
|
+
case 0:
|
|
1210
|
+
originalEmail = emailFor('r16');
|
|
1211
|
+
originalPhone = nextPhone();
|
|
1212
|
+
return [4 /*yield*/, makeVictim('r16', { email: originalEmail, phone: originalPhone })];
|
|
1213
|
+
case 1:
|
|
1214
|
+
victim = _a.sent();
|
|
1215
|
+
attackerEmail = emailFor('r16-attacker');
|
|
1216
|
+
intakePhone = nextPhone();
|
|
1217
|
+
return [4 /*yield*/, postWebhook({ label: 'r16', finalized: false, answers: [{ key: 'phone', value: originalPhone }] })];
|
|
1218
|
+
case 2:
|
|
1219
|
+
_a.sent();
|
|
1220
|
+
return [4 /*yield*/, postWebhook({
|
|
1221
|
+
label: 'r16',
|
|
1222
|
+
finalized: true,
|
|
1223
|
+
answers: [{ key: 'phone', value: intakePhone }, { key: 'email', value: attackerEmail }],
|
|
1224
|
+
})];
|
|
1225
|
+
case 3:
|
|
1226
|
+
data = (_a.sent()).data;
|
|
1227
|
+
if (!matched('R16', 'without the flag the same request blocks phone and email', data, victim.id))
|
|
1228
|
+
return [2 /*return*/];
|
|
1229
|
+
return [4 /*yield*/, pollEnduser(victim.id, function (e) { return e.phone === intakePhone || e.email === attackerEmail; })];
|
|
1230
|
+
case 4:
|
|
1231
|
+
enduser = _a.sent();
|
|
1232
|
+
record('R16', 'without the flag phone stays blocked', (enduser === null || enduser === void 0 ? void 0 : enduser.phone) === originalPhone, "phone=".concat((enduser === null || enduser === void 0 ? void 0 : enduser.phone) || '(unset)', " expected=").concat(originalPhone));
|
|
1233
|
+
record('R16', 'without the flag email stays blocked', (enduser === null || enduser === void 0 ? void 0 : enduser.email) === originalEmail, "email=".concat((enduser === null || enduser === void 0 ? void 0 : enduser.email) || '(unset)', " expected=").concat(originalEmail));
|
|
1234
|
+
return [2 /*return*/];
|
|
1235
|
+
}
|
|
1236
|
+
});
|
|
1237
|
+
}); })
|
|
1238
|
+
// ---------------------------------------------------------------------------------------------
|
|
1239
|
+
// R17 — the flag is phone-only in BOTH match directions: matched on phone (R1's shape), the
|
|
1240
|
+
// submitted email must still not land.
|
|
1241
|
+
// ---------------------------------------------------------------------------------------------
|
|
1242
|
+
];
|
|
1243
|
+
case 23:
|
|
1244
|
+
// ---------------------------------------------------------------------------------------------
|
|
1245
|
+
// R16 — the control for G17: byte-identical request without the flag. Both fields stay blocked,
|
|
1246
|
+
// i.e. the default behavior is unchanged.
|
|
1247
|
+
// ---------------------------------------------------------------------------------------------
|
|
1248
|
+
_h.sent();
|
|
1249
|
+
// ---------------------------------------------------------------------------------------------
|
|
1250
|
+
// R17 — the flag is phone-only in BOTH match directions: matched on phone (R1's shape), the
|
|
1251
|
+
// submitted email must still not land.
|
|
1252
|
+
// ---------------------------------------------------------------------------------------------
|
|
1253
|
+
return [4 /*yield*/, runScenario('R17', 'alwaysSetPhone=true does not repoint email on a phone match', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1254
|
+
var originalEmail, phone, victim, attackerEmail, data, enduser;
|
|
1255
|
+
return __generator(this, function (_a) {
|
|
1256
|
+
switch (_a.label) {
|
|
1257
|
+
case 0:
|
|
1258
|
+
originalEmail = emailFor('r17');
|
|
1259
|
+
phone = nextPhone();
|
|
1260
|
+
return [4 /*yield*/, makeVictim('r17', { email: originalEmail, phone: phone })];
|
|
1261
|
+
case 1:
|
|
1262
|
+
victim = _a.sent();
|
|
1263
|
+
attackerEmail = emailFor('r17-attacker');
|
|
1264
|
+
return [4 /*yield*/, postWebhook({
|
|
1265
|
+
label: 'r17',
|
|
1266
|
+
finalized: true,
|
|
1267
|
+
alwaysSetPhone: 'true',
|
|
1268
|
+
answers: [{ key: 'phone', value: phone }, { key: 'email', value: attackerEmail }],
|
|
1269
|
+
})];
|
|
1270
|
+
case 2:
|
|
1271
|
+
data = (_a.sent()).data;
|
|
1272
|
+
if (!matched('R17', 'alwaysSetPhone=true does not repoint email on a phone match', data, victim.id))
|
|
1273
|
+
return [2 /*return*/];
|
|
1274
|
+
return [4 /*yield*/, pollEnduser(victim.id, function (e) { return e.email === attackerEmail; })];
|
|
1275
|
+
case 3:
|
|
1276
|
+
enduser = _a.sent();
|
|
1277
|
+
record('R17', 'alwaysSetPhone=true does not repoint email on a phone match', (enduser === null || enduser === void 0 ? void 0 : enduser.email) === originalEmail, "email=".concat((enduser === null || enduser === void 0 ? void 0 : enduser.email) || '(unset)', " expected=").concat(originalEmail));
|
|
1278
|
+
return [2 /*return*/];
|
|
1279
|
+
}
|
|
1280
|
+
});
|
|
1281
|
+
}); })
|
|
1282
|
+
// ---------------------------------------------------------------------------------------------
|
|
1283
|
+
// R18 — parsed as === 'true', matching createNewEnduser / matchByName. Any other value, including
|
|
1284
|
+
// a truthy-looking one, keeps today's behavior.
|
|
1285
|
+
// ---------------------------------------------------------------------------------------------
|
|
1286
|
+
];
|
|
1287
|
+
case 24:
|
|
1288
|
+
// ---------------------------------------------------------------------------------------------
|
|
1289
|
+
// R17 — the flag is phone-only in BOTH match directions: matched on phone (R1's shape), the
|
|
1290
|
+
// submitted email must still not land.
|
|
1291
|
+
// ---------------------------------------------------------------------------------------------
|
|
1292
|
+
_h.sent();
|
|
1293
|
+
// ---------------------------------------------------------------------------------------------
|
|
1294
|
+
// R18 — parsed as === 'true', matching createNewEnduser / matchByName. Any other value, including
|
|
1295
|
+
// a truthy-looking one, keeps today's behavior.
|
|
1296
|
+
// ---------------------------------------------------------------------------------------------
|
|
1297
|
+
return [4 /*yield*/, runScenario('R18', 'alwaysSetPhone=1 does not enable the opt-in', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1298
|
+
var email, originalPhone, victim, intakePhone, data, enduser;
|
|
1299
|
+
return __generator(this, function (_a) {
|
|
1300
|
+
switch (_a.label) {
|
|
1301
|
+
case 0:
|
|
1302
|
+
email = emailFor('r18');
|
|
1303
|
+
originalPhone = nextPhone();
|
|
1304
|
+
return [4 /*yield*/, makeVictim('r18', { email: email, phone: originalPhone })];
|
|
1305
|
+
case 1:
|
|
1306
|
+
victim = _a.sent();
|
|
1307
|
+
intakePhone = nextPhone();
|
|
1308
|
+
return [4 /*yield*/, postWebhook({
|
|
1309
|
+
label: 'r18',
|
|
1310
|
+
finalized: true,
|
|
1311
|
+
alwaysSetPhone: '1',
|
|
1312
|
+
answers: [{ key: 'email', value: email }, { key: 'phone', value: intakePhone }],
|
|
1313
|
+
})];
|
|
1314
|
+
case 2:
|
|
1315
|
+
data = (_a.sent()).data;
|
|
1316
|
+
if (!matched('R18', 'alwaysSetPhone=1 does not enable the opt-in', data, victim.id))
|
|
1317
|
+
return [2 /*return*/];
|
|
1318
|
+
return [4 /*yield*/, pollEnduser(victim.id, function (e) { return e.phone === intakePhone; })];
|
|
1319
|
+
case 3:
|
|
1320
|
+
enduser = _a.sent();
|
|
1321
|
+
record('R18', 'alwaysSetPhone=1 does not enable the opt-in', (enduser === null || enduser === void 0 ? void 0 : enduser.phone) === originalPhone, "phone=".concat((enduser === null || enduser === void 0 ? void 0 : enduser.phone) || '(unset)', " expected=").concat(originalPhone));
|
|
1322
|
+
return [2 /*return*/];
|
|
1323
|
+
}
|
|
1324
|
+
});
|
|
1325
|
+
}); })
|
|
1326
|
+
// ---------------------------------------------------------------------------------------------
|
|
1327
|
+
// G18 — the opt-in is a per-REQUEST allow, exactly like G11 (?enduserId=) and R15 (the Stripe
|
|
1328
|
+
// grace): the response still records that it attached to a pre-existing patient, so the other
|
|
1329
|
+
// consumer of that flag — save_enduser_updates_for_form_response, reached by later staff edits —
|
|
1330
|
+
// stays protected.
|
|
1331
|
+
// ---------------------------------------------------------------------------------------------
|
|
1332
|
+
];
|
|
1333
|
+
case 25:
|
|
1334
|
+
// ---------------------------------------------------------------------------------------------
|
|
1335
|
+
// R18 — parsed as === 'true', matching createNewEnduser / matchByName. Any other value, including
|
|
1336
|
+
// a truthy-looking one, keeps today's behavior.
|
|
1337
|
+
// ---------------------------------------------------------------------------------------------
|
|
1338
|
+
_h.sent();
|
|
1339
|
+
// ---------------------------------------------------------------------------------------------
|
|
1340
|
+
// G18 — the opt-in is a per-REQUEST allow, exactly like G11 (?enduserId=) and R15 (the Stripe
|
|
1341
|
+
// grace): the response still records that it attached to a pre-existing patient, so the other
|
|
1342
|
+
// consumer of that flag — save_enduser_updates_for_form_response, reached by later staff edits —
|
|
1343
|
+
// stays protected.
|
|
1344
|
+
// ---------------------------------------------------------------------------------------------
|
|
1345
|
+
return [4 /*yield*/, runScenario('G18', 'alwaysSetPhone does not clear the stored flag', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1346
|
+
var email, victim, intakePhone, data, enduser, response;
|
|
1347
|
+
return __generator(this, function (_a) {
|
|
1348
|
+
switch (_a.label) {
|
|
1349
|
+
case 0:
|
|
1350
|
+
email = emailFor('g18');
|
|
1351
|
+
return [4 /*yield*/, makeVictim('g18', { email: email, phone: nextPhone() })];
|
|
1352
|
+
case 1:
|
|
1353
|
+
victim = _a.sent();
|
|
1354
|
+
intakePhone = nextPhone();
|
|
1355
|
+
return [4 /*yield*/, postWebhook({
|
|
1356
|
+
label: 'g18',
|
|
1357
|
+
finalized: true,
|
|
1358
|
+
alwaysSetPhone: 'true',
|
|
1359
|
+
answers: [{ key: 'email', value: email }, { key: 'phone', value: intakePhone }],
|
|
1360
|
+
})];
|
|
1361
|
+
case 2:
|
|
1362
|
+
data = (_a.sent()).data;
|
|
1363
|
+
if (!matched('G18', 'alwaysSetPhone does not clear the stored flag', data, victim.id))
|
|
1364
|
+
return [2 /*return*/];
|
|
1365
|
+
return [4 /*yield*/, pollEnduser(victim.id, function (e) { return e.phone === intakePhone; })];
|
|
1366
|
+
case 3:
|
|
1367
|
+
enduser = _a.sent();
|
|
1368
|
+
record('G18', 'flagged webhook landed the phone (probe precondition)', (enduser === null || enduser === void 0 ? void 0 : enduser.phone) === intakePhone, "phone=".concat((enduser === null || enduser === void 0 ? void 0 : enduser.phone) || '(unset)', " expected=").concat(intakePhone));
|
|
1369
|
+
if (!data.formResponseId) {
|
|
1370
|
+
skip('G18', 'alwaysSetPhone does not clear the stored flag', 'webhook returned no formResponseId');
|
|
1371
|
+
return [2 /*return*/];
|
|
1372
|
+
}
|
|
1373
|
+
return [4 /*yield*/, sdk.api.form_responses.getOne(data.formResponseId).catch(function () { return null; })];
|
|
1374
|
+
case 4:
|
|
1375
|
+
response = _a.sent();
|
|
1376
|
+
if (!response) {
|
|
1377
|
+
skip('G18', 'alwaysSetPhone does not clear the stored flag', 'form response not readable');
|
|
1378
|
+
}
|
|
1379
|
+
else if (response.authFieldIntakeDisabled === undefined) {
|
|
1380
|
+
// deliberately absent from schema.ts; if reads project it away there is nothing to assert here
|
|
1381
|
+
skip('G18', 'alwaysSetPhone does not clear the stored flag', 'authFieldIntakeDisabled not exposed on read');
|
|
1382
|
+
}
|
|
1383
|
+
else {
|
|
1384
|
+
record('G18', 'alwaysSetPhone does not clear the stored flag', response.authFieldIntakeDisabled === true, "authFieldIntakeDisabled=".concat(response.authFieldIntakeDisabled, " expected=true"));
|
|
1385
|
+
}
|
|
1386
|
+
return [2 /*return*/];
|
|
1387
|
+
}
|
|
1388
|
+
});
|
|
1389
|
+
}); })
|
|
1390
|
+
// ---------------------------------------------------------------------------------------------
|
|
1391
|
+
// R19 — nothing about the opt-in is recorded on the response, so a later webhook for the same
|
|
1392
|
+
// responder_uuid that omits it is blocked as usual. The earlier webhook here must be the DRAFT:
|
|
1393
|
+
// once a response is submitted the handler returns 'Already submitted' before reaching the lock,
|
|
1394
|
+
// which would make a finalized-then-finalized pair pass no matter what the implementation did.
|
|
1395
|
+
// ---------------------------------------------------------------------------------------------
|
|
1396
|
+
];
|
|
1397
|
+
case 26:
|
|
1398
|
+
// ---------------------------------------------------------------------------------------------
|
|
1399
|
+
// G18 — the opt-in is a per-REQUEST allow, exactly like G11 (?enduserId=) and R15 (the Stripe
|
|
1400
|
+
// grace): the response still records that it attached to a pre-existing patient, so the other
|
|
1401
|
+
// consumer of that flag — save_enduser_updates_for_form_response, reached by later staff edits —
|
|
1402
|
+
// stays protected.
|
|
1403
|
+
// ---------------------------------------------------------------------------------------------
|
|
1404
|
+
_h.sent();
|
|
1405
|
+
// ---------------------------------------------------------------------------------------------
|
|
1406
|
+
// R19 — nothing about the opt-in is recorded on the response, so a later webhook for the same
|
|
1407
|
+
// responder_uuid that omits it is blocked as usual. The earlier webhook here must be the DRAFT:
|
|
1408
|
+
// once a response is submitted the handler returns 'Already submitted' before reaching the lock,
|
|
1409
|
+
// which would make a finalized-then-finalized pair pass no matter what the implementation did.
|
|
1410
|
+
// ---------------------------------------------------------------------------------------------
|
|
1411
|
+
return [4 /*yield*/, runScenario('R19', 'alwaysSetPhone on an earlier webhook does not unlock a later one', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1412
|
+
var email, originalPhone, victim, intakePhone, draft, data, enduser;
|
|
1413
|
+
return __generator(this, function (_a) {
|
|
1414
|
+
switch (_a.label) {
|
|
1415
|
+
case 0:
|
|
1416
|
+
email = emailFor('r19');
|
|
1417
|
+
originalPhone = nextPhone();
|
|
1418
|
+
return [4 /*yield*/, makeVictim('r19', { email: email, phone: originalPhone })];
|
|
1419
|
+
case 1:
|
|
1420
|
+
victim = _a.sent();
|
|
1421
|
+
intakePhone = nextPhone();
|
|
1422
|
+
return [4 /*yield*/, postWebhook({
|
|
1423
|
+
label: 'r19',
|
|
1424
|
+
finalized: false,
|
|
1425
|
+
alwaysSetPhone: 'true',
|
|
1426
|
+
answers: [{ key: 'email', value: email }],
|
|
1427
|
+
})];
|
|
1428
|
+
case 2:
|
|
1429
|
+
draft = _a.sent();
|
|
1430
|
+
if (draft.status !== 200) {
|
|
1431
|
+
record('R19', 'alwaysSetPhone on an earlier webhook does not unlock a later one', false, "draft webhook returned ".concat(draft.status));
|
|
1432
|
+
return [2 /*return*/];
|
|
1433
|
+
}
|
|
1434
|
+
return [4 /*yield*/, postWebhook({
|
|
1435
|
+
label: 'r19',
|
|
1436
|
+
finalized: true,
|
|
1437
|
+
answers: [{ key: 'email', value: email }, { key: 'phone', value: intakePhone }],
|
|
1438
|
+
})];
|
|
1439
|
+
case 3:
|
|
1440
|
+
data = (_a.sent()).data;
|
|
1441
|
+
if (!matched('R19', 'alwaysSetPhone on an earlier webhook does not unlock a later one', data, victim.id))
|
|
1442
|
+
return [2 /*return*/];
|
|
1443
|
+
return [4 /*yield*/, pollEnduser(victim.id, function (e) { return e.phone === intakePhone; })];
|
|
1444
|
+
case 4:
|
|
1445
|
+
enduser = _a.sent();
|
|
1446
|
+
record('R19', 'alwaysSetPhone on an earlier webhook does not unlock a later one', (enduser === null || enduser === void 0 ? void 0 : enduser.phone) === originalPhone, "phone=".concat((enduser === null || enduser === void 0 ? void 0 : enduser.phone) || '(unset)', " expected=").concat(originalPhone));
|
|
1447
|
+
return [2 /*return*/];
|
|
1448
|
+
}
|
|
1449
|
+
});
|
|
1450
|
+
}); })
|
|
1451
|
+
// ---------------------------------------------------------------------------------------------
|
|
1452
|
+
// Report
|
|
1453
|
+
// ---------------------------------------------------------------------------------------------
|
|
1454
|
+
];
|
|
1455
|
+
case 27:
|
|
1456
|
+
// ---------------------------------------------------------------------------------------------
|
|
1457
|
+
// R19 — nothing about the opt-in is recorded on the response, so a later webhook for the same
|
|
1458
|
+
// responder_uuid that omits it is blocked as usual. The earlier webhook here must be the DRAFT:
|
|
1459
|
+
// once a response is submitted the handler returns 'Already submitted' before reaching the lock,
|
|
1460
|
+
// which would make a finalized-then-finalized pair pass no matter what the implementation did.
|
|
1461
|
+
// ---------------------------------------------------------------------------------------------
|
|
1462
|
+
_h.sent();
|
|
1078
1463
|
failures = results.filter(function (r) { return !r.ok; });
|
|
1079
1464
|
skipped = results.filter(function (r) { return !!r.skipped; });
|
|
1080
1465
|
console.log('');
|
|
@@ -1087,69 +1472,69 @@ export var formsort_webhook_auth_field_lock_tests = function (_a) {
|
|
|
1087
1472
|
console.log(" \u2514\u2500 ".concat(results.length - failures.length, "/").concat(results.length, " passed, ").concat(skipped.length, " skipped, ").concat(failures.length, " failed"));
|
|
1088
1473
|
console.log('');
|
|
1089
1474
|
_b = 0, createdFormIds_1 = createdFormIds;
|
|
1090
|
-
_h.label =
|
|
1091
|
-
case
|
|
1092
|
-
if (!(_b < createdFormIds_1.length)) return [3 /*break*/,
|
|
1475
|
+
_h.label = 28;
|
|
1476
|
+
case 28:
|
|
1477
|
+
if (!(_b < createdFormIds_1.length)) return [3 /*break*/, 34];
|
|
1093
1478
|
formId = createdFormIds_1[_b];
|
|
1094
1479
|
return [4 /*yield*/, sdk.api.form_responses.getSome({ filter: { formId: formId } }).catch(function () { return []; })];
|
|
1095
|
-
case
|
|
1480
|
+
case 29:
|
|
1096
1481
|
responses = _h.sent();
|
|
1097
1482
|
_c = 0, responses_1 = responses;
|
|
1098
|
-
_h.label =
|
|
1099
|
-
case
|
|
1100
|
-
if (!(_c < responses_1.length)) return [3 /*break*/,
|
|
1483
|
+
_h.label = 30;
|
|
1484
|
+
case 30:
|
|
1485
|
+
if (!(_c < responses_1.length)) return [3 /*break*/, 33];
|
|
1101
1486
|
response = responses_1[_c];
|
|
1102
1487
|
return [4 /*yield*/, sdk.api.form_responses.deleteOne(response.id).catch(function () { return null; })];
|
|
1103
|
-
case
|
|
1488
|
+
case 31:
|
|
1104
1489
|
_h.sent();
|
|
1105
|
-
_h.label =
|
|
1106
|
-
case
|
|
1490
|
+
_h.label = 32;
|
|
1491
|
+
case 32:
|
|
1107
1492
|
_c++;
|
|
1108
|
-
return [3 /*break*/,
|
|
1109
|
-
case
|
|
1493
|
+
return [3 /*break*/, 30];
|
|
1494
|
+
case 33:
|
|
1110
1495
|
_b++;
|
|
1111
|
-
return [3 /*break*/,
|
|
1112
|
-
case
|
|
1496
|
+
return [3 /*break*/, 28];
|
|
1497
|
+
case 34:
|
|
1113
1498
|
_d = 0, createdFormIds_2 = createdFormIds;
|
|
1114
|
-
_h.label =
|
|
1115
|
-
case
|
|
1116
|
-
if (!(_d < createdFormIds_2.length)) return [3 /*break*/,
|
|
1499
|
+
_h.label = 35;
|
|
1500
|
+
case 35:
|
|
1501
|
+
if (!(_d < createdFormIds_2.length)) return [3 /*break*/, 38];
|
|
1117
1502
|
id = createdFormIds_2[_d];
|
|
1118
1503
|
return [4 /*yield*/, sdk.api.forms.deleteOne(id).catch(function () { return null; })];
|
|
1119
|
-
case
|
|
1504
|
+
case 36:
|
|
1120
1505
|
_h.sent();
|
|
1121
|
-
_h.label =
|
|
1122
|
-
case
|
|
1506
|
+
_h.label = 37;
|
|
1507
|
+
case 37:
|
|
1123
1508
|
_d++;
|
|
1124
|
-
return [3 /*break*/,
|
|
1125
|
-
case
|
|
1509
|
+
return [3 /*break*/, 35];
|
|
1510
|
+
case 38:
|
|
1126
1511
|
uniqueEnduserIds = createdEnduserIds.filter(function (id, i) { return !!id && createdEnduserIds.indexOf(id) === i; });
|
|
1127
1512
|
_e = 0, uniqueEnduserIds_1 = uniqueEnduserIds;
|
|
1128
|
-
_h.label =
|
|
1129
|
-
case
|
|
1130
|
-
if (!(_e < uniqueEnduserIds_1.length)) return [3 /*break*/,
|
|
1513
|
+
_h.label = 39;
|
|
1514
|
+
case 39:
|
|
1515
|
+
if (!(_e < uniqueEnduserIds_1.length)) return [3 /*break*/, 42];
|
|
1131
1516
|
id = uniqueEnduserIds_1[_e];
|
|
1132
1517
|
return [4 /*yield*/, sdk.api.endusers.deleteOne(id).catch(function () { return null; })];
|
|
1133
|
-
case
|
|
1518
|
+
case 40:
|
|
1134
1519
|
_h.sent();
|
|
1135
|
-
_h.label =
|
|
1136
|
-
case
|
|
1520
|
+
_h.label = 41;
|
|
1521
|
+
case 41:
|
|
1137
1522
|
_e++;
|
|
1138
|
-
return [3 /*break*/,
|
|
1139
|
-
case
|
|
1523
|
+
return [3 /*break*/, 39];
|
|
1524
|
+
case 42:
|
|
1140
1525
|
_f = 0, createdApiKeyIds_1 = createdApiKeyIds;
|
|
1141
|
-
_h.label =
|
|
1142
|
-
case
|
|
1143
|
-
if (!(_f < createdApiKeyIds_1.length)) return [3 /*break*/,
|
|
1526
|
+
_h.label = 43;
|
|
1527
|
+
case 43:
|
|
1528
|
+
if (!(_f < createdApiKeyIds_1.length)) return [3 /*break*/, 46];
|
|
1144
1529
|
id = createdApiKeyIds_1[_f];
|
|
1145
1530
|
return [4 /*yield*/, sdk.api.api_keys.deleteOne(id).catch(function () { return null; })];
|
|
1146
|
-
case
|
|
1531
|
+
case 44:
|
|
1147
1532
|
_h.sent();
|
|
1148
|
-
_h.label =
|
|
1149
|
-
case
|
|
1533
|
+
_h.label = 45;
|
|
1534
|
+
case 45:
|
|
1150
1535
|
_f++;
|
|
1151
|
-
return [3 /*break*/,
|
|
1152
|
-
case
|
|
1536
|
+
return [3 /*break*/, 43];
|
|
1537
|
+
case 46:
|
|
1153
1538
|
// ---------------------------------------------------------------------------------------------
|
|
1154
1539
|
// Assert — single pass, last, so the full table above is always printed first.
|
|
1155
1540
|
// ---------------------------------------------------------------------------------------------
|