davinci_crd_test_kit 0.14.0 → 0.14.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.
- checksums.yaml +4 -4
- data/config/presets/{inferno_crd_server_suite.json.erb → client_against_inferno_crd_server_suite.json.erb} +0 -33
- data/config/presets/{ri_crd_request_generator.json.erb → client_against_ri_crd_request_generator.json.erb} +1 -14
- data/config/presets/client_v221_against_inferno_crd_server_suite.json.erb +84 -0
- data/config/presets/client_v221_against_ri_br_provider.json.erb +31 -0
- data/config/presets/{ri_crd_request_generator.json_v221.json.erb → client_v221_against_ri_crd_request_generator.json.erb} +1 -1
- data/config/presets/{inferno_crd_client_suite.json.erb → server_against_inferno_crd_client_suite.json.erb} +0 -43
- data/config/presets/{ri_crd_server.json.erb → server_against_ri_crd_server.json.erb} +1 -44
- data/config/presets/{inferno_crd_client_suite_v221.json.erb → server_v221_against_inferno_crd_client_suite.json.erb} +48 -45
- data/config/presets/{inferno_crd_client_suite_prefetch_subset_v221.json.erb → server_v221_against_inferno_crd_client_suite_prefetch_subset.json.erb} +0 -46
- data/config/presets/server_v221_against_inferno_g31_suite.json.erb +49 -0
- data/lib/davinci_crd_test_kit/client/cross_hook_helper.rb +26 -0
- data/lib/davinci_crd_test_kit/client/endpoints/custom_service_response.rb +7 -7
- data/lib/davinci_crd_test_kit/client/endpoints/gather_response_generation_data.rb +4 -1
- data/lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb +70 -39
- data/lib/davinci_crd_test_kit/client/endpoints/mock_service_response.rb +26 -7
- data/lib/davinci_crd_test_kit/client/endpoints/mocked_card_responses/external_reference.json +1 -1
- data/lib/davinci_crd_test_kit/client/endpoints/mocked_card_responses/launch_smart_app.json +0 -7
- data/lib/davinci_crd_test_kit/client/endpoints/scenario_service_response.rb +54 -0
- data/lib/davinci_crd_test_kit/client/tagged_request_load_helper.rb +8 -27
- data/lib/davinci_crd_test_kit/client/v2.0.1/auth/retrieve_jwks_test.rb +35 -23
- data/lib/davinci_crd_test_kit/client/v2.0.1/auth/token_payload_test.rb +34 -21
- data/lib/davinci_crd_test_kit/client/v2.0.1/cds-services-v201.json +20 -20
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_appointment_book_group.rb +12 -10
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_discharge_group.rb +12 -10
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_start_group.rb +12 -10
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_hooks_group.rb +5 -5
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_dispatch_group.rb +12 -10
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_select_group.rb +12 -10
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_sign_group.rb +12 -10
- data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_coverage_information.rb +3 -36
- data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_external_reference.rb +3 -36
- data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_instructions.rb +3 -36
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_fetched_data_test.rb +4 -13
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_prefetch_equals_queried_test.rb +3 -13
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/client_display_cards_attest.rb +3 -13
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/inferno_response_validation.rb +3 -13
- data/lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/attestation_instructions.rb +10 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_authorized_scope_attestation_test.rb +45 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_coverage_based_invocation_attestation_test.rb +44 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_data_element_expectations_attestation_test.rb +44 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_hook_invocation_logging_attestation_test.rb +43 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_must_support_exposure_attestation_test.rb +43 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_must_support_use_attestation_test.rb +41 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_order_sign_support_attestation_test.rb +42 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_prefetch_key_omission_attestation_test.rb +42 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_resource_identifiers_attestation_test.rb +43 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_response_case_distinction_attestation_test.rb +43 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_security_and_privacy_attestation_test.rb +43 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_workflow_integration_attestation_test.rb +44 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/auth/decode_auth_token_test.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/auth/retrieve_jwks_test.rb +29 -18
- data/lib/davinci_crd_test_kit/client/v2.2.1/auth/token_payload_test.rb +35 -22
- data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-prefetch-subset-v221.json +47 -47
- data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-v221.json +50 -50
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_appointment_book_group.rb +24 -15
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_attestations_group.rb +49 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_cross_hook_group.rb +22 -6
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_cross_hook_interaction_group.rb +98 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_discharge_group.rb +19 -11
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_start_group.rb +19 -11
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_fhir_api_group.rb +14 -12
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_hooks_group.rb +25 -5
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_long_running_hook_group.rb +3 -2
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_dispatch_group.rb +23 -15
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_select_group.rb +19 -11
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_sign_group.rb +23 -15
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_registration_group.rb +6 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_scenarios_group.rb +26 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_self_pay_hook_group.rb +36 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_unknown_content_hook_group.rb +34 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/crd_client_suite.rb +24 -3
- data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_card_must_support_coverage_information_test.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_fhirpath_collection_as_comma_delimited_string_test.rb +4 -11
- data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_hook_instances_unique_test.rb +1 -9
- data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_location_address_propagation_test.rb +6 -2
- data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_prefetch_complete_and_subset_test.rb +3 -12
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/appointment_book_receive_request_test.rb +8 -89
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/base_hook_invocation_receive_request_test.rb +163 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/cross_hooks_receive_request_test.rb +97 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_discharge_receive_request_test.rb +8 -90
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_start_receive_request_test.rb +8 -90
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_dispatch_receive_request_test.rb +8 -98
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_select_receive_request_test.rb +8 -98
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_sign_receive_request_test.rb +8 -98
- data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_long_running_receive_request_test.rb +10 -2
- data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_skip_long_running_attestation_test.rb +11 -6
- data/lib/davinci_crd_test_kit/client/v2.2.1/registration/client_service_registration_attestation_test.rb +2 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/self_pay/client_self_pay_no_request_test.rb +30 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/self_pay/client_self_pay_workflow_test.rb +55 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/unknown_content/client_unknown_content_attestation_test.rb +99 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/unknown_content/client_unknown_content_receive_request_test.rb +62 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_conformance_test.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_coverage_verification_test.rb +10 -2
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_data_fetch_verification_test.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_granted_scopes_test.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_complete_test.rb +7 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_profiles_test.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_requested_version_test.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_secured_transport_test.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/client_display_cards_attest.rb +54 -21
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/hook_response_support_coverage_information_test.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/inferno_response_validation.rb +6 -3
- data/lib/davinci_crd_test_kit/cross_suite/cards_identification.rb +18 -0
- data/lib/davinci_crd_test_kit/cross_suite/logical_models_override_helper.rb +30 -13
- data/lib/davinci_crd_test_kit/cross_suite/prefetch_completeness_checker.rb +25 -11
- data/lib/davinci_crd_test_kit/cross_suite/prefetch_profile_validation.rb +2 -0
- data/lib/davinci_crd_test_kit/cross_suite/requests_logical_model_validation.rb +28 -28
- data/lib/davinci_crd_test_kit/cross_suite/response_logical_model_validation.rb +211 -43
- data/lib/davinci_crd_test_kit/cross_suite/tags.rb +7 -0
- data/lib/davinci_crd_test_kit/requirements/cds-hooks_3.0.0-ballot_requirements.xlsx +0 -0
- data/lib/davinci_crd_test_kit/requirements/davinci_crd_test_kit_requirements.csv +6 -2
- data/lib/davinci_crd_test_kit/requirements/generated/crd_client_requirements_coverage.csv +107 -107
- data/lib/davinci_crd_test_kit/requirements/generated/crd_client_v221_requirements_coverage.csv +101 -97
- data/lib/davinci_crd_test_kit/requirements/generated/crd_server_requirements_coverage.csv +18 -18
- data/lib/davinci_crd_test_kit/requirements/generated/crd_server_v221_requirements_coverage.csv +43 -39
- data/lib/davinci_crd_test_kit/requirements/hl7.fhir.us.davinci-crd_2.2.1_requirements.xlsx +0 -0
- data/lib/davinci_crd_test_kit/server/jobs/invoke_hook.rb +3 -3
- data/lib/davinci_crd_test_kit/server/jobs/invoke_hook_no_special_requests.rb +17 -0
- data/lib/davinci_crd_test_kit/server/jobs/invoke_hook_with_bad_auth.rb +14 -0
- data/lib/davinci_crd_test_kit/server/server_abstract_invoke_hook_test.rb +24 -6
- data/lib/davinci_crd_test_kit/server/server_hook_helper.rb +2 -2
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_server_suite.rb +1 -1
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_hooks_group.rb +5 -5
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_server_suite.rb +3 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_standard_prefetch_expressions_test.rb +165 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/interaction/server_invoke_hook_single_request_test.rb +22 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_appointment_book_group.rb +10 -102
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_demonstrate_hook_response_group.rb +3 -2
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_discovery_group.rb +2 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_discharge_group.rb +10 -97
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_start_group.rb +10 -97
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_hooks_group.rb +5 -5
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_dispatch_group.rb +10 -103
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_select_group.rb +12 -116
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_sign_group.rb +12 -121
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_response_group.rb +23 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/coverage_info_reason_test.rb +108 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/coverage_not_found_group.rb +116 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/no_active_coverage_group.rb +115 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/no_member_found_group.rb +117 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/technical_issues_group.rb +121 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/technical_issues_invoke_test.rb +22 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_context_validation_test.rb +1 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_optional_fields_validation_test.rb +1 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_required_fields_validation_test.rb +1 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/additional_orders_validation_test.rb +78 -35
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_card_absence_test.rb +76 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb +70 -124
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/create_or_update_coverage_info_response_validation_test.rb +83 -39
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/external_reference_card_validation_test.rb +59 -17
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/form_completion_response_validation_test.rb +80 -45
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/hook_request_resource_resolution.rb +37 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/instructions_card_received_test.rb +57 -6
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/launch_smart_app_card_validation_test.rb +56 -17
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/propose_alternate_request_card_validation_test.rb +52 -25
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/service_response_validation_test.rb +17 -51
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_cds_hooks_elements_test.rb +1 -1
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_configuration_test.rb +1 -1
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_context_test.rb +1 -1
- data/lib/davinci_crd_test_kit/version.rb +2 -2
- metadata +54 -16
- data/config/presets/inferno_crd_server_suite_v221.json.erb +0 -94
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/card_optional_fields_validation_test.rb +0 -57
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_received_test.rb +0 -65
|
@@ -39,21 +39,24 @@ module DaVinciCRDTestKit
|
|
|
39
39
|
"#{CRD_LOGICAL_MODEL_BASE}/#{profile_name}"
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
def perform_response_logical_model_validation(cards, system_actions, request_body, response_index, ig_semver
|
|
42
|
+
def perform_response_logical_model_validation(cards, system_actions, request_body, response_index, ig_semver,
|
|
43
|
+
validator: :default)
|
|
43
44
|
if cards.is_a?(Array)
|
|
44
45
|
cards.each_with_index do |card, card_index|
|
|
45
|
-
validate_card_against_logical_model(card, response_index, request_body, card_index, ig_semver)
|
|
46
|
+
validate_card_against_logical_model(card, response_index, request_body, card_index, ig_semver, validator:)
|
|
46
47
|
end
|
|
47
48
|
end
|
|
48
49
|
|
|
49
50
|
return unless system_actions.is_a?(Array)
|
|
50
51
|
|
|
51
52
|
system_actions.each_with_index do |action, action_index|
|
|
52
|
-
validate_system_action_against_logical_model(action, response_index, request_body, action_index, ig_semver
|
|
53
|
+
validate_system_action_against_logical_model(action, response_index, request_body, action_index, ig_semver,
|
|
54
|
+
validator:)
|
|
53
55
|
end
|
|
54
56
|
end
|
|
55
57
|
|
|
56
|
-
def validate_card_against_logical_model(card, response_index, request_body, card_index, ig_semver
|
|
58
|
+
def validate_card_against_logical_model(card, response_index, request_body, card_index, ig_semver,
|
|
59
|
+
validator: :default)
|
|
57
60
|
label = logical_model_entity_label(response_index, card_index, 'card')
|
|
58
61
|
unless card.is_a?(Hash)
|
|
59
62
|
add_message('error', "#{label} is not a JSON object; skipping logical model validation.")
|
|
@@ -71,15 +74,62 @@ module DaVinciCRDTestKit
|
|
|
71
74
|
|
|
72
75
|
validation_issues = []
|
|
73
76
|
conforms_to_logical_model?({ 'cards' => [card] }, logical_model_url(profile_name),
|
|
74
|
-
add_messages_to_runnable: false, validator_response_details: validation_issues
|
|
77
|
+
add_messages_to_runnable: false, validator_response_details: validation_issues,
|
|
78
|
+
validator:)
|
|
79
|
+
|
|
80
|
+
validate_summary_length(card, label)
|
|
81
|
+
validate_suggestion_uuid_presence(card, label) unless ['v201', '2.0.1'].include? ig_semver
|
|
82
|
+
validate_no_smart_suggestions(card, label) if card_type == CardsIdentification::LAUNCH_SMART_APP_RESPONSE_TYPE
|
|
75
83
|
|
|
76
84
|
error_prefix = "#{label} (#{card_type || 'uncategorized'}): "
|
|
77
85
|
filtered_issues = manually_check_card_specific_errors(card, validation_issues, card_type,
|
|
78
|
-
request_body, error_prefix, ig_semver)
|
|
86
|
+
request_body, error_prefix, ig_semver, validator:)
|
|
87
|
+
filter_logical_model_extension_issues(filtered_issues, validator)
|
|
79
88
|
add_messages_not_excluded(filtered_issues, error_prefix)
|
|
80
89
|
end
|
|
81
90
|
|
|
82
|
-
def
|
|
91
|
+
def validate_summary_length(card, label)
|
|
92
|
+
return unless card['summary'].is_a? String
|
|
93
|
+
|
|
94
|
+
summary_length = card['summary'].length
|
|
95
|
+
|
|
96
|
+
return if summary_length < 140
|
|
97
|
+
|
|
98
|
+
add_message(
|
|
99
|
+
'error',
|
|
100
|
+
"#{label} summary length of #{summary_length} characters is longer than " \
|
|
101
|
+
'the maximum allowed of 139 characters.'
|
|
102
|
+
)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def validate_suggestion_uuid_presence(card, label)
|
|
106
|
+
return unless card['suggestions'].presence.is_a? Array
|
|
107
|
+
return unless card['suggestions'].all?(Hash)
|
|
108
|
+
|
|
109
|
+
card['suggestions'].each_with_index do |suggestion, index|
|
|
110
|
+
next if suggestion['uuid'].present?
|
|
111
|
+
|
|
112
|
+
add_message(
|
|
113
|
+
'error',
|
|
114
|
+
"#{label} suggestion #{index + 1} does not contain a `uuid`"
|
|
115
|
+
)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def validate_no_smart_suggestions(card, label)
|
|
120
|
+
suggestion_count = card['suggestions']&.length || 0
|
|
121
|
+
|
|
122
|
+
return if suggestion_count.zero?
|
|
123
|
+
|
|
124
|
+
add_message(
|
|
125
|
+
'error',
|
|
126
|
+
"#{label} CDSHooksResponse.cards.suggestions: max allowed = 0, but found #{suggestion_count} " \
|
|
127
|
+
'(from http://hl7.org/fhir/us/davinci-crd/StructureDefinition/CRDHooksResponse-launchSMART|2.2.1)'
|
|
128
|
+
)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def validate_system_action_against_logical_model(action, response_index, request_body, action_index, ig_semver,
|
|
132
|
+
validator: :default)
|
|
83
133
|
label = logical_model_entity_label(response_index, action_index, 'systemAction')
|
|
84
134
|
unless action.is_a?(Hash)
|
|
85
135
|
add_message('error', "#{label} is not a JSON object; skipping logical model validation.")
|
|
@@ -102,17 +152,116 @@ module DaVinciCRDTestKit
|
|
|
102
152
|
|
|
103
153
|
validation_issues = []
|
|
104
154
|
conforms_to_logical_model?({ 'systemActions' => [action] }, logical_model_url(profile_name),
|
|
105
|
-
add_messages_to_runnable: false, validator_response_details: validation_issues
|
|
155
|
+
add_messages_to_runnable: false, validator_response_details: validation_issues,
|
|
156
|
+
validator:)
|
|
106
157
|
|
|
158
|
+
validation_issues
|
|
159
|
+
.reject! do |issue|
|
|
160
|
+
issue.message.match?(%r{CDSHooksResponse\.systemActions\[\d+\]\.extension: The extension definition http://hl7\.org/fhir/us/davinci-crd/StructureDefinition/CDSHookServiceResponseExtensionIfNoneExist\|2\.2\.1 defines the contexts of use as}) # rubocop:disable Layout/LineLength
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if action_type == CardsIdentification::COVERAGE_INFORMATION_RESPONSE_TYPE
|
|
164
|
+
check_multiple_coverage_info_extension_conformance(action)
|
|
165
|
+
end
|
|
107
166
|
error_prefix = "#{label} (#{action_type || 'uncategorized'}): "
|
|
108
167
|
filtered_issues = manually_check_action_specific_errors(action, validation_issues, action_type,
|
|
109
|
-
request_body, error_prefix, ig_semver)
|
|
168
|
+
request_body, error_prefix, ig_semver, validator:)
|
|
169
|
+
filter_logical_model_extension_issues(filtered_issues, validator)
|
|
110
170
|
add_messages_not_excluded(filtered_issues, error_prefix)
|
|
111
171
|
end
|
|
112
172
|
|
|
173
|
+
def check_multiple_coverage_info_extension_conformance(action)
|
|
174
|
+
resource = FHIR.from_contents(action['resource'].to_json)
|
|
175
|
+
|
|
176
|
+
grouped_coverage_info = extract_and_group_coverage_info(resource)
|
|
177
|
+
multiple_extensions_conformance_check(grouped_coverage_info, resource)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def extract_and_group_coverage_info(resource)
|
|
181
|
+
resource.extension.each_with_object({}) do |extension, grouped_extensions|
|
|
182
|
+
next unless extension.url == COVERAGE_INFO_EXT_URL
|
|
183
|
+
|
|
184
|
+
coverage_key = find_extension_value(extension, 'coverage', 'valueReference', 'reference')
|
|
185
|
+
grouped_extensions[coverage_key] ||= []
|
|
186
|
+
grouped_extensions[coverage_key] << extension
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# For the same coverage, ensure coverage-assertion-ids and satisfied-pa-ids are the same.
|
|
191
|
+
# For different coverages, ensure coverage-assertion-ids and satisfied-pa-ids are distinct.
|
|
192
|
+
def multiple_extensions_conformance_check(grouped_coverage_info, resource)
|
|
193
|
+
resource_ref = "#{resource.resourceType}/#{resource.id}"
|
|
194
|
+
assertion_ids_across_coverages = Set.new
|
|
195
|
+
pa_ids_across_coverages = Set.new
|
|
196
|
+
|
|
197
|
+
grouped_coverage_info.each do |coverage, extensions|
|
|
198
|
+
coverage_assertion_ids = collect_extensions_id(extensions, 'coverage-assertion-id', 'valueString').uniq
|
|
199
|
+
satisfied_pa_ids = collect_extensions_id(extensions, 'satisfied-pa-id', 'valueString').uniq.compact
|
|
200
|
+
if coverage_assertion_ids.length != 1
|
|
201
|
+
add_message(
|
|
202
|
+
'error',
|
|
203
|
+
same_coverage_conformance_error_msg(resource_ref, coverage, 'coverage-assertion-ids')
|
|
204
|
+
)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
if satisfied_pa_ids.length > 1
|
|
208
|
+
add_message(
|
|
209
|
+
'error',
|
|
210
|
+
same_coverage_conformance_error_msg(resource_ref, coverage, 'satisfied-pa-ids')
|
|
211
|
+
)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
assertion_id = coverage_assertion_ids.first
|
|
215
|
+
if assertion_ids_across_coverages.include?(assertion_id)
|
|
216
|
+
add_message(
|
|
217
|
+
'error',
|
|
218
|
+
different_coverage_conformance_error_msg(resource_ref, 'coverage-assertion-ids')
|
|
219
|
+
)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
assertion_ids_across_coverages.add(assertion_id)
|
|
223
|
+
pa_id = satisfied_pa_ids.first
|
|
224
|
+
next unless pa_id
|
|
225
|
+
|
|
226
|
+
if pa_ids_across_coverages.include?(pa_id)
|
|
227
|
+
add_message(
|
|
228
|
+
'error',
|
|
229
|
+
different_coverage_conformance_error_msg(resource_ref, 'satisfied-pa-ids')
|
|
230
|
+
)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
pa_ids_across_coverages.add(pa_id)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def collect_extensions_id(extensions, url, *properties)
|
|
238
|
+
extensions.map do |extension|
|
|
239
|
+
find_extension_value(extension, url, *properties)
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def find_extension_value(extension, url, *properties)
|
|
244
|
+
found_extension = extension.extension.find { |ext| ext.url == url }
|
|
245
|
+
return nil unless found_extension
|
|
246
|
+
|
|
247
|
+
properties.reduce(found_extension) do |current, prop|
|
|
248
|
+
return current unless current.respond_to?(prop)
|
|
249
|
+
|
|
250
|
+
current.send(prop)
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def same_coverage_conformance_error_msg(resource_ref, coverage, id_name)
|
|
255
|
+
"#{resource_ref}: extension has multiple repetitions of coverage `#{coverage}` with different #{id_name}."
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def different_coverage_conformance_error_msg(resource_ref, id_name)
|
|
259
|
+
"#{resource_ref}: extensions referencing differing coverage SHALL have distinct #{id_name}."
|
|
260
|
+
end
|
|
261
|
+
|
|
113
262
|
def add_messages_not_excluded(issues, error_prefix)
|
|
114
263
|
issues.each do |issue|
|
|
115
|
-
next if issue.filtered
|
|
264
|
+
next if issue.filtered
|
|
116
265
|
|
|
117
266
|
add_message(issue.severity, "#{error_prefix}#{issue.message}")
|
|
118
267
|
end
|
|
@@ -126,47 +275,45 @@ module DaVinciCRDTestKit
|
|
|
126
275
|
# Validator Filtering and Manual Checks Depending on the Card Type
|
|
127
276
|
# -------------------------------------------------------------------------
|
|
128
277
|
|
|
129
|
-
def logical_model_extension_issue?(issue)
|
|
130
|
-
issue.message.match(/\.extension: Unrecognized property/).present?
|
|
131
|
-
end
|
|
132
|
-
|
|
133
278
|
def manually_check_card_specific_errors(card, validation_issues, card_type, request_body, error_prefix,
|
|
134
|
-
ig_semver)
|
|
279
|
+
ig_semver, validator: :default)
|
|
135
280
|
case card_type
|
|
136
|
-
when
|
|
137
|
-
manually_check_form_completion_errors(card, validation_issues, error_prefix)
|
|
138
|
-
when
|
|
281
|
+
when CardsIdentification::FORM_COMPLETION_RESPONSE_TYPE
|
|
282
|
+
manually_check_form_completion_errors(card, validation_issues, error_prefix, validator:)
|
|
283
|
+
when CardsIdentification::PROPOSE_ALTERNATIVE_REQUEST_RESPONSE_TYPE
|
|
139
284
|
manually_check_propose_alternative_errors(card, validation_issues, request_body,
|
|
140
|
-
error_prefix, ig_semver)
|
|
141
|
-
when
|
|
285
|
+
error_prefix, ig_semver, validator:)
|
|
286
|
+
when CardsIdentification::ADDITIONAL_ORDERS_RESPONSE_TYPE
|
|
142
287
|
manually_check_additional_orders_errors(card, validation_issues, request_body,
|
|
143
|
-
error_prefix, ig_semver)
|
|
288
|
+
error_prefix, ig_semver, validator:)
|
|
289
|
+
when CardsIdentification::LAUNCH_SMART_APP_RESPONSE_TYPE
|
|
290
|
+
manually_check_launch_smart_app_errors(validation_issues)
|
|
144
291
|
else
|
|
145
292
|
validation_issues
|
|
146
293
|
end
|
|
147
294
|
end
|
|
148
295
|
|
|
149
296
|
def manually_check_action_specific_errors(action, validation_issues, action_type, request_body,
|
|
150
|
-
error_prefix, ig_semver)
|
|
297
|
+
error_prefix, ig_semver, validator: :default)
|
|
151
298
|
case action_type
|
|
152
299
|
when DaVinciCRDTestKit::CardsIdentification::COVERAGE_INFORMATION_RESPONSE_TYPE
|
|
153
300
|
manually_check_coverage_information_errors(action, validation_issues, request_body,
|
|
154
|
-
error_prefix, ig_semver)
|
|
301
|
+
error_prefix, ig_semver, validator:)
|
|
155
302
|
when DaVinciCRDTestKit::CardsIdentification::CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE
|
|
156
303
|
manually_check_update_coverage_action_errors(action, validation_issues,
|
|
157
|
-
error_prefix, ig_semver)
|
|
304
|
+
error_prefix, ig_semver, validator:)
|
|
158
305
|
when DaVinciCRDTestKit::CardsIdentification::FORM_COMPLETION_RESPONSE_TYPE
|
|
159
306
|
manually_check_form_completion_action_errors(action, validation_issues,
|
|
160
|
-
error_prefix, ig_semver)
|
|
307
|
+
error_prefix, ig_semver, validator:)
|
|
161
308
|
else
|
|
162
309
|
validation_issues
|
|
163
310
|
end
|
|
164
311
|
end
|
|
165
312
|
|
|
166
|
-
def manually_check_form_completion_errors(card, validation_issues, error_prefix)
|
|
313
|
+
def manually_check_form_completion_errors(card, validation_issues, error_prefix, validator: :default)
|
|
167
314
|
validation_issues.reject do |issue|
|
|
168
315
|
if issue.message.match?(/The type 'Questionnaire' is not valid - must be Task/)
|
|
169
|
-
check_questionnaire_actions(card, issue.message, error_prefix)
|
|
316
|
+
check_questionnaire_actions(card, issue.message, error_prefix, validator:)
|
|
170
317
|
true
|
|
171
318
|
else
|
|
172
319
|
false
|
|
@@ -174,7 +321,7 @@ module DaVinciCRDTestKit
|
|
|
174
321
|
end
|
|
175
322
|
end
|
|
176
323
|
|
|
177
|
-
def check_questionnaire_actions(card, error_message, error_prefix)
|
|
324
|
+
def check_questionnaire_actions(card, error_message, error_prefix, validator: :default)
|
|
178
325
|
extracted_indexes =
|
|
179
326
|
error_message.match(/CDSHooksResponse\.cards\[0\]\.suggestions\[(\d+)\]\.actions\[(\d+)\]\.resource/)
|
|
180
327
|
unless extracted_indexes
|
|
@@ -187,43 +334,63 @@ module DaVinciCRDTestKit
|
|
|
187
334
|
|
|
188
335
|
message_prefix = "#{error_prefix} suggestion #{suggestion_index + 1}, action #{action_index + 1} - "
|
|
189
336
|
resource = FHIR.from_contents(card['suggestions'][suggestion_index]['actions'][action_index]['resource'].to_json)
|
|
190
|
-
resource_is_valid?(resource:, message_prefix:) # no questionnaire profile applied per CRD
|
|
337
|
+
resource_is_valid?(resource:, message_prefix:, validator:) # no questionnaire profile applied per CRD
|
|
191
338
|
|
|
192
339
|
return if resource.id.present?
|
|
193
340
|
|
|
194
341
|
add_message('error', "#{message_prefix}Questionnaire must have an id.")
|
|
195
342
|
end
|
|
196
343
|
|
|
344
|
+
def manually_check_launch_smart_app_errors(validation_issues)
|
|
345
|
+
validation_issues.reject do |issue|
|
|
346
|
+
issue.message.match?(/CDSHooksResponse.cards.suggestions: minimum required = 1, but only found 0/)
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
197
350
|
def manually_check_propose_alternative_errors(card, validation_issues, request_body,
|
|
198
|
-
error_prefix, ig_semver)
|
|
351
|
+
error_prefix, ig_semver, validator: :default)
|
|
199
352
|
no_resource_issues = manually_check_action_resources_for_order_profile_conformance(card,
|
|
200
353
|
validation_issues,
|
|
201
354
|
request_body,
|
|
202
355
|
error_prefix,
|
|
203
|
-
ig_semver
|
|
356
|
+
ig_semver,
|
|
357
|
+
validator:)
|
|
358
|
+
|
|
359
|
+
no_resource_issues.each do |issue|
|
|
360
|
+
next unless issue.message.match?(/Constraint failed: crd-respar-1/)
|
|
361
|
+
|
|
362
|
+
new_message =
|
|
363
|
+
"#{issue.message}. In some cases [additional create " \
|
|
364
|
+
'actions](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#propose-alternate-request-response-type) ' \
|
|
365
|
+
'are permitted. Manually check the suggestion to verify whether this is an actual error.'
|
|
366
|
+
issue.instance_variable_set(:@severity, 'warning')
|
|
367
|
+
issue.instance_variable_set(:@message, new_message)
|
|
368
|
+
end
|
|
369
|
+
|
|
204
370
|
no_resource_issues.reject do |issue|
|
|
205
371
|
issue.message.match?(/but is fixed to 'create' in the profile/)
|
|
206
372
|
end
|
|
207
373
|
end
|
|
208
374
|
|
|
209
375
|
def manually_check_additional_orders_errors(card, validation_issues, request_body,
|
|
210
|
-
error_prefix, ig_semver)
|
|
376
|
+
error_prefix, ig_semver, validator: :default)
|
|
211
377
|
manually_check_action_resources_for_order_profile_conformance(card,
|
|
212
378
|
validation_issues,
|
|
213
379
|
request_body,
|
|
214
380
|
error_prefix,
|
|
215
|
-
ig_semver
|
|
381
|
+
ig_semver,
|
|
382
|
+
validator:)
|
|
216
383
|
end
|
|
217
384
|
|
|
218
385
|
def manually_check_action_resources_for_order_profile_conformance(card, validation_issues, request_body,
|
|
219
|
-
error_prefix, ig_semver)
|
|
386
|
+
error_prefix, ig_semver, validator: :default)
|
|
220
387
|
if card['suggestions'].present?
|
|
221
388
|
card['suggestions'].each_with_index do |suggestion, suggestion_index|
|
|
222
389
|
next unless suggestion['actions'].present?
|
|
223
390
|
|
|
224
391
|
suggestion['actions'].each_with_index do |action, action_index|
|
|
225
392
|
action_error_prefix = "#{error_prefix}suggestion #{suggestion_index + 1}, action #{action_index + 1} - "
|
|
226
|
-
check_action_target(action, request_body, action_error_prefix, ig_semver)
|
|
393
|
+
check_action_target(action, request_body, action_error_prefix, ig_semver, validator:)
|
|
227
394
|
end
|
|
228
395
|
end
|
|
229
396
|
end
|
|
@@ -231,36 +398,37 @@ module DaVinciCRDTestKit
|
|
|
231
398
|
reject_resource_issues(validation_issues)
|
|
232
399
|
end
|
|
233
400
|
|
|
234
|
-
def check_action_target(action, request_body, error_prefix, ig_semver)
|
|
401
|
+
def check_action_target(action, request_body, error_prefix, ig_semver, validator: :default)
|
|
235
402
|
local_reference?(action['resourceId'], error_prefix) if action['resourceId'].present?
|
|
236
403
|
return unless action['resource'].present?
|
|
237
404
|
|
|
238
|
-
check_resource_conformance_to_order_profile(action['resource'], request_body, error_prefix, ig_semver)
|
|
405
|
+
check_resource_conformance_to_order_profile(action['resource'], request_body, error_prefix, ig_semver, validator:)
|
|
239
406
|
end
|
|
240
407
|
|
|
241
408
|
def manually_check_coverage_information_errors(action, validation_issues, request_body,
|
|
242
|
-
error_prefix, ig_semver)
|
|
409
|
+
error_prefix, ig_semver, validator: :default)
|
|
243
410
|
if action['resource'].present?
|
|
244
411
|
check_resource_conformance_to_order_or_encounter_profile(action['resource'], request_body,
|
|
245
|
-
error_prefix, ig_semver)
|
|
412
|
+
error_prefix, ig_semver, validator:)
|
|
246
413
|
end
|
|
247
414
|
reject_resource_issues(validation_issues)
|
|
248
415
|
end
|
|
249
416
|
|
|
250
417
|
def manually_check_update_coverage_action_errors(action, validation_issues,
|
|
251
|
-
error_prefix, ig_semver)
|
|
418
|
+
error_prefix, ig_semver, validator: :default)
|
|
252
419
|
check_required_action_type(action, 'update', error_prefix, 'coverage update action response type')
|
|
253
420
|
if action['resource'].present?
|
|
254
|
-
check_resource_conformance_to_coverage_profile(action['resource'], error_prefix, ig_semver)
|
|
421
|
+
check_resource_conformance_to_coverage_profile(action['resource'], error_prefix, ig_semver, validator:)
|
|
255
422
|
end
|
|
256
423
|
reject_resource_issues(validation_issues)
|
|
257
424
|
end
|
|
258
425
|
|
|
259
426
|
def manually_check_form_completion_action_errors(action, validation_issues,
|
|
260
|
-
error_prefix, ig_semver)
|
|
427
|
+
error_prefix, ig_semver, validator: :default)
|
|
261
428
|
check_required_action_type(action, 'create', error_prefix, 'form completion action response type')
|
|
262
429
|
if action['resource'].present?
|
|
263
|
-
check_resource_conformance_to_questionnaire_task_profile(action['resource'], error_prefix, ig_semver
|
|
430
|
+
check_resource_conformance_to_questionnaire_task_profile(action['resource'], error_prefix, ig_semver,
|
|
431
|
+
validator:)
|
|
264
432
|
end
|
|
265
433
|
reject_resource_issues(validation_issues)
|
|
266
434
|
end
|
|
@@ -7,14 +7,21 @@ module DaVinciCRDTestKit
|
|
|
7
7
|
ORDER_SIGN_TAG = 'order-sign'.freeze
|
|
8
8
|
DISCOVERY_TAG = 'cds_discovery'.freeze
|
|
9
9
|
ANY_HOOK_TAG = 'any_hook'.freeze
|
|
10
|
+
CROSS_HOOK_ANALYSIS_TAG = 'cross_hook'.freeze
|
|
10
11
|
DATA_FETCH_TAG = 'data_fetch'.freeze
|
|
11
12
|
PAYER_ORG_FETCH_TAG = 'payer_org'.freeze
|
|
12
13
|
PARENT_LOCATION_FETCH_TAG = 'parent_location'.freeze
|
|
13
14
|
HOOK_INSTANCE_TAG_PREFIX = 'hi_'.freeze
|
|
14
15
|
HOOK_INSTANCE_DATA_FETCH_TAG_PREFIX = 'hi_data_fetch_'.freeze
|
|
15
16
|
LONG_RUNNING_GROUP_TAG = 'long_running_request'.freeze
|
|
17
|
+
UNKNOWN_CONTENT_GROUP_TAG = 'unknown_content_request'.freeze
|
|
18
|
+
SELF_PAY_GROUP_TAG = 'self_pay_request'.freeze
|
|
16
19
|
DUPLICATED_HOOK_INSTANCE_TAG = 'duplicate_hook_instance'.freeze
|
|
17
20
|
COVERAGE_INFO_DISABLED_TAG = 'coverage-info-disabled'.freeze
|
|
21
|
+
TECHNICAL_ISSUES_TAG = 'technical-issues'.freeze
|
|
22
|
+
NO_MEMBER_FOUND_TAG = 'no-member-found'.freeze
|
|
23
|
+
COVERAGE_NOT_FOUND_TAG = 'coverage-not-found'.freeze
|
|
24
|
+
NO_ACTIVE_COVERAGE_TAG = 'no-active-coverage'.freeze
|
|
18
25
|
UNKNOWN_CONFIGURATION_TAG = 'unknown-configuration'.freeze
|
|
19
26
|
UNKNOWN_CONTEXT_TAG = 'unknown-context'.freeze
|
|
20
27
|
UNKNOWN_ELEMENT_TAG = 'unknown-element'.freeze
|
|
Binary file
|
|
@@ -1216,7 +1216,7 @@ hl7.fhir.us.davinci-crd_2.2.1,hook-35,https://hl7.org/fhir/us/davinci-crd/2.2.1/
|
|
|
1216
1216
|
hl7.fhir.us.davinci-crd_2.2.1,hook-36,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/hooks.html#ci-c-hook-36,"Where CRD Clients have an appropriate workflow and data capture mechanism, the order-select hook **MAY** be used in scenarios that do not involve creating a true order.",MAY,CRD Client,,true,,
|
|
1217
1217
|
hl7.fhir.us.davinci-crd_2.2.1,hook-37,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/hooks.html#ci-c-hook-37,The 'context' field in invocations of the order-sign hook **SHALL** conform to the logical model specified [here](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/StructureDefinition-CRDOrderSignContext.html),SHALL,CRD Client,,true,,
|
|
1218
1218
|
hl7.fhir.us.davinci-crd_2.2.1,hook-38,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/hooks.html#ci-c-hook-38,CRD Servers **MAY** use the order-sign hook as a basis for associating a patient with a particular practitioner from a payer attribution perspective.,MAY,CRD Server,,false,,
|
|
1219
|
-
hl7.fhir.us.davinci-crd_2.2.1,hook-39,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/hooks.html#ci-c-hook-39,"CRD clients and servers **SHALL**, at minimum, support returning and processing the [Coverage Information](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/StructureDefinition-ext-coverage-information.html) system action for all invocations of the order-
|
|
1219
|
+
hl7.fhir.us.davinci-crd_2.2.1,hook-39,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/hooks.html#ci-c-hook-39,"CRD clients and servers **SHALL**, at minimum, support returning and processing the [Coverage Information](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/StructureDefinition-ext-coverage-information.html) system action for all invocations of the order-sign hook.",SHALL,"CRD Client, CRD Server",,false,,
|
|
1220
1220
|
hl7.fhir.us.davinci-crd_2.2.1,impl-1,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/implementation.html#ci-c-impl-1,Clients that suppress 'default presumption' coverage-information of messages **SHALL** mitigate the potential for misinterpretation in the event CRD is unavailable.,SHALL,CRD Client,,false,,
|
|
1221
1221
|
hl7.fhir.us.davinci-crd_2.2.1,impl-2,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/implementation.html#ci-c-impl-2,CRD servers **SHOULD** strive to achieve a minimum of 3-9s availability for their services and strive to provide at least some level of useful response to CRD clients even if some of their back-end systems are unavailable.,SHOULD,CRD Server,,false,,
|
|
1222
1222
|
hl7.fhir.us.davinci-crd_2.2.1,impl-3,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/implementation.html#ci-c-impl-3,"Even if implemented using multiple components, there is still a requirement that the exchanges between the provider HIT (including any ePA coordinators) and the payer HIT (including any ePA coordinators) **SHALL** replicate all of the defined exchanges between provider and payer.",SHALL,"CRD Client, CRD Server",,false,,
|
|
@@ -1311,7 +1311,11 @@ hl7.fhir.us.davinci-crd_2.2.1,resp-69,https://hl7.org/fhir/us/davinci-crd/2.2.1/
|
|
|
1311
1311
|
hl7.fhir.us.davinci-crd_2.2.1,resp-70,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#ci-c-resp-70,"If returning a card rather than a system action, the ""Update Coverage Records"" response type **SHOULD NOT** be returned for hook types that are likely to be triggered by clinical users rather than administrative staff. Cards of this type would be appropriate for hooks such as encounter-start or appointment-book but would not be appropriate for order-select or order-sign.",SHOULD NOT,CRD Server,,true,,
|
|
1312
1312
|
hl7.fhir.us.davinci-crd_2.2.1,resp-71,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#ci-c-resp-71,Adjust Coverage responses **SHALL** comply with the logical model profile found [here](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/StructureDefinition-CRDHooksResponse-adjustCoverage.html).,SHALL,CRD Server,,false,,
|
|
1313
1313
|
hl7.fhir.us.davinci-crd_2.2.1,resp-72,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#ci-c-resp-72,Launch SMART responses **SHALL** comply with the logical model profile found [here](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/StructureDefinition-CRDHooksResponse-launchSMART.html).,SHALL,CRD Server,,false,,
|
|
1314
|
-
hl7.fhir.us.davinci-crd_2.2.1,sec-1,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/security.html#ci-c-sec-1,Implementers SHALL adhere to
|
|
1314
|
+
hl7.fhir.us.davinci-crd_2.2.1,sec-1,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/security.html#ci-c-sec-1,"Implementers SHALL adhere to any security and privacy rules defined by:
|
|
1315
|
+
- FHIR Core: [Security & Privacy Module](http://hl7.org/fhir/R4/secpriv-module.html), [Security Principles](http://hl7.org/fhir/R4/security.html) and [Implementer's Checklist](http://hl7.org/fhir/R4/safety.html)
|
|
1316
|
+
- HRex: [Privacy & Security](http://hl7.org/fhir/us/davinci-hrex/1.2.0/security.html)
|
|
1317
|
+
- CDS Hooks: [Security & Safety](http://cds-hooks.hl7.org/2026Jan/index.html#security-and-safety)
|
|
1318
|
+
- SMART on FHIR: [SMART App Launch](http://www.hl7.org/fhir/smart-app-launch)",SHALL,"CRD Client, CRD Server",,false,,
|
|
1315
1319
|
hl7.fhir.us.davinci-crd_2.2.1,sec-2,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/security.html#ci-c-sec-2,"As per the CDS Hooks specification, communications between CRD clients and CRD servers **SHALL** use TLS.",SHALL,"CRD Client, CRD Server",,false,,
|
|
1316
1320
|
hl7.fhir.us.davinci-crd_2.2.1,sec-3,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/security.html#ci-c-sec-3,CRD servers and CRD clients **SHOULD** enforce a minimum version and other TLS configuration requirements based on [HRex rules](http://hl7.org/fhir/us/davinci-hrex/1.2.0/security.html#exchange-security) for PHI exchange.,SHOULD,"CRD Client, CRD Server",,false,,
|
|
1317
1321
|
hl7.fhir.us.davinci-crd_2.2.1,sec-4,https://hl7.org/fhir/us/davinci-crd/2.2.1/en/security.html#ci-c-sec-4,CRD clients that support the Launch SMART Application Response Type **SHALL** support running applications that adhere to the SMART on FHIR [confidential app](https://hl7.org/fhir/smart-app-launch/STU2.2/app-launch.html#support-for-public-and-confidential-apps) profile.,SHALL,CRD Client,,true,,
|