onc_certification_g10_test_kit 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/inferno/exceptions.rb +31 -0
  4. data/lib/inferno/ext/bloomer.rb +24 -0
  5. data/lib/inferno/repositiories/validators.rb +17 -0
  6. data/lib/inferno/repositiories/value_sets.rb +26 -0
  7. data/lib/inferno/terminology/bcp47.rb +95 -0
  8. data/lib/inferno/terminology/bcp_13.rb +26 -0
  9. data/lib/inferno/terminology/codesystem.rb +49 -0
  10. data/lib/inferno/terminology/expected_manifest.yml +1123 -0
  11. data/lib/inferno/terminology/fhir_package_manager.rb +69 -0
  12. data/lib/inferno/terminology/loader.rb +298 -0
  13. data/lib/inferno/terminology/tasks/check_built_terminology.rb +77 -0
  14. data/lib/inferno/terminology/tasks/cleanup.rb +13 -0
  15. data/lib/inferno/terminology/tasks/cleanup_precursors.rb +23 -0
  16. data/lib/inferno/terminology/tasks/count_codes_in_value_set.rb +20 -0
  17. data/lib/inferno/terminology/tasks/create_value_set_validators.rb +34 -0
  18. data/lib/inferno/terminology/tasks/download_fhir_terminology.rb +27 -0
  19. data/lib/inferno/terminology/tasks/download_umls.rb +109 -0
  20. data/lib/inferno/terminology/tasks/download_umls_notice.rb +20 -0
  21. data/lib/inferno/terminology/tasks/expand_value_set_to_file.rb +36 -0
  22. data/lib/inferno/terminology/tasks/process_umls.rb +91 -0
  23. data/lib/inferno/terminology/tasks/process_umls_translations.rb +85 -0
  24. data/lib/inferno/terminology/tasks/run_umls_jar.rb +75 -0
  25. data/lib/inferno/terminology/tasks/temp_dir.rb +27 -0
  26. data/lib/inferno/terminology/tasks/unzip_umls.rb +42 -0
  27. data/lib/inferno/terminology/tasks/validate_code.rb +36 -0
  28. data/lib/inferno/terminology/tasks.rb +11 -0
  29. data/lib/inferno/terminology/terminology_configuration.rb +52 -0
  30. data/lib/inferno/terminology/terminology_validation.rb +42 -0
  31. data/lib/inferno/terminology/validator.rb +64 -0
  32. data/lib/inferno/terminology/value_set.rb +462 -0
  33. data/lib/inferno/terminology.rb +16 -0
  34. data/lib/onc_certification_g10_test_kit/authorization_request_builder.rb +87 -0
  35. data/lib/onc_certification_g10_test_kit/base_token_refresh_group.rb +48 -0
  36. data/lib/onc_certification_g10_test_kit/bulk_data_authorization.rb +235 -0
  37. data/lib/onc_certification_g10_test_kit/bulk_data_group_export.rb +255 -0
  38. data/lib/onc_certification_g10_test_kit/bulk_data_group_export_validation.rb +474 -0
  39. data/lib/onc_certification_g10_test_kit/bulk_data_jwks.json +58 -0
  40. data/lib/onc_certification_g10_test_kit/bulk_export_validation_tester.rb +171 -0
  41. data/lib/onc_certification_g10_test_kit/configuration_checker.rb +104 -0
  42. data/lib/onc_certification_g10_test_kit/export_kick_off_performer.rb +12 -0
  43. data/lib/onc_certification_g10_test_kit/igs/StructureDefinition-bodyheight.json +3772 -0
  44. data/lib/onc_certification_g10_test_kit/igs/StructureDefinition-bodytemp.json +3772 -0
  45. data/lib/onc_certification_g10_test_kit/igs/StructureDefinition-bodyweight.json +3772 -0
  46. data/lib/onc_certification_g10_test_kit/igs/StructureDefinition-bp.json +6034 -0
  47. data/lib/onc_certification_g10_test_kit/igs/StructureDefinition-heartrate.json +3756 -0
  48. data/lib/onc_certification_g10_test_kit/igs/StructureDefinition-resprate.json +3756 -0
  49. data/lib/onc_certification_g10_test_kit/limited_scope_grant_test.rb +66 -0
  50. data/lib/onc_certification_g10_test_kit/multi_patient_api.rb +43 -0
  51. data/lib/onc_certification_g10_test_kit/patient_context_test.rb +30 -0
  52. data/lib/onc_certification_g10_test_kit/profile_guesser.rb +69 -0
  53. data/lib/onc_certification_g10_test_kit/resource_access_test.rb +96 -0
  54. data/lib/onc_certification_g10_test_kit/restricted_access_test.rb +12 -0
  55. data/lib/onc_certification_g10_test_kit/restricted_resource_type_access_group.rb +303 -0
  56. data/lib/onc_certification_g10_test_kit/smart_app_launch_invalid_aud_group.rb +136 -0
  57. data/lib/onc_certification_g10_test_kit/smart_ehr_practitioner_app_group.rb +209 -0
  58. data/lib/onc_certification_g10_test_kit/smart_invalid_token_group.rb +197 -0
  59. data/lib/onc_certification_g10_test_kit/smart_limited_app_group.rb +123 -0
  60. data/lib/onc_certification_g10_test_kit/smart_public_standalone_launch_group.rb +113 -0
  61. data/lib/onc_certification_g10_test_kit/smart_scopes_test.rb +153 -0
  62. data/lib/onc_certification_g10_test_kit/smart_standalone_patient_app_group.rb +177 -0
  63. data/lib/onc_certification_g10_test_kit/terminology_binding_validator.rb +140 -0
  64. data/lib/onc_certification_g10_test_kit/token_revocation_group.rb +133 -0
  65. data/lib/onc_certification_g10_test_kit/unauthorized_access_test.rb +25 -0
  66. data/lib/onc_certification_g10_test_kit/unrestricted_resource_type_access_group.rb +375 -0
  67. data/lib/onc_certification_g10_test_kit/version.rb +3 -0
  68. data/lib/onc_certification_g10_test_kit/visual_inspection_and_attestations_group.rb +470 -0
  69. data/lib/onc_certification_g10_test_kit/well_known_capabilities_test.rb +37 -0
  70. data/lib/onc_certification_g10_test_kit.rb +223 -0
  71. metadata +310 -0
@@ -0,0 +1,470 @@
1
+ module ONCCertificationG10TestKit
2
+ class VisualInspectionAndAttestationsGroup < Inferno::TestGroup
3
+ title 'Visual Inspection and Attestation'
4
+ short_title 'Visual Inspection'
5
+ description 'Verify conformance to portions of the test procedure that are not automated.'
6
+ id :g10_visual_inspection_and_attestations
7
+ run_as_group
8
+
9
+ test do
10
+ title 'Health IT Module demonstrated support for application registration for single patients.'
11
+ description %(
12
+ Health IT Module demonstrated support for application registration for
13
+ single patients.
14
+ )
15
+ input :single_patient_registration_supported,
16
+ title: 'Health IT Module demonstrated support for application registration for single patients.',
17
+ type: 'radio',
18
+ default: 'false',
19
+ options: {
20
+ list_options: [
21
+ {
22
+ label: 'Yes',
23
+ value: 'true'
24
+ },
25
+ {
26
+ label: 'No',
27
+ value: 'false'
28
+ }
29
+ ]
30
+ }
31
+ input :single_patient_registration_notes,
32
+ title: 'Notes, if applicable:',
33
+ type: 'textarea',
34
+ optional: true
35
+
36
+ run do
37
+ assert single_patient_registration_supported == 'true',
38
+ 'Health IT Module did not demonstrate support for application registration for single patients.'
39
+ pass single_patient_registration_notes if single_patient_registration_notes.present?
40
+ end
41
+ end
42
+
43
+ test do
44
+ title 'Health IT Module demonstrated support for application registration for multiple patients.'
45
+ description %(
46
+ Health IT Module demonstrated support for supports application
47
+ registration for multiple patients.
48
+ )
49
+ input :multiple_patient_registration_supported,
50
+ title: 'Health IT Module demonstrated support for application registration for multiple patients.',
51
+ type: 'radio',
52
+ default: 'false',
53
+ options: {
54
+ list_options: [
55
+ {
56
+ label: 'Yes',
57
+ value: 'true'
58
+ },
59
+ {
60
+ label: 'No',
61
+ value: 'false'
62
+ }
63
+ ]
64
+ }
65
+ input :multiple_patient_registration_notes,
66
+ title: 'Notes, if applicable:',
67
+ type: 'textarea',
68
+ optional: true
69
+
70
+ run do
71
+ assert multiple_patient_registration_supported == 'true',
72
+ 'Health IT Module did not demonstrate support for application registration for multiple patients.'
73
+ pass multiple_patient_registration_notes if multiple_patient_registration_notes.present?
74
+ end
75
+ end
76
+
77
+ test do
78
+ title 'Health IT Module demonstrated a graphical user interface for user to authorize FHIR resources.'
79
+ description %(
80
+ Health IT Module demonstrated a graphical user interface for user to
81
+ authorize FHIR resources
82
+ )
83
+ input :resource_authorization_gui_supported,
84
+ title: 'Health IT Module demonstrated a graphical user interface for user to authorize FHIR resources.',
85
+ type: 'radio',
86
+ default: 'false',
87
+ options: {
88
+ list_options: [
89
+ {
90
+ label: 'Yes',
91
+ value: 'true'
92
+ },
93
+ {
94
+ label: 'No',
95
+ value: 'false'
96
+ }
97
+ ]
98
+ }
99
+ input :resource_authorization_gui_notes,
100
+ title: 'Notes, if applicable:',
101
+ type: 'textarea',
102
+ optional: true
103
+
104
+ run do
105
+ assert resource_authorization_gui_supported == 'true',
106
+ 'Health IT Module did not demonstrate a graphical user interface for user to authorize FHIR resources'
107
+ pass resource_authorization_gui_notes if resource_authorization_gui_notes.present?
108
+ end
109
+ end
110
+
111
+ test do
112
+ title 'Health IT Module informed patient when "offline_access" scope is being granted during authorization.'
113
+ description %(
114
+ Health IT Module informed patient when "offline_access" scope is being
115
+ granted during authorization.
116
+ )
117
+ input :offline_access_notification_supported,
118
+ title: 'Health IT Module informed patient when "offline_access" scope is being granted during authorization.', # rubocop:disable Layout/LineLength
119
+ type: 'radio',
120
+ default: 'false',
121
+ options: {
122
+ list_options: [
123
+ {
124
+ label: 'Yes',
125
+ value: 'true'
126
+ },
127
+ {
128
+ label: 'No',
129
+ value: 'false'
130
+ }
131
+ ]
132
+ }
133
+ input :offline_access_notification_notes,
134
+ title: 'Notes, if applicable:',
135
+ type: 'textarea',
136
+ optional: true
137
+
138
+ run do
139
+ assert offline_access_notification_supported == 'true',
140
+ 'Health IT Module did not inform patient when offline access scope ' \
141
+ 'is being granted during authorization.'
142
+ pass offline_access_notification_notes if offline_access_notification_notes.present?
143
+ end
144
+ end
145
+
146
+ test do
147
+ title 'Health IT Module attested that refresh tokens are valid for a period of no shorter than three months.'
148
+ description %(
149
+ Health IT Module attested that refresh tokens are valid for a period of
150
+ no shorter than three months.
151
+ )
152
+ input :refresh_token_period_attestation,
153
+ title: 'Health IT Module attested that refresh tokens are valid for a period of no shorter than three months.', # rubocop:disable Layout/LineLength
154
+ type: 'radio',
155
+ default: 'false',
156
+ options: {
157
+ list_options: [
158
+ {
159
+ label: 'Yes',
160
+ value: 'true'
161
+ },
162
+ {
163
+ label: 'No',
164
+ value: 'false'
165
+ }
166
+ ]
167
+ }
168
+ input :refresh_token_period_notes,
169
+ title: 'Notes, if applicable:',
170
+ type: 'textarea',
171
+ optional: true
172
+
173
+ run do
174
+ assert refresh_token_period_attestation == 'true',
175
+ 'Health IT Module did not attest that refresh tokens are valid ' \
176
+ 'for a period of no shorter than three months.'
177
+ pass refresh_token_period_notes if refresh_token_period_notes.present?
178
+ end
179
+ end
180
+
181
+ test do
182
+ title 'Health IT developer demonstrated the ability of the Health IT Module / ' \
183
+ 'authorization server to validate token it has issued.'
184
+ description %(
185
+ Health IT developer demonstrated the ability of the Health IT Module /
186
+ authorization server to validate token it has issued
187
+ )
188
+ input :token_validation_support,
189
+ title: 'Health IT developer demonstrated the ability of the Health IT Module / authorization server to validate token it has issued.', # rubocop:disable Layout/LineLength
190
+ type: 'radio',
191
+ default: 'false',
192
+ options: {
193
+ list_options: [
194
+ {
195
+ label: 'Yes',
196
+ value: 'true'
197
+ },
198
+ {
199
+ label: 'No',
200
+ value: 'false'
201
+ }
202
+ ]
203
+ }
204
+ input :token_validation_notes,
205
+ title: 'Notes, if applicable:',
206
+ type: 'textarea',
207
+ optional: true
208
+
209
+ run do
210
+ assert token_validation_support == 'true',
211
+ 'Health IT Module did not demonstrate the ability of the Health IT Module / ' \
212
+ 'authorization server to validate token it has issued'
213
+ pass token_validation_notes if token_validation_notes.present?
214
+ end
215
+ end
216
+
217
+ test do
218
+ title 'Tester verifies that all information is accurate and without omission.'
219
+ description %(
220
+ Tester verifies that all information is accurate and without omission.
221
+ )
222
+ input :information_accuracy_attestation,
223
+ title: 'Tester verifies that all information is accurate and without omission.',
224
+ type: 'radio',
225
+ default: 'false',
226
+ options: {
227
+ list_options: [
228
+ {
229
+ label: 'Yes',
230
+ value: 'true'
231
+ },
232
+ {
233
+ label: 'No',
234
+ value: 'false'
235
+ }
236
+ ]
237
+ }
238
+ input :information_accuracy_notes,
239
+ title: 'Notes, if applicable:',
240
+ type: 'textarea',
241
+ optional: true
242
+
243
+ run do
244
+ assert information_accuracy_attestation == 'true',
245
+ 'Tester did not verify that all information is accurate and without omission.'
246
+ pass information_accuracy_notes if information_accuracy_notes.present?
247
+ end
248
+ end
249
+
250
+ test do
251
+ title 'Information returned no greater than scopes pre-authorized for multi-patient queries.'
252
+ description %(
253
+ Information returned no greater than scopes pre-authorized for
254
+ multi-patient queries.
255
+ )
256
+ input :multi_patient_scopes_attestation,
257
+ title: 'Information returned no greater than scopes pre-authorized for multi-patient queries.',
258
+ type: 'radio',
259
+ default: 'false',
260
+ options: {
261
+ list_options: [
262
+ {
263
+ label: 'Yes',
264
+ value: 'true'
265
+ },
266
+ {
267
+ label: 'No',
268
+ value: 'false'
269
+ }
270
+ ]
271
+ }
272
+ input :multi_patient_scopes_notes,
273
+ title: 'Notes, if applicable:',
274
+ type: 'textarea',
275
+ optional: true
276
+
277
+ run do
278
+ assert multi_patient_scopes_attestation == 'true',
279
+ 'Tester did not verify that all information is accurate and without omission.'
280
+ pass multi_patient_scopes_notes if multi_patient_scopes_notes.present?
281
+ end
282
+ end
283
+
284
+ test do
285
+ title 'Health IT developer demonstrated the documentation is available at a publicly accessible URL.'
286
+ description %(
287
+ Health IT developer demonstrated the documentation is available at a
288
+ publicly accessible URL.
289
+ )
290
+ input :developer_documentation_attestation,
291
+ title: 'Health IT developer demonstrated the documentation is available at a publicly accessible URL.',
292
+ type: 'radio',
293
+ default: 'false',
294
+ options: {
295
+ list_options: [
296
+ {
297
+ label: 'Yes',
298
+ value: 'true'
299
+ },
300
+ {
301
+ label: 'No',
302
+ value: 'false'
303
+ }
304
+ ]
305
+ }
306
+ input :developer_documentation_notes,
307
+ title: 'Notes, if applicable:',
308
+ type: 'textarea',
309
+ optional: true
310
+
311
+ run do
312
+ assert developer_documentation_attestation == 'true',
313
+ 'Health IT developer did not demonstrate the documentation is available at a publicly accessible URL.'
314
+ pass developer_documentation_notes if developer_documentation_notes.present?
315
+ end
316
+ end
317
+
318
+ test do
319
+ title 'Health IT developer confirms the Health IT module does not cache the JWK Set received ' \
320
+ 'via a TLS-protected URL for longer than the cache-control header received by an application indicates.'
321
+ description %(
322
+ The Health IT developer confirms the Health IT module does not cache the
323
+ JWK Set received via a TLS-protected URL for longer than the
324
+ cache-control header indicates.
325
+ )
326
+ input :jwks_cache_attestation,
327
+ title: 'Health IT developer confirms the Health IT module does not cache the JWK Set received via a TLS-protected URL for longer than the cache-control header indicates.', # rubocop:disable Layout/LineLength
328
+ type: 'radio',
329
+ default: 'false',
330
+ options: {
331
+ list_options: [
332
+ {
333
+ label: 'Yes',
334
+ value: 'true'
335
+ },
336
+ {
337
+ label: 'No',
338
+ value: 'false'
339
+ }
340
+ ]
341
+ }
342
+ input :jwks_cache_notes,
343
+ title: 'Notes, if applicable:',
344
+ type: 'textarea',
345
+ optional: true
346
+
347
+ run do
348
+ assert jwks_cache_attestation == 'true',
349
+ 'Health IT developer did not confirm that the JWK Sets are not cached for longer than appropriate.'
350
+ pass jwks_cache_notes if jwks_cache_notes.present?
351
+ end
352
+ end
353
+
354
+ test do
355
+ title 'Health IT developer demonstrates support for the Patient Demographics Suffix USCDI v1 element.'
356
+ description %(
357
+ ONC certification criteria states that all USCDI v1 data classes and
358
+ elements need to be supported, including Patient Demographics -
359
+ Suffix.However, US Core v3.1.1 does not tag the relevant element
360
+ (Patient.name.suffix) as MUST SUPPORT. The Health IT developer must
361
+ demonstrate support for this USCDI v1 element as described in the US
362
+ Core Patient Profile implementation guidance.
363
+ )
364
+ input :patient_suffix_attestation,
365
+ title: 'Health IT developer demonstrates support for the Patient Demographics Suffix USCDI v1 element.',
366
+ type: 'radio',
367
+ default: 'false',
368
+ options: {
369
+ list_options: [
370
+ {
371
+ label: 'Yes',
372
+ value: 'true'
373
+ },
374
+ {
375
+ label: 'No',
376
+ value: 'false'
377
+ }
378
+ ]
379
+ }
380
+ input :patient_suffix_notes,
381
+ title: 'Notes, if applicable:',
382
+ type: 'textarea',
383
+ optional: true
384
+
385
+ run do
386
+ assert patient_suffix_attestation == 'true',
387
+ 'Health IT developer did not demonstrate that Patient Demographics Suffix is supported.'
388
+ pass patient_suffix_notes if patient_suffix_notes.present?
389
+ end
390
+ end
391
+
392
+ test do
393
+ title 'Health IT developer demonstrates support for the Patient Demographics Previous Name USCDI v1 element.'
394
+ description %(
395
+ ONC certification criteria states that all USCDI v1 data classes and
396
+ elements need to be supported, including Patient Demographics - Previous
397
+ Name. However, US Core v3.1.1 does not tag the relevant element
398
+ (Patient.name.period) as MUST SUPPORT. The Health IT developer must
399
+ demonstrate support for this USCDI v1 element as described in the US
400
+ Core Patient Profile implementation guidance.
401
+ )
402
+ input :patient_previous_name_attestation,
403
+ title: 'Health IT developer demonstrates support for the Patient Demographics Previous Name USCDI v1 element.', # rubocop:disable Layout/LineLength
404
+ type: 'radio',
405
+ default: 'false',
406
+ options: {
407
+ list_options: [
408
+ {
409
+ label: 'Yes',
410
+ value: 'true'
411
+ },
412
+ {
413
+ label: 'No',
414
+ value: 'false'
415
+ }
416
+ ]
417
+ }
418
+ input :patient_previous_name_notes,
419
+ title: 'Notes, if applicable:',
420
+ type: 'textarea',
421
+ optional: true
422
+
423
+ run do
424
+ assert patient_previous_name_attestation == 'true',
425
+ 'Health IT developer did not demonstrate that Patient Demographics Previous Name is supported.'
426
+ pass patient_previous_name_notes if patient_previous_name_notes.present?
427
+ end
428
+ end
429
+
430
+ test do
431
+ title 'Health IT developer demonstrates support for issuing refresh tokens to native applications.'
432
+ description %(
433
+ The health IT developer demonstrates the ability of the Health IT Module
434
+ to grant a refresh token valid for a period of no less than three months
435
+ to native applications capable of storing a refresh token.
436
+
437
+ This cannot be tested in an automated way because the health IT
438
+ developer may require use of additional security mechanisms within the
439
+ OAuth 2.0 authorization flow to ensure authorization is sufficiently
440
+ secure for native applications.
441
+ )
442
+ input :native_refresh_attestation,
443
+ title: 'Health IT developer demonstrates support for issuing refresh tokens to native applications.',
444
+ type: 'radio',
445
+ default: 'false',
446
+ options: {
447
+ list_options: [
448
+ {
449
+ label: 'Yes',
450
+ value: 'true'
451
+ },
452
+ {
453
+ label: 'No',
454
+ value: 'false'
455
+ }
456
+ ]
457
+ }
458
+ input :native_refresh_notes,
459
+ title: 'Notes, if applicable:',
460
+ type: 'textarea',
461
+ optional: true
462
+
463
+ run do
464
+ assert native_refresh_attestation == 'true',
465
+ 'Health IT developer did not demonstrate support for issuing refresh tokens to native applications.'
466
+ pass native_refresh_notes if native_refresh_notes.present?
467
+ end
468
+ end
469
+ end
470
+ end
@@ -0,0 +1,37 @@
1
+ module ONCCertificationG10TestKit
2
+ class SMARTWellKnownCapabilitiesTest < Inferno::Test
3
+ title 'Well-known configuration declares support for required capabilities'
4
+ description %(
5
+ A SMART on FHIR server SHALL convey its capabilities to app developers
6
+ by listing the SMART core capabilities supported by their
7
+ implementation within the Well-known configuration file. This test
8
+ ensures that the capabilities required by this scenario are properly
9
+ documented in the Well-known file.
10
+ )
11
+ id :g10_smart_well_known_capabilities
12
+ input :well_known_configuration
13
+
14
+ run do
15
+ skip_if well_known_configuration.blank?, 'No well-known SMART configuration found.'
16
+
17
+ assert_valid_json(well_known_configuration)
18
+ capabilities = JSON.parse(well_known_configuration)['capabilities']
19
+ assert capabilities.is_a?(Array),
20
+ "Expected the well-known capabilities to be an Array, but found #{capabilities.class.name}"
21
+
22
+ required_smart_capabilities = [
23
+ 'launch-standalone',
24
+ 'client-public',
25
+ 'client-confidential-symmetric',
26
+ 'sso-openid-connect',
27
+ 'context-standalone-patient',
28
+ 'permission-offline',
29
+ 'permission-patient'
30
+ ]
31
+
32
+ missing_capabilities = required_smart_capabilities - capabilities
33
+ assert missing_capabilities.empty?,
34
+ "The following capabilities required for this scenario are missing: #{missing_capabilities.join(', ')}"
35
+ end
36
+ end
37
+ end