davinci_pdex_test_kit 0.12.0 → 0.12.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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/pdex_payer_client_postman_preset.json.erb +67 -0
  3. data/lib/davinci_pdex_test_kit/docs/payer_client_suite_description_v200.md +124 -32
  4. data/lib/davinci_pdex_test_kit/pdex_payer_client/client_auth_smart_alca_group.rb +32 -0
  5. data/lib/davinci_pdex_test_kit/pdex_payer_client/client_auth_smart_alcs_group.rb +32 -0
  6. data/lib/davinci_pdex_test_kit/pdex_payer_client/client_auth_smart_alp_group.rb +32 -0
  7. data/lib/davinci_pdex_test_kit/pdex_payer_client/client_auth_udap_group.rb +31 -0
  8. data/lib/davinci_pdex_test_kit/pdex_payer_client/client_member_match_tests/client_member_match_validation_test.rb +0 -1
  9. data/lib/davinci_pdex_test_kit/pdex_payer_client/client_registration/configuration_display_smart_test.rb +38 -0
  10. data/lib/davinci_pdex_test_kit/pdex_payer_client/client_registration/configuration_display_udap_test.rb +38 -0
  11. data/lib/davinci_pdex_test_kit/pdex_payer_client/client_registration_group.rb +67 -0
  12. data/lib/davinci_pdex_test_kit/pdex_payer_client/client_validation_test.rb +10 -2
  13. data/lib/davinci_pdex_test_kit/pdex_payer_client/client_workflow_interaction_test.rb +37 -7
  14. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/allergyintolerance_clinical_data_request_test.rb +0 -1
  15. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/careplan_clinical_data_request_test.rb +0 -1
  16. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/careteam_clinical_data_request_test.rb +0 -1
  17. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/condition_clinical_data_request_test.rb +0 -1
  18. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/device_clinical_data_request_test.rb +1 -2
  19. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/diagnosticreport_clinical_data_request_test.rb +0 -1
  20. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/documentreference_clinical_data_request_test.rb +0 -1
  21. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/encounter_clinical_data_request_test.rb +0 -1
  22. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/explanationofbenefit_clinical_data_request_test.rb +0 -1
  23. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/goal_clinical_data_request_test.rb +0 -1
  24. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/immunization_clinical_data_request_test.rb +0 -1
  25. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/location_clinical_data_request_test.rb +0 -1
  26. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/medicationdispense_clinical_data_request_test.rb +0 -1
  27. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/medicationrequest_clinical_data_request_test.rb +0 -1
  28. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/observation_clinical_data_request_test.rb +0 -1
  29. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/organization_clinical_data_request_test.rb +0 -1
  30. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/patient_clinical_data_request_test.rb +0 -1
  31. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/practitioner_clinical_data_request_test.rb +0 -1
  32. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/practitionerrole_clinical_data_request_test.rb +0 -1
  33. data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/procedure_clinical_data_request_test.rb +0 -1
  34. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/export_endpoint.rb +1 -1
  35. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/export_status_endpoint.rb +1 -1
  36. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/next_page_endpoint.rb +9 -2
  37. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/patient_endpoint.rb +1 -1
  38. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/proxy_endpoint.rb +15 -6
  39. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/resource_read_endpoint.rb +1 -1
  40. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/resource_search_endpoint.rb +1 -1
  41. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server.rb +28 -2
  42. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_udap_smart_server/authorization_endpoint.rb +53 -0
  43. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_udap_smart_server/token_endpoint.rb +85 -0
  44. data/lib/davinci_pdex_test_kit/pdex_payer_client/pdex_client_options.rb +26 -0
  45. data/lib/davinci_pdex_test_kit/pdex_payer_client/tags.rb +8 -9
  46. data/lib/davinci_pdex_test_kit/pdex_payer_client/urls.rb +17 -9
  47. data/lib/davinci_pdex_test_kit/pdex_payer_client/visual_inspection_and_attestation/authentication.rb +34 -0
  48. data/lib/davinci_pdex_test_kit/pdex_payer_client/visual_inspection_and_attestation/must_support.rb +40 -0
  49. data/lib/davinci_pdex_test_kit/pdex_payer_client/visual_inspection_and_attestation/provenance.rb +32 -0
  50. data/lib/davinci_pdex_test_kit/pdex_payer_client/visual_inspection_and_attestation/receive_must_support.rb +34 -0
  51. data/lib/davinci_pdex_test_kit/pdex_payer_client/visual_inspection_and_attestation.rb +24 -0
  52. data/lib/davinci_pdex_test_kit/pdex_payer_client_suite.rb +65 -2
  53. data/lib/davinci_pdex_test_kit/pdex_payer_server/urls.rb +27 -0
  54. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/bulk_data_transmission_restrictions.rb +33 -0
  55. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/consent_failure.rb +40 -0
  56. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/consent_requirements.rb +40 -0
  57. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/hrex_must_support.rb +35 -0
  58. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/licensing.rb +37 -0
  59. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/member_auth.rb +81 -0
  60. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/mtls.rb +61 -0
  61. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/payer_consent_compliance.rb +33 -0
  62. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/prior_authorization_decisions.rb +35 -0
  63. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/provenance_records.rb +40 -0
  64. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/read_and_search_hrex.rb +35 -0
  65. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation/resources_in_capability_statement.rb +35 -0
  66. data/lib/davinci_pdex_test_kit/pdex_payer_server/visual_inspection_and_attestation.rb +39 -0
  67. data/lib/davinci_pdex_test_kit/pdex_payer_server/workflow_export_group.rb +2 -0
  68. data/lib/davinci_pdex_test_kit/pdex_payer_server_suite.rb +29 -3
  69. data/lib/davinci_pdex_test_kit/pdex_provider_client_suite.rb +8 -0
  70. data/lib/davinci_pdex_test_kit/requirements/davinci_pdex_test_kit_requirements.csv +115 -0
  71. data/lib/davinci_pdex_test_kit/requirements/generated/pdex_payer_client_requirements_coverage.csv +29 -0
  72. data/lib/davinci_pdex_test_kit/requirements/generated/pdex_payer_server_requirements_coverage.csv +479 -0
  73. data/lib/davinci_pdex_test_kit/requirements/hl7.fhir.us.davinci-pdex_2.0.0_reqs.xlsx +0 -0
  74. data/lib/davinci_pdex_test_kit/version.rb +2 -2
  75. data/lib/davinci_pdex_test_kit.rb +0 -1
  76. metadata +70 -17
  77. data/config/presets/pdex_payer_client_postman_preset.json +0 -12
  78. data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/token_endpoint.rb +0 -27
  79. data/lib/davinci_pdex_test_kit/requirements/davinci-pdex-test-kit_out_of_scope_requirements.csv +0 -1
  80. data/lib/davinci_pdex_test_kit/requirements/davinci-pdex-test-kit_requirements.csv +0 -64
  81. data/lib/davinci_pdex_test_kit/requirements/generated/davinci-pdex-test-kit_requirements_coverage.csv +0 -64
  82. data/lib/inferno_requirements_tools/ext/inferno_core/runnable.rb +0 -22
  83. data/lib/inferno_requirements_tools/rake/rakefile_template +0 -19
  84. data/lib/inferno_requirements_tools/tasks/requirements_coverage.rb +0 -284
  85. data/lib/requirements_config.yaml +0 -17
@@ -4,12 +4,10 @@ module DaVinciPDexTestKit
4
4
  module PDexPayerClient
5
5
 
6
6
  module URLs
7
- BASE_PATH = "#{Inferno::Application['base_url']}/custom/pdex_payer_client"
8
- TOKEN_PATH = '/mock_auth/token'
9
7
  PATIENT_PATH = '/fhir/Patient'
8
+ PATIENT_INSTANCE_PATH = '/fhir/Patient/:patient'
10
9
  RESOURCE_PATH = '/fhir/:endpoint'
11
10
  INSTANCE_PATH = '/fhir/:endpoint/:id'
12
- SUBMIT_PATH = '/fhir/:endpoint' # FIXME duplicate
13
11
  BINARY_PATH = '/fhir/Binary/:id'
14
12
  METADATA_PATH = '/fhir/metadata'
15
13
  EVERYTHING_PATH = '/fhir/Patient/:patient/$everything'
@@ -19,7 +17,9 @@ module DaVinciPDexTestKit
19
17
  BASE_FHIR_PATH = '/fhir'
20
18
  RESUME_PASS_PATH = '/resume_pass'
21
19
  RESUME_CLINICAL_DATA_PATH = '/resume_clinical_data'
22
- RESUME_FAIL_PATH = '/resume_fail'
20
+ RESUME_FAIL_PATH = '/resume_fail'
21
+ AUTHORIZATION_PATH = '/auth/authorization'
22
+ TOKEN_PATH = '/auth/token'
23
23
 
24
24
  constants.each do |path_constant|
25
25
  # For each constant X_PATH, define x_path()
@@ -29,20 +29,28 @@ module DaVinciPDexTestKit
29
29
 
30
30
  # For each constant X_PATH, define x_url(), which includes base
31
31
  define_method(path_constant.to_s.downcase.gsub(/_path$/, '_url')) do
32
- File.join(BASE_PATH, URLs.const_get(path_constant))
32
+ base_url + URLs.const_get(path_constant)
33
33
  end
34
34
  end
35
35
 
36
+ def suite_id
37
+ PDexPayerClientSuite.id
38
+ end
39
+
36
40
  # overwrite base_url which is irregular
37
41
  def base_url
38
- BASE_PATH
42
+ @base_url ||= "#{Inferno::Application['base_url']}/custom/#{suite_id}"
39
43
  end
40
44
 
41
- # overwrite base_fhir_url which is irregular
42
- def base_fhir_url
43
- File.join(BASE_PATH, BASE_FHIR_PATH)
45
+ # overwrite fhir_base_url which is irregular
46
+ def fhir_base_url
47
+ base_url + BASE_FHIR_PATH
44
48
  end
45
49
 
50
+ # alias for smart and udap tests
51
+ def client_fhir_base_url
52
+ fhir_base_url
53
+ end
46
54
  end
47
55
 
48
56
  # Add all constants and dynamically defined methods to PDexPayerClient namespace
@@ -0,0 +1,34 @@
1
+ module DaVinciPDexTestKit
2
+ module PDexPayerClient
3
+ class PDexMemberAuthenticationTest < Inferno::Test
4
+ title 'Uses recognized Health Plan credentials'
5
+
6
+ description <<~DESCRIPTION
7
+ The Health IT Module requires members to authenticate
8
+ using credentials issued or recognized by the Health Plan, such as credentials used to access
9
+ a member portal, and accepts only those credentials when processing member-authorized requests.
10
+ DESCRIPTION
11
+
12
+ id :pdex_member_authentication_test
13
+
14
+ verifies_requirements 'hl7.fhir.us.davinci-pdex_2.0.0@10'
15
+
16
+ run do
17
+ identifier = SecureRandom.hex(32)
18
+
19
+ wait(
20
+ identifier:,
21
+ message: <<~MESSAGE
22
+ I attest that the Health IT Module requires members to authenticate
23
+ using credentials issued or recognized by the Health Plan, such as credentials used to access
24
+ a member portal, and accepts only those credentials when processing member-authorized requests.
25
+
26
+ [Click here](#{resume_pass_url}?token=#{identifier}) if the system **meets** this requirement.
27
+
28
+ [Click here](#{resume_fail_url}?token=#{identifier}) if the system **does not meet** this requirement.
29
+ MESSAGE
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ module DaVinciPDexTestKit
2
+ module PDexPayerClient
3
+ class PDexClientMustSupportInterpretationTest < Inferno::Test
4
+ title 'Interprets Must Support according to US Core and HRex'
5
+
6
+ description <<~DESCRIPTION
7
+ The Health IT Module applies Must Support rules for all profiles it implements as follows:
8
+
9
+ - For US Core profiles, Must Support elements are interpreted according to the US Core IG.
10
+ - For HRex profiles, Must Support elements are interpreted according to the HRex IG.
11
+ - For PDex profiles, Must Support elements are interpreted according to the US Core IG.
12
+ DESCRIPTION
13
+
14
+ id :pdex_client_must_support_interpretation_test
15
+
16
+ verifies_requirements 'hl7.fhir.us.davinci-pdex_2.0.0@4',
17
+ 'hl7.fhir.us.davinci-pdex_2.0.0@6',
18
+ 'hl7.fhir.us.davinci-pdex_2.0.0@8'
19
+
20
+ run do
21
+ identifier = SecureRandom.hex(32)
22
+
23
+ wait(
24
+ identifier:,
25
+ message: <<~MESSAGE
26
+ The developer of the Health IT Module attests that:
27
+
28
+ - For US Core profiles, Must Support elements are interpreted according to the US Core IG.
29
+ - For HRex profiles, Must Support elements are interpreted according to the HRex IG.
30
+ - For PDex profiles, Must Support elements are interpreted according to the US Core IG.
31
+
32
+ [Click here](#{resume_pass_url}?token=#{identifier}) if the system **meets** these requirements.
33
+
34
+ [Click here](#{resume_fail_url}?token=#{identifier}) if the system **does not meet** these requirements.
35
+ MESSAGE
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,32 @@
1
+ module DaVinciPDexTestKit
2
+ module PDexPayerClient
3
+ class PDexRetainProvenanceFromPayerExchangeTest < Inferno::Test
4
+ title 'Accepts and retains Provenance in member-authorized payer-to-payer exchange'
5
+
6
+ description <<~DESCRIPTION
7
+ The Health IT Module accepts and retains
8
+ Provenance records received with data as part of a member-authorized payer-to-payer exchange.
9
+ DESCRIPTION
10
+
11
+ id :pdex_accept_retain_provenance_test
12
+
13
+ verifies_requirements 'hl7.fhir.us.davinci-pdex_2.0.0@28'
14
+
15
+ run do
16
+ identifier = SecureRandom.hex(32)
17
+
18
+ wait(
19
+ identifier:,
20
+ message: <<~MESSAGE
21
+ I attest that the Health IT Module accepts and retains
22
+ Provenance records received with data as part of a member-authorized payer-to-payer exchange.
23
+
24
+ [Click here](#{resume_pass_url}?token=#{identifier}) if the system **meets** this requirement.
25
+
26
+ [Click here](#{resume_fail_url}?token=#{identifier}) if the system **does not meet** this requirement.
27
+ MESSAGE
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,34 @@
1
+ module DaVinciPDexTestKit
2
+ module PDexPayerClient
3
+ class PDexMustSupportSubElementHandlingTest < Inferno::Test
4
+ title 'Accepts Must Support elements without error'
5
+
6
+ description <<~DESCRIPTION
7
+ The Health IT Module ensures that it can accept sub-elements marked Must Support
8
+ without generating errors — unless those sub-elements belong to a parent element
9
+ that has a minimum cardinality of 0 and no Must Support flag.
10
+ DESCRIPTION
11
+
12
+ id :pdex_must_support_sub_element_handling_test
13
+
14
+ verifies_requirements 'hl7.fhir.us.davinci-pdex_2.0.0@53'
15
+
16
+ run do
17
+ identifier = SecureRandom.hex(32)
18
+
19
+ wait(
20
+ identifier:,
21
+ message: <<~MESSAGE
22
+ The developer of the Health IT Module attests that the Health IT System can accept sub-elements marked Must Support
23
+ without generating errors — unless those sub-elements belong to a parent element
24
+ that has a minimum cardinality of 0 and no Must Support flag.
25
+
26
+ [Click here](#{resume_pass_url}?token=#{identifier}) if the system **meets** this requirement.
27
+
28
+ [Click here](#{resume_fail_url}?token=#{identifier}) if the system **does not meet** this requirement.
29
+ MESSAGE
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'visual_inspection_and_attestation/must_support'
2
+ require_relative 'visual_inspection_and_attestation/receive_must_support'
3
+ require_relative 'visual_inspection_and_attestation/provenance'
4
+ require_relative 'visual_inspection_and_attestation/authentication'
5
+
6
+ module DaVinciPDexTestKit
7
+ module PDexPayerClient
8
+ class PDexClientVisualInspectionAndAttestationGroup < Inferno::TestGroup
9
+ id :pdex_client_visual_inspection_and_attestation
10
+ title 'Visual Inspection and Attestation'
11
+
12
+ description <<~DESCRIPTION
13
+ Perform visual inspections or attestations to ensure that the Client is conformant to the Da Vinci Payer Data Exchange IG requirements.
14
+ DESCRIPTION
15
+
16
+ run_as_group
17
+
18
+ test from: :pdex_member_authentication_test
19
+ test from: :pdex_client_must_support_interpretation_test
20
+ test from: :pdex_must_support_sub_element_handling_test
21
+ test from: :pdex_accept_retain_provenance_test
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,4 @@
1
+ require_relative 'pdex_payer_client/pdex_client_options'
1
2
  require_relative 'pdex_payer_client/urls'
2
3
  require_relative 'pdex_payer_client/tags'
3
4
  require_relative 'pdex_payer_client/collection'
@@ -5,6 +6,11 @@ require_relative 'pdex_payer_client/mock_server'
5
6
  # require_relative 'must_support_test'
6
7
  # require_relative 'pdex_payer_client/client_validation_test'
7
8
 
9
+ require_relative 'pdex_payer_client/client_registration_group'
10
+ require_relative 'pdex_payer_client/client_auth_smart_alca_group'
11
+ require_relative 'pdex_payer_client/client_auth_smart_alcs_group'
12
+ require_relative 'pdex_payer_client/client_auth_smart_alp_group'
13
+ require_relative 'pdex_payer_client/client_auth_udap_group'
8
14
  require_relative 'pdex_payer_client/client_workflow_interaction_test'
9
15
  require_relative 'pdex_payer_client/client_member_match_tests/client_member_match_validation_test'
10
16
 
@@ -31,6 +37,8 @@ require_relative 'pdex_payer_client/clinical_data_request_tests/practitioner_cli
31
37
  require_relative 'pdex_payer_client/clinical_data_request_tests/practitionerrole_clinical_data_request_test'
32
38
  require_relative 'pdex_payer_client/clinical_data_request_tests/procedure_clinical_data_request_test'
33
39
 
40
+ require_relative 'pdex_payer_client/visual_inspection_and_attestation'
41
+
34
42
  module DaVinciPDexTestKit
35
43
  class PDexPayerClientSuite < Inferno::TestSuite
36
44
  include PDexPayerClient
@@ -70,6 +78,35 @@ module DaVinciPDexTestKit
70
78
  end
71
79
  end
72
80
 
81
+ requirement_sets(
82
+ {
83
+ identifier: 'hl7.fhir.us.davinci-pdex_2.0.0',
84
+ title: 'Da Vinci Payer Data Exchange (PDex) v2.0.0',
85
+ actor: 'Client'
86
+ }
87
+ )
88
+
89
+ suite_option :client_type,
90
+ title: 'Client Security Type',
91
+ list_options: [
92
+ {
93
+ label: 'SMART App Launch Public Client',
94
+ value: PDexClientOptions::SMART_APP_LAUNCH_PUBLIC
95
+ },
96
+ {
97
+ label: 'SMART App Launch Confidential Symmetric Client',
98
+ value: PDexClientOptions::SMART_APP_LAUNCH_CONFIDENTIAL_SYMMETRIC
99
+ },
100
+ {
101
+ label: 'SMART App Launch Confidential Asymmetric Client',
102
+ value: PDexClientOptions::SMART_APP_LAUNCH_CONFIDENTIAL_ASYMMETRIC
103
+ },
104
+ {
105
+ label: 'UDAP Authorization Code Client',
106
+ value: PDexClientOptions::UDAP_AUTHORIZATION_CODE
107
+ }
108
+ ]
109
+
73
110
  resume_test_route :get, RESUME_PASS_PATH do |request|
74
111
  PDexPayerClientSuite.extract_token_from_query_params(request)
75
112
  end
@@ -82,18 +119,37 @@ module DaVinciPDexTestKit
82
119
  PDexPayerClientSuite.extract_token_from_query_params(request)
83
120
  end
84
121
 
122
+ group from: :pdex_client_registration
123
+
85
124
  group do
86
125
  run_as_group
87
- title 'Workflow Tests'
126
+ title 'Verify PDex Data Access'
88
127
  id :payer_to_payer_workflow
89
128
 
90
129
  group do
91
130
  title 'Interaction Tests'
92
- id :client_workflow_interaction
131
+ id :pdex_client_workflow_interaction
93
132
 
94
133
  test from: :pdex_client_workflow_interaction
95
134
  end
96
135
 
136
+ group from: :pdex_client_auth_smart_alca,
137
+ required_suite_options: {
138
+ client_type: PDexClientOptions::SMART_APP_LAUNCH_CONFIDENTIAL_ASYMMETRIC
139
+ }
140
+ group from: :pdex_client_auth_smart_alcs,
141
+ required_suite_options: {
142
+ client_type: PDexClientOptions::SMART_APP_LAUNCH_CONFIDENTIAL_SYMMETRIC
143
+ }
144
+ group from: :pdex_client_auth_smart_alp,
145
+ required_suite_options: {
146
+ client_type: PDexClientOptions::SMART_APP_LAUNCH_PUBLIC
147
+ }
148
+ group from: :pdex_client_auth_udap,
149
+ required_suite_options: {
150
+ client_type: PDexClientOptions::UDAP_AUTHORIZATION_CODE
151
+ }
152
+
97
153
  group do
98
154
  title '$member-match validation'
99
155
  id :member_match_validation
@@ -130,8 +186,15 @@ module DaVinciPDexTestKit
130
186
  end
131
187
  end
132
188
 
189
+ group from: :pdex_client_visual_inspection_and_attestation do
190
+ optional
191
+ end
192
+
193
+
133
194
  # TODO: must support validation
134
195
 
196
+
197
+
135
198
  private
136
199
 
137
200
  def self.extract_token_from_query_params(request)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaVinciPDexTestKit
4
+ module PDexPayerServer
5
+ RESUME_PASS_PATH = '/resume_pass'
6
+ RESUME_FAIL_PATH = '/resume_fail'
7
+
8
+ # URLs
9
+ module URLs
10
+ def base_url
11
+ @base_url ||= "#{Inferno::Application['base_url']}/custom/#{suite_id}"
12
+ end
13
+
14
+ def resume_pass_url
15
+ @resume_pass_url ||= base_url + RESUME_PASS_PATH
16
+ end
17
+
18
+ def resume_fail_url
19
+ @resume_fail_url ||= base_url + RESUME_FAIL_PATH
20
+ end
21
+
22
+ def suite_id
23
+ PDexPayerServerSuite.id
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ require_relative '../urls'
2
+
3
+ module DaVinciPDexTestKit
4
+ class BulkDataTransmissionRestrictionsTest < Inferno::Test
5
+ include PDexPayerServer::URLs
6
+
7
+ title 'Properly restricts Bulk Data transmission of individual member data'
8
+
9
+ description <<~DESCRIPTION
10
+ The Health IT Module's use of the Bulk FHIR specification for transmission of individual member data honors jurisdictional and personal privacy restrictions.
11
+ DESCRIPTION
12
+
13
+ id :pdex_bulk_data_transmission_restrictions_test
14
+
15
+ verifies_requirements 'hl7.fhir.us.davinci-pdex_2.0.0@11'
16
+
17
+ run do
18
+ identifier = SecureRandom.hex(32)
19
+
20
+ wait(
21
+ identifier:,
22
+ message: <<~MESSAGE
23
+ The developer of the Health IT Module attests that the Health IT Module's use of the Bulk FHIR specification for transmission of individual member data
24
+ honors jurisdictional and personal privacy restrictions that are relevant to a member's health record.
25
+
26
+ [Click here](#{resume_pass_url}?token=#{identifier}) if the system **meets** this requirement.
27
+
28
+ [Click here](#{resume_fail_url}?token=#{identifier}) if the system **does not meet** this requirement.
29
+ MESSAGE
30
+ )
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../urls'
2
+
3
+ module DaVinciPDexTestKit
4
+ class PDexMemberMatchConsentFailureHandlingTest < Inferno::Test
5
+ include PDexPayerServer::URLs
6
+
7
+ title 'Handles consent non-compliance correctly during $member-match'
8
+
9
+ description <<~DESCRIPTION
10
+ The Health IT Module correctly handles situations where during the `$member-match` operation:
11
+ - If a unique match to a member is found but the consent request cannot be honored (e.g., due to unsupported data segmentation policies), the system does not return a Patient ID in the response.
12
+ - In such cases, the system returns an HTTP 422 status code with an accompanying Operation Outcome that explains why the consent request could not be honored.
13
+
14
+ DESCRIPTION
15
+
16
+ id :pdex_member_match_consent_failure_test
17
+
18
+ verifies_requirements 'hl7.fhir.us.davinci-pdex_2.0.0@38',
19
+ 'hl7.fhir.us.davinci-pdex_2.0.0@39'
20
+
21
+ run do
22
+ identifier = SecureRandom.hex(32)
23
+
24
+ wait(
25
+ identifier:,
26
+ message: <<~MESSAGE
27
+ The developer of the Health IT Module attests that during the `$member-match` operation:
28
+
29
+ - If a unique match to a member is found but the consent request cannot be honored (e.g., due to unsupported data segmentation policies), the system does not return a Patient ID in the response.
30
+
31
+ - In such cases, the system returns an HTTP 422 status code with an accompanying Operation Outcome that explains why the consent request could not be honored.
32
+
33
+ [Click here](#{resume_pass_url}?token=#{identifier}) if the system **meets** these requirements.
34
+
35
+ [Click here](#{resume_fail_url}?token=#{identifier}) if the system **does not meet** these requirements.
36
+ MESSAGE
37
+ )
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../urls'
2
+
3
+ module DaVinciPDexTestKit
4
+ class ConsentRequirementsTest < Inferno::Test
5
+ include PDexPayerServer::URLs
6
+
7
+ title 'Assesses consent requirements'
8
+
9
+ description <<~DESCRIPTION
10
+ The Health IT Module considers consent requirements to be met only if:
11
+ - Member Identity is matched
12
+ - Consent Policy (Everything or only Non-Sensitive data) matches the data release segmentation capabilities of the receiving payer
13
+ - Date period for consent is valid
14
+ - Payer requesting retrieval of data is matched.
15
+ DESCRIPTION
16
+
17
+ id :pdex_consent_requirements_test
18
+
19
+ verifies_requirements 'hl7.fhir.us.davinci-pdex_2.0.0@40'
20
+
21
+ run do
22
+ identifier = SecureRandom.hex(32)
23
+
24
+ wait(
25
+ identifier:,
26
+ message: <<~MESSAGE
27
+ The developer of the Health IT Module attests that the Health IT Module considers consent requirements to be met only if:
28
+ - Member Identity is matched
29
+ - Consent Policy (Everything or only Non-Sensitive data) matches the data release segmentation capabilities of the receiving payer
30
+ - Date period for consent is valid
31
+ - Payer requesting retrieval of data is matched.
32
+
33
+ [Click here](#{resume_pass_url}?token=#{identifier}) if the system **meets** this requirement.
34
+
35
+ [Click here](#{resume_fail_url}?token=#{identifier}) if the system **does not meet** this requirement.
36
+ MESSAGE
37
+ )
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,35 @@
1
+ require_relative '../urls'
2
+
3
+ module DaVinciPDexTestKit
4
+ class PDexMustSupportDefinedByHRexTest < Inferno::Test
5
+ include PDexPayerServer::URLs
6
+
7
+ title 'Uses HRex Must Support definitions for HRex profiles'
8
+
9
+ description <<~DESCRIPTION
10
+ The Health IT Module applies the definition of "Must Support" as defined
11
+ by the Da Vinci HRex Implementation Guide for all HRex profiles referenced in PDex.
12
+ DESCRIPTION
13
+
14
+ id :pdex_must_support_defined_by_hrex_test
15
+
16
+ verifies_requirements 'hl7.fhir.us.davinci-pdex_2.0.0@5'
17
+
18
+ run do
19
+ identifier = SecureRandom.hex(32)
20
+
21
+ wait(
22
+ identifier:,
23
+ message: <<~MESSAGE
24
+ The developer of the Health IT Module attests that the system applies the definition
25
+ of "Must Support" as defined by the Da Vinci HRex Implementation Guide for all
26
+ HRex profiles referenced in PDex.
27
+
28
+ [Click here](#{resume_pass_url}?token=#{identifier}) if the system **meets** this requirement.
29
+
30
+ [Click here](#{resume_fail_url}?token=#{identifier}) if the system **does not meet** this requirement.
31
+ MESSAGE
32
+ )
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ require_relative '../urls'
2
+
3
+ module DaVinciPDexTestKit
4
+ class PDexLicensingTest < Inferno::Test
5
+ include PDexPayerServer::URLs
6
+
7
+ title 'Complies with licensing requirements'
8
+
9
+ description <<~DESCRIPTION
10
+ The Health IT Module abides by the license
11
+ requirements for each terminology content artifact utilized within a functioning implementation and obtained
12
+ terminology licenses from the Third-Party IP owner for each code system and/or other specified artifact used.
13
+ DESCRIPTION
14
+
15
+ id :pdex_licensing_test
16
+
17
+ verifies_requirements 'hl7.fhir.us.davinci-pdex_2.0.0@1',
18
+ 'hl7.fhir.us.davinci-pdex_2.0.0@2'
19
+
20
+ run do
21
+ identifier = SecureRandom.hex(32)
22
+
23
+ wait(
24
+ identifier:,
25
+ message: <<~MESSAGE
26
+ The developer of the Health IT Module attests that the Health IT Module abides by the license
27
+ requirements for each terminology content artifact utilized within a functioning implementation and obtained
28
+ terminology licenses from the Third-Party IP owner for each code system and/or other specified artifact used.
29
+
30
+ [Click here](#{resume_pass_url}?token=#{identifier}) if the system **meets** these requirements.
31
+
32
+ [Click here](#{resume_fail_url}?token=#{identifier}) if the system **does not meet** these requirements.
33
+ MESSAGE
34
+ )
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,81 @@
1
+ require_relative '../urls'
2
+
3
+ module DaVinciPDexTestKit
4
+ class PDexMemberAuthorizedExchangeTest < Inferno::Test
5
+ include PDexPayerServer::URLs
6
+
7
+ title 'Supports Payer-to-Payer member-authorized exchange'
8
+
9
+ description <<~DESCRIPTION
10
+ The Health IT Module supports Payer-to-Payer member-authorized
11
+ information exchange using SMART on FHIR and OAuth 2.0 by satisfying the following criteria.
12
+
13
+ The Health IT Module is acting as the **source** Health Plan, and is the Health Plan the member would like to get data from.
14
+ The **target** Health Plan is the Health PLan the member would like to share data to.
15
+
16
+ 1. **Client Authorization Credentials**
17
+ The Health IT Module issues the target Health Plan OAuth 2.0 client application credentials during client registration.
18
+
19
+ 1. **Member Consent Flow**
20
+ After the member authenticates to the Health IT Module's authorization server, the system presents an Authorization
21
+ screen enabling the member to approve sharing with the target Health Plan.
22
+
23
+ The Authorization process aligns with applicable privacy policy and regulations, allowing members to
24
+ select what data may be shared.
25
+
26
+ 4. **Token Issuance**
27
+ Upon successful authorization, the Health IT Module issues an Access Token to the target Health Plan.
28
+ The scopes associated with the Access Token are limited to the information and permissions authorized by the member.
29
+
30
+ 6. **Refresh Token Handling**:
31
+ Any Access Token subsequently issued by the Health IT Module using a Refresh Token enforces the same scope and member-specific
32
+ restrictions as the original authorization.
33
+ DESCRIPTION
34
+
35
+ id :pdex_member_authorized_exchange_test
36
+
37
+ verifies_requirements 'hl7.fhir.us.davinci-pdex_2.0.0@20',
38
+ 'hl7.fhir.us.davinci-pdex_2.0.0@21',
39
+ 'hl7.fhir.us.davinci-pdex_2.0.0@22',
40
+ 'hl7.fhir.us.davinci-pdex_2.0.0@23',
41
+ 'hl7.fhir.us.davinci-pdex_2.0.0@25',
42
+ 'hl7.fhir.us.davinci-pdex_2.0.0@26'
43
+
44
+ run do
45
+ identifier = SecureRandom.hex(32)
46
+
47
+ wait(
48
+ identifier:,
49
+ message: <<~MESSAGE
50
+ I attest that the Health IT Module supports Payer-to-Payer member-authorized
51
+ information exchange using SMART on FHIR and OAuth 2.0 by satisfying the following criteria.
52
+
53
+ The **source** Health Plan is the Health Plan the member would like to get data from, and the **etarget**
54
+ Health Plan is the Health PLan the member would like to share data to.
55
+
56
+ 1. **Client Authorization Credentials**
57
+ The Health IT Module issues the target Health Plan OAuth 2.0 client application credentials during client registration.
58
+
59
+ 1. **Member Consent Flow**
60
+ After the member authenticates to the Health IT Module's authorization server, the system presents an Authorization
61
+ screen enabling the member to approve sharing with the target Health Plan.
62
+
63
+ The Authorization process aligns with applicable privacy policy and regulations, allowing members to
64
+ select what data may be shared.
65
+
66
+ 4. **Token Issuance**
67
+ Upon successful authorization, the Health IT Module issues an Access Token to the target Health Plan.
68
+ The scopes associated with the Access Token are limited to the information and permissions authorized by the member.
69
+
70
+ 6. **Refresh Token Handling**:
71
+ Any Access Token subsequently issued by the Health IT Module using a Refresh Token enforces the same scope and member-specific
72
+ restrictions as the original authorization.
73
+
74
+ [Click here](#{resume_pass_url}?token=#{identifier}) if the system **meets** these requirements.
75
+
76
+ [Click here](#{resume_fail_url}?token=#{identifier}) if the system **does not meet** these requirements.
77
+ MESSAGE
78
+ )
79
+ end
80
+ end
81
+ end