onc_certification_g10_test_kit 2.0.0.rc1

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 (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