From 01feef5187b9e23874a8f324bd5e2eb26135e91d Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Mon, 6 Oct 2025 14:22:14 -0500 Subject: [PATCH 01/26] WIP - support list of categories --- .../schema/adverse_action/__init__.py | 12 ++++++-- .../data_model/schema/adverse_action/api.py | 30 +++++++++++++++++-- .../schema/adverse_action/record.py | 7 +++-- .../stacks/api_stack/v1_api/api_model.py | 18 ++++++++--- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/__init__.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/__init__.py index f613a3d4c..dc3540db6 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/__init__.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/__init__.py @@ -80,8 +80,8 @@ def encumbranceType(self, encumbrance_type_enum: EncumbranceType) -> None: self._data['encumbranceType'] = encumbrance_type_enum.value @property - def clinicalPrivilegeActionCategory(self) -> str: - return self._data['clinicalPrivilegeActionCategory'] + def clinicalPrivilegeActionCategory(self) -> str | None: + return self._data.get('clinicalPrivilegeActionCategory') @clinicalPrivilegeActionCategory.setter def clinicalPrivilegeActionCategory( @@ -89,6 +89,14 @@ def clinicalPrivilegeActionCategory( ) -> None: self._data['clinicalPrivilegeActionCategory'] = clinical_privilege_action_category_enum.value + @property + def clinicalPrivilegeActionCategories(self) -> list[str] | None: + return self._data.get('clinicalPrivilegeActionCategories') + + @clinicalPrivilegeActionCategories.setter + def clinicalPrivilegeActionCategories(self, value: list[str]) -> None: + self._data['clinicalPrivilegeActionCategories'] = value + @property def effectiveStartDate(self) -> date: return self._data['effectiveStartDate'] diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py index b4346558e..66b415279 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py @@ -1,5 +1,6 @@ # ruff: noqa: N801, N815 invalid-name -from marshmallow.fields import Date, Raw, String +from marshmallow import ValidationError, validates_schema +from marshmallow.fields import Date, List, Raw, String from marshmallow.validate import OneOf from cc_common.data_model.schema.base_record import ForgivingSchema @@ -24,7 +25,27 @@ class AdverseActionPostRequestSchema(ForgivingSchema): encumbranceEffectiveDate = Date(required=True, allow_none=False) encumbranceType = EncumbranceTypeField(required=True, allow_none=False) - clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=True, allow_none=False) + clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) + clinicalPrivilegeActionCategories = List( + ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False + ) + + @validates_schema + def validate_clinical_privilege_action_category_fields(self, data, **kwargs): + """Ensure exactly one of the category fields is provided.""" + has_singular = 'clinicalPrivilegeActionCategory' in data + has_plural = 'clinicalPrivilegeActionCategories' in data + + if has_singular and has_plural: + raise ValidationError( + 'Cannot provide both clinicalPrivilegeActionCategory and clinicalPrivilegeActionCategories. ' + 'Use clinicalPrivilegeActionCategories (the singular field is deprecated).' + ) + + if not has_singular and not has_plural: + raise ValidationError( + 'Must provide either clinicalPrivilegeActionCategory or clinicalPrivilegeActionCategories.' + ) class AdverseActionPatchRequestSchema(ForgivingSchema): @@ -76,6 +97,9 @@ class AdverseActionGeneralResponseSchema(AdverseActionPublicResponseSchema): """ encumbranceType = EncumbranceTypeField(required=True, allow_none=False) - clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=True, allow_none=False) + clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) + clinicalPrivilegeActionCategories = List( + ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False + ) liftingUser = Raw(required=False, allow_none=False) submittingUser = Raw(required=True, allow_none=False) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py index 72294f977..79e75b9d7 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py @@ -1,6 +1,6 @@ # ruff: noqa: N801, N815 invalid-name from marshmallow import ValidationError, pre_dump, validates_schema -from marshmallow.fields import UUID, Date, DateTime, String +from marshmallow.fields import UUID, Date, DateTime, List, String from marshmallow.validate import OneOf from cc_common.config import config @@ -34,7 +34,10 @@ class AdverseActionRecordSchema(BaseRecordSchema): # Populated on creation encumbranceType = EncumbranceTypeField(required=True, allow_none=False) - clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=True, allow_none=False) + clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) + clinicalPrivilegeActionCategories = List( + ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False + ) effectiveStartDate = Date(required=True, allow_none=False) submittingUser = UUID(required=True, allow_none=False) creationDate = DateTime(required=True, allow_none=False) diff --git a/backend/compact-connect/stacks/api_stack/v1_api/api_model.py b/backend/compact-connect/stacks/api_stack/v1_api/api_model.py index 792b7b00d..44922a13f 100644 --- a/backend/compact-connect/stacks/api_stack/v1_api/api_model.py +++ b/backend/compact-connect/stacks/api_stack/v1_api/api_model.py @@ -414,7 +414,7 @@ def post_privilege_encumbrance_request_model(self) -> Model: schema=JsonSchema( type=JsonSchemaType.OBJECT, additional_properties=False, - required=['encumbranceEffectiveDate', 'encumbranceType', 'clinicalPrivilegeActionCategory'], + required=['encumbranceEffectiveDate', 'encumbranceType'], properties={ 'encumbranceEffectiveDate': JsonSchema( type=JsonSchemaType.STRING, @@ -425,7 +425,12 @@ def post_privilege_encumbrance_request_model(self) -> Model: 'encumbranceType': self._encumbrance_type_schema, 'clinicalPrivilegeActionCategory': JsonSchema( type=JsonSchemaType.STRING, - description='The category of clinical privilege action', + description='(Deprecated) The category of clinical privilege action. Use clinicalPrivilegeActionCategories instead.', + ), + 'clinicalPrivilegeActionCategories': JsonSchema( + type=JsonSchemaType.ARRAY, + description='The categories of clinical privilege action', + items=JsonSchema(type=JsonSchemaType.STRING), ), }, ), @@ -444,7 +449,7 @@ def post_license_encumbrance_request_model(self) -> Model: schema=JsonSchema( type=JsonSchemaType.OBJECT, additional_properties=False, - required=['encumbranceEffectiveDate', 'encumbranceType', 'clinicalPrivilegeActionCategory'], + required=['encumbranceEffectiveDate', 'encumbranceType'], properties={ 'encumbranceEffectiveDate': JsonSchema( type=JsonSchemaType.STRING, @@ -455,7 +460,12 @@ def post_license_encumbrance_request_model(self) -> Model: 'encumbranceType': self._encumbrance_type_schema, 'clinicalPrivilegeActionCategory': JsonSchema( type=JsonSchemaType.STRING, - description='The category of clinical privilege action', + description='(Deprecated) The category of clinical privilege action. Use clinicalPrivilegeActionCategories instead.', + ), + 'clinicalPrivilegeActionCategories': JsonSchema( + type=JsonSchemaType.ARRAY, + description='The categories of clinical privilege action', + items=JsonSchema(type=JsonSchemaType.STRING), ), }, ), From 5569542fa192a4425110cf3e7d8ce70bc79e879d Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Mon, 6 Oct 2025 22:01:07 -0500 Subject: [PATCH 02/26] migrate data from deprecated field to list field --- .../schema/adverse_action/record.py | 18 ++++- .../test_handlers/test_encumbrance.py | 72 +++++++++++++++++++ 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py index 79e75b9d7..aa164f5fd 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py @@ -35,9 +35,7 @@ class AdverseActionRecordSchema(BaseRecordSchema): # Populated on creation encumbranceType = EncumbranceTypeField(required=True, allow_none=False) clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) - clinicalPrivilegeActionCategories = List( - ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False - ) + clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) effectiveStartDate = Date(required=True, allow_none=False) submittingUser = UUID(required=True, allow_none=False) creationDate = DateTime(required=True, allow_none=False) @@ -48,6 +46,11 @@ class AdverseActionRecordSchema(BaseRecordSchema): liftingUser = UUID(required=False, allow_none=False) @pre_dump + def pre_dump_serialization(self, in_data, **_kwargs): + """Pre-dump serialization to ensure the clinicalPrivilegeActionCategories list is serialized correctly.""" + in_data = self.generate_pk_sk(in_data) + return self.migrate_clinical_privilege_action_category(in_data) + def generate_pk_sk(self, in_data, **_kwargs): in_data['pk'] = f'{in_data["compact"]}#PROVIDER#{in_data["providerId"]}' # ensure this is passed in lowercase @@ -57,6 +60,15 @@ def generate_pk_sk(self, in_data, **_kwargs): ) return in_data + def migrate_clinical_privilege_action_category(self, in_data, **_kwargs): + """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list.""" + # If the deprecated field exists and the new field doesn't, migrate it + if 'clinicalPrivilegeActionCategory' in in_data and 'clinicalPrivilegeActionCategories' not in in_data: + in_data['clinicalPrivilegeActionCategories'] = [in_data['clinicalPrivilegeActionCategory']] + # Remove the deprecated field to avoid storing both + del in_data['clinicalPrivilegeActionCategory'] + return in_data + @validates_schema def validate_license_type(self, data, **_kwargs): # noqa: ARG001 unused-argument compact = data['compact'] diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py index b48549319..b8e9b75a4 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py @@ -305,6 +305,42 @@ def test_privilege_encumbrance_handler_handles_event_publishing_failure(self, mo encumbrance_handler(event, self.mock_context) self.assertEqual('Event publishing failed', str(context.exception)) + def test_privilege_encumbrance_handler_migrates_clinical_privilege_action_category_to_list(self): + """Test that the deprecated clinicalPrivilegeActionCategory field is migrated + to clinicalPrivilegeActionCategories list.""" + from cc_common.data_model.schema.adverse_action import AdverseActionData + from handlers.encumbrance import encumbrance_handler + + event, test_privilege_record = self._when_testing_privilege_encumbrance() + + response = encumbrance_handler(event, self.mock_context) + self.assertEqual(200, response['statusCode'], msg=json.loads(response['body'])) + + # Verify that the adverse action record was created with the migrated field + adverse_action_encumbrances = self._provider_table.query( + Select='ALL_ATTRIBUTES', + KeyConditionExpression=Key('pk').eq(test_privilege_record.serialize_to_database_record()['pk']) + & Key('sk').begins_with( + f'{test_privilege_record.compact}#PROVIDER#privilege/{test_privilege_record.jurisdiction}/slp#ADVERSE_ACTION' + ), + ) + self.assertEqual(1, len(adverse_action_encumbrances['Items'])) + item = adverse_action_encumbrances['Items'][0] + + # Load the adverse action record from the database + loaded_adverse_action = AdverseActionData.from_database_record(item) + + # Verify that the deprecated field is not present in the stored data + self.assertNotIn('clinicalPrivilegeActionCategory', item) + self.assertIsNone(loaded_adverse_action.clinicalPrivilegeActionCategory) + + # Verify that the new list field contains the migrated value + self.assertIn('clinicalPrivilegeActionCategories', item) + self.assertIsNotNone(loaded_adverse_action.clinicalPrivilegeActionCategories) + self.assertEqual( + ['Unsafe Practice or Substandard Care'], loaded_adverse_action.clinicalPrivilegeActionCategories + ) + @mock_aws @patch('cc_common.config._Config.current_standard_datetime', datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP)) @@ -524,6 +560,42 @@ def test_license_encumbrance_handler_returns_400_if_encumbrance_date_in_future(s response_body, ) + def test_license_encumbrance_handler_migrates_clinical_privilege_action_category_to_list(self): + """Test that the deprecated clinicalPrivilegeActionCategory field is migrated to + clinicalPrivilegeActionCategories list.""" + from cc_common.data_model.schema.adverse_action import AdverseActionData + from handlers.encumbrance import encumbrance_handler + + event, test_license_record = self._when_testing_valid_license_encumbrance() + + response = encumbrance_handler(event, self.mock_context) + self.assertEqual(200, response['statusCode'], msg=json.loads(response['body'])) + + # Verify that the adverse action record was created with the migrated field + adverse_action_encumbrances = self._provider_table.query( + Select='ALL_ATTRIBUTES', + KeyConditionExpression=Key('pk').eq(test_license_record.serialize_to_database_record()['pk']) + & Key('sk').begins_with( + f'{test_license_record.compact}#PROVIDER#license/{test_license_record.jurisdiction}/slp#ADVERSE_ACTION' + ), + ) + self.assertEqual(1, len(adverse_action_encumbrances['Items'])) + item = adverse_action_encumbrances['Items'][0] + + # Load the adverse action record from the database + loaded_adverse_action = AdverseActionData.from_database_record(item) + + # Verify that the deprecated field is not present in the stored data + self.assertNotIn('clinicalPrivilegeActionCategory', item) + self.assertIsNone(loaded_adverse_action.clinicalPrivilegeActionCategory) + + # Verify that the new list field contains the migrated value + self.assertIn('clinicalPrivilegeActionCategories', item) + self.assertIsNotNone(loaded_adverse_action.clinicalPrivilegeActionCategories) + self.assertEqual( + ['Unsafe Practice or Substandard Care'], loaded_adverse_action.clinicalPrivilegeActionCategories + ) + @mock_aws @patch('cc_common.config._Config.current_standard_datetime', datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP)) From f8e8ab0d389d3f24636349e06f354b5fbf95f821 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Mon, 6 Oct 2025 22:01:27 -0500 Subject: [PATCH 03/26] formatter/linter --- .../cc_common/data_model/schema/adverse_action/api.py | 10 +++------- .../stacks/api_stack/v1_api/api_model.py | 6 ++++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py index 66b415279..e60761456 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py @@ -26,12 +26,10 @@ class AdverseActionPostRequestSchema(ForgivingSchema): encumbranceEffectiveDate = Date(required=True, allow_none=False) encumbranceType = EncumbranceTypeField(required=True, allow_none=False) clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) - clinicalPrivilegeActionCategories = List( - ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False - ) + clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) @validates_schema - def validate_clinical_privilege_action_category_fields(self, data, **kwargs): + def validate_clinical_privilege_action_category_fields(self, data, **_kwargs): """Ensure exactly one of the category fields is provided.""" has_singular = 'clinicalPrivilegeActionCategory' in data has_plural = 'clinicalPrivilegeActionCategories' in data @@ -98,8 +96,6 @@ class AdverseActionGeneralResponseSchema(AdverseActionPublicResponseSchema): encumbranceType = EncumbranceTypeField(required=True, allow_none=False) clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) - clinicalPrivilegeActionCategories = List( - ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False - ) + clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) liftingUser = Raw(required=False, allow_none=False) submittingUser = Raw(required=True, allow_none=False) diff --git a/backend/compact-connect/stacks/api_stack/v1_api/api_model.py b/backend/compact-connect/stacks/api_stack/v1_api/api_model.py index 44922a13f..ba09566cc 100644 --- a/backend/compact-connect/stacks/api_stack/v1_api/api_model.py +++ b/backend/compact-connect/stacks/api_stack/v1_api/api_model.py @@ -425,7 +425,8 @@ def post_privilege_encumbrance_request_model(self) -> Model: 'encumbranceType': self._encumbrance_type_schema, 'clinicalPrivilegeActionCategory': JsonSchema( type=JsonSchemaType.STRING, - description='(Deprecated) The category of clinical privilege action. Use clinicalPrivilegeActionCategories instead.', + description='(Deprecated) The category of clinical privilege action. ' + 'Use clinicalPrivilegeActionCategories instead.', ), 'clinicalPrivilegeActionCategories': JsonSchema( type=JsonSchemaType.ARRAY, @@ -460,7 +461,8 @@ def post_license_encumbrance_request_model(self) -> Model: 'encumbranceType': self._encumbrance_type_schema, 'clinicalPrivilegeActionCategory': JsonSchema( type=JsonSchemaType.STRING, - description='(Deprecated) The category of clinical privilege action. Use clinicalPrivilegeActionCategories instead.', + description='(Deprecated) The category of clinical privilege action. ' + 'Use clinicalPrivilegeActionCategories instead.', ), 'clinicalPrivilegeActionCategories': JsonSchema( type=JsonSchemaType.ARRAY, From e8b238a31112498fbb91f7ad7bf5504f62615a48 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Mon, 6 Oct 2025 22:25:39 -0500 Subject: [PATCH 04/26] Add TODO markers to track needed cleanup after migration --- .../schema/adverse_action/__init__.py | 1 + .../data_model/schema/adverse_action/api.py | 2 + .../schema/adverse_action/record.py | 2 + .../test_handlers/test_encumbrance.py | 52 +++++++++++++++++++ .../stacks/api_stack/v1_api/api_model.py | 16 +++++- 5 files changed, 71 insertions(+), 2 deletions(-) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/__init__.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/__init__.py index dc3540db6..d3a4b1bae 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/__init__.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/__init__.py @@ -79,6 +79,7 @@ def encumbranceType(self) -> str: def encumbranceType(self, encumbrance_type_enum: EncumbranceType) -> None: self._data['encumbranceType'] = encumbrance_type_enum.value + # TODO - remove deprecated getter/setter after migrating to 'clinicalPrivilegeActionCategories' field # noqa: FIX002 @property def clinicalPrivilegeActionCategory(self) -> str | None: return self._data.get('clinicalPrivilegeActionCategory') diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py index e60761456..ffd4e5e91 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py @@ -25,6 +25,7 @@ class AdverseActionPostRequestSchema(ForgivingSchema): encumbranceEffectiveDate = Date(required=True, allow_none=False) encumbranceType = EncumbranceTypeField(required=True, allow_none=False) + # TODO - remove this deprecated field after migrating to 'clinicalPrivilegeActionCategories' field # noqa: FIX002 clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) @@ -95,6 +96,7 @@ class AdverseActionGeneralResponseSchema(AdverseActionPublicResponseSchema): """ encumbranceType = EncumbranceTypeField(required=True, allow_none=False) + # TODO - remove this deprecated field after migrating to 'clinicalPrivilegeActionCategories' field # noqa: FIX002 clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) liftingUser = Raw(required=False, allow_none=False) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py index aa164f5fd..1e932bb88 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py @@ -34,6 +34,7 @@ class AdverseActionRecordSchema(BaseRecordSchema): # Populated on creation encumbranceType = EncumbranceTypeField(required=True, allow_none=False) + # TODO - remove this deprecated field after migrating to 'clinicalPrivilegeActionCategories' field # noqa: FIX002 clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) effectiveStartDate = Date(required=True, allow_none=False) @@ -60,6 +61,7 @@ def generate_pk_sk(self, in_data, **_kwargs): ) return in_data + # TODO - remove this hook once migration is complete # noqa: FIX002 def migrate_clinical_privilege_action_category(self, in_data, **_kwargs): """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list.""" # If the deprecated field exists and the new field doesn't, migrate it diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py index b8e9b75a4..2e93119b7 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py @@ -305,6 +305,7 @@ def test_privilege_encumbrance_handler_handles_event_publishing_failure(self, mo encumbrance_handler(event, self.mock_context) self.assertEqual('Event publishing failed', str(context.exception)) + # TODO - remove this test once the deprecated 'clinicalPrivilegeActionCategory' field is removed # noqa: FIX002 def test_privilege_encumbrance_handler_migrates_clinical_privilege_action_category_to_list(self): """Test that the deprecated clinicalPrivilegeActionCategory field is migrated to clinicalPrivilegeActionCategories list.""" @@ -341,6 +342,31 @@ def test_privilege_encumbrance_handler_migrates_clinical_privilege_action_catego ['Unsafe Practice or Substandard Care'], loaded_adverse_action.clinicalPrivilegeActionCategories ) + # TODO - remove this test once the deprecated 'clinicalPrivilegeActionCategory' field is removed # noqa: FIX002 + def test_privilege_encumbrance_handler_returns_400_if_both_category_fields_provided(self): + """Test that a 400 error is returned when both clinicalPrivilegeActionCategory and + clinicalPrivilegeActionCategories are provided.""" + from handlers.encumbrance import encumbrance_handler + + event, test_privilege_record = self._when_testing_privilege_encumbrance( + body_overrides={ + 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', + 'clinicalPrivilegeActionCategories': [ + 'Unsafe Practice or Substandard Care', + 'Non-compliance With Requirements', + ], + } + ) + + response = encumbrance_handler(event, self.mock_context) + self.assertEqual(400, response['statusCode'], msg=json.loads(response['body'])) + response_body = json.loads(response['body']) + + self.assertIn( + 'Cannot provide both clinicalPrivilegeActionCategory and clinicalPrivilegeActionCategories', + response_body['message'], + ) + @mock_aws @patch('cc_common.config._Config.current_standard_datetime', datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP)) @@ -560,6 +586,7 @@ def test_license_encumbrance_handler_returns_400_if_encumbrance_date_in_future(s response_body, ) + # TODO - remove this test once the deprecated 'clinicalPrivilegeActionCategory' field is removed # noqa: FIX002 def test_license_encumbrance_handler_migrates_clinical_privilege_action_category_to_list(self): """Test that the deprecated clinicalPrivilegeActionCategory field is migrated to clinicalPrivilegeActionCategories list.""" @@ -596,6 +623,31 @@ def test_license_encumbrance_handler_migrates_clinical_privilege_action_category ['Unsafe Practice or Substandard Care'], loaded_adverse_action.clinicalPrivilegeActionCategories ) + # TODO - remove this test once the deprecated 'clinicalPrivilegeActionCategory' field is removed # noqa: FIX002 + def test_license_encumbrance_handler_returns_400_if_both_category_fields_provided(self): + """Test that a 400 error is returned when both clinicalPrivilegeActionCategory + and clinicalPrivilegeActionCategories are provided.""" + from handlers.encumbrance import encumbrance_handler + + event, test_license_record = self._when_testing_valid_license_encumbrance( + body_overrides={ + 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', + 'clinicalPrivilegeActionCategories': [ + 'Unsafe Practice or Substandard Care', + 'Non-compliance With Requirements', + ], + } + ) + + response = encumbrance_handler(event, self.mock_context) + self.assertEqual(400, response['statusCode'], msg=json.loads(response['body'])) + response_body = json.loads(response['body']) + + self.assertIn( + 'Cannot provide both clinicalPrivilegeActionCategory and clinicalPrivilegeActionCategories', + response_body['message'], + ) + @mock_aws @patch('cc_common.config._Config.current_standard_datetime', datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP)) diff --git a/backend/compact-connect/stacks/api_stack/v1_api/api_model.py b/backend/compact-connect/stacks/api_stack/v1_api/api_model.py index ba09566cc..1dd14a3bc 100644 --- a/backend/compact-connect/stacks/api_stack/v1_api/api_model.py +++ b/backend/compact-connect/stacks/api_stack/v1_api/api_model.py @@ -423,6 +423,7 @@ def post_privilege_encumbrance_request_model(self) -> Model: pattern=cc_api.YMD_FORMAT, ), 'encumbranceType': self._encumbrance_type_schema, + # TODO - remove this after migrating to 'clinicalPrivilegeActionCategories' field # noqa: FIX002 'clinicalPrivilegeActionCategory': JsonSchema( type=JsonSchemaType.STRING, description='(Deprecated) The category of clinical privilege action. ' @@ -459,6 +460,7 @@ def post_license_encumbrance_request_model(self) -> Model: pattern=cc_api.YMD_FORMAT, ), 'encumbranceType': self._encumbrance_type_schema, + # TODO - remove this after migrating to 'clinicalPrivilegeActionCategories' field # noqa: FIX002 'clinicalPrivilegeActionCategory': JsonSchema( type=JsonSchemaType.STRING, description='(Deprecated) The category of clinical privilege action. ' @@ -1182,7 +1184,6 @@ def _provider_detail_response_schema(self): 'adverseActionId', 'dateOfUpdate', 'encumbranceType', - 'clinicalPrivilegeActionCategory', ], properties={ 'type': JsonSchema(type=JsonSchemaType.STRING, enum=['adverseAction']), @@ -1213,7 +1214,13 @@ def _provider_detail_response_schema(self): type=JsonSchemaType.STRING, format='date', pattern=cc_api.YMD_FORMAT ), 'encumbranceType': JsonSchema(type=JsonSchemaType.STRING), + # TODO - remove this after migrating to list field # noqa: FIX002 'clinicalPrivilegeActionCategory': JsonSchema(type=JsonSchemaType.STRING), + 'clinicalPrivilegeActionCategories': JsonSchema( + type=JsonSchemaType.ARRAY, + description='The categories of clinical privilege action', + items=JsonSchema(type=JsonSchemaType.STRING), + ), 'liftingUser': JsonSchema(type=JsonSchemaType.STRING), }, ), @@ -1318,7 +1325,6 @@ def _provider_detail_response_schema(self): 'adverseActionId', 'dateOfUpdate', 'encumbranceType', - 'clinicalPrivilegeActionCategory', ], properties={ 'type': JsonSchema(type=JsonSchemaType.STRING, enum=['adverseAction']), @@ -1349,7 +1355,13 @@ def _provider_detail_response_schema(self): type=JsonSchemaType.STRING, format='date', pattern=cc_api.YMD_FORMAT ), 'encumbranceType': JsonSchema(type=JsonSchemaType.STRING), + # TODO - remove this after migrating to list field # noqa: FIX002 'clinicalPrivilegeActionCategory': JsonSchema(type=JsonSchemaType.STRING), + 'clinicalPrivilegeActionCategories': JsonSchema( + type=JsonSchemaType.ARRAY, + description='The categories of clinical privilege action', + items=JsonSchema(type=JsonSchemaType.STRING), + ), 'liftingUser': JsonSchema(type=JsonSchemaType.STRING), }, ), From 31b9a3255378319ba684bfec947a31f894ceb130 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Tue, 7 Oct 2025 15:22:08 -0500 Subject: [PATCH 05/26] Replicate data between deprecated and new field --- .../cc_common/data_model/data_client.py | 15 ++++++++---- .../data_model/schema/adverse_action/api.py | 8 +++---- .../schema/adverse_action/record.py | 23 +++++++++++++------ .../data_model/schema/privilege/record.py | 21 +++++++++++++++-- .../common/cc_common/event_bus_client.py | 3 --- .../provider-data-v1/handlers/encumbrance.py | 14 +++++++---- .../test_handlers/test_encumbrance.py | 12 ++++++---- 7 files changed, 67 insertions(+), 29 deletions(-) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py index 28a251632..fef07cd3a 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py @@ -1427,10 +1427,17 @@ def encumber_privilege(self, adverse_action: AdverseActionData) -> None: ) now = config.current_standard_datetime - encumbrance_details = { - 'clinicalPrivilegeActionCategory': adverse_action.clinicalPrivilegeActionCategory, - 'adverseActionId': adverse_action.adverseActionId, - } + # TODO - replace with a feature flag when available + if True: + encumbrance_details = { + 'clinicalPrivilegeActionCategories': adverse_action.clinicalPrivilegeActionCategories, + 'adverseActionId': adverse_action.adverseActionId, + } + else: + encumbrance_details = { + 'clinicalPrivilegeActionCategory': adverse_action.clinicalPrivilegeActionCategory, + 'adverseActionId': adverse_action.adverseActionId, + } # The time selected here is somewhat arbitrary; however, we want this selection to not alter the date # displayed for a user when it is transformed back to their timezone. We selected noon UTC-4:00 so that diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py index ffd4e5e91..1784baac0 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py @@ -25,9 +25,9 @@ class AdverseActionPostRequestSchema(ForgivingSchema): encumbranceEffectiveDate = Date(required=True, allow_none=False) encumbranceType = EncumbranceTypeField(required=True, allow_none=False) - # TODO - remove this deprecated field after migrating to 'clinicalPrivilegeActionCategories' field # noqa: FIX002 - clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) + # TODO - remove this field as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) @validates_schema def validate_clinical_privilege_action_category_fields(self, data, **_kwargs): @@ -96,8 +96,8 @@ class AdverseActionGeneralResponseSchema(AdverseActionPublicResponseSchema): """ encumbranceType = EncumbranceTypeField(required=True, allow_none=False) - # TODO - remove this deprecated field after migrating to 'clinicalPrivilegeActionCategories' field # noqa: FIX002 - clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) liftingUser = Raw(required=False, allow_none=False) submittingUser = Raw(required=True, allow_none=False) + # TODO - remove this field as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py index 1e932bb88..b8b09307d 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py @@ -1,5 +1,5 @@ # ruff: noqa: N801, N815 invalid-name -from marshmallow import ValidationError, pre_dump, validates_schema +from marshmallow import ValidationError, pre_dump, pre_load, validates_schema from marshmallow.fields import UUID, Date, DateTime, List, String from marshmallow.validate import OneOf @@ -34,18 +34,29 @@ class AdverseActionRecordSchema(BaseRecordSchema): # Populated on creation encumbranceType = EncumbranceTypeField(required=True, allow_none=False) - # TODO - remove this deprecated field after migrating to 'clinicalPrivilegeActionCategories' field # noqa: FIX002 - clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) effectiveStartDate = Date(required=True, allow_none=False) submittingUser = UUID(required=True, allow_none=False) creationDate = DateTime(required=True, allow_none=False) adverseActionId = UUID(required=True, allow_none=False) + # TODO - remove this field as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) # Populated when the action is lifted effectiveLiftDate = Date(required=False, allow_none=False) liftingUser = UUID(required=False, allow_none=False) + # TODO - remove this hook once migration is complete to the new field # noqa: FIX002 + @pre_load + def migrate_clinical_privilege_action_category_on_load(self, in_data, **_kwargs): + """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list when loading from database.""" + # If the deprecated field exists and the new field doesn't, migrate it + if 'clinicalPrivilegeActionCategory' in in_data and 'clinicalPrivilegeActionCategories' not in in_data: + in_data['clinicalPrivilegeActionCategories'] = [in_data['clinicalPrivilegeActionCategory']] + # Remove the deprecated field to avoid having both + del in_data['clinicalPrivilegeActionCategory'] + return in_data + @pre_dump def pre_dump_serialization(self, in_data, **_kwargs): """Pre-dump serialization to ensure the clinicalPrivilegeActionCategories list is serialized correctly.""" @@ -61,14 +72,12 @@ def generate_pk_sk(self, in_data, **_kwargs): ) return in_data - # TODO - remove this hook once migration is complete # noqa: FIX002 + # TODO - remove this hook as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 def migrate_clinical_privilege_action_category(self, in_data, **_kwargs): """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list.""" - # If the deprecated field exists and the new field doesn't, migrate it + # If the deprecated field exists and the new field doesn't, migrate it for backwards compatibility if 'clinicalPrivilegeActionCategory' in in_data and 'clinicalPrivilegeActionCategories' not in in_data: in_data['clinicalPrivilegeActionCategories'] = [in_data['clinicalPrivilegeActionCategory']] - # Remove the deprecated field to avoid storing both - del in_data['clinicalPrivilegeActionCategory'] return in_data @validates_schema diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py index 389d055f2..7b808c6ec 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py @@ -56,11 +56,28 @@ class EncumbranceDetailsSchema(Schema): """ Schema for tracking details about an encumbrance. """ - - clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) + clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) adverseActionId = UUID(required=True, allow_none=False) # present if update is created by upstream license encumbrance licenseJurisdiction = Jurisdiction(required=False, allow_none=False) + # TODO - remove this field as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) + + + # TODO - remove these hooks as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + @pre_load + def migrate_clinical_privilege_action_category_on_load(self, in_data, **_kwargs): + """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list when loading from database.""" + if 'clinicalPrivilegeActionCategory' in in_data and 'clinicalPrivilegeActionCategories' not in in_data: + in_data['clinicalPrivilegeActionCategories'] = [in_data['clinicalPrivilegeActionCategory']] + return in_data + + @pre_dump + def migrate_clinical_privilege_action_category_on_dump(self, in_data, **_kwargs): + """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list when dumping to database.""" + if 'clinicalPrivilegeActionCategory' in in_data and 'clinicalPrivilegeActionCategories' not in in_data: + in_data['clinicalPrivilegeActionCategories'] = [in_data['clinicalPrivilegeActionCategory']] + return in_data @BaseRecordSchema.register_schema('privilege') diff --git a/backend/compact-connect/lambdas/python/common/cc_common/event_bus_client.py b/backend/compact-connect/lambdas/python/common/cc_common/event_bus_client.py index 55754e32a..71106346f 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/event_bus_client.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/event_bus_client.py @@ -174,7 +174,6 @@ def publish_license_encumbrance_event( provider_id: UUID, jurisdiction: str, adverse_action_id: UUID, - adverse_action_category: str, license_type_abbreviation: str, effective_date: date, event_batch_writer: EventBatchWriter | None = None, @@ -187,7 +186,6 @@ def publish_license_encumbrance_event( :param provider_id: The provider ID :param jurisdiction: The jurisdiction of the license :param adverse_action_id: The adverse action ID - :param adverse_action_category: The type of adverse action perpetrated :param license_type_abbreviation: The license type abbreviation :param effective_date: The date when the encumbrance became effective :param event_batch_writer: Optional EventBatchWriter for efficient batch publishing @@ -197,7 +195,6 @@ def publish_license_encumbrance_event( 'providerId': provider_id, 'jurisdiction': jurisdiction, 'adverseActionId': adverse_action_id, - 'adverseActionCategory': adverse_action_category, 'licenseTypeAbbreviation': license_type_abbreviation, 'effectiveDate': effective_date, 'eventTime': config.current_standard_datetime, diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py index 36f6768af..0cfdf5ae8 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py @@ -102,9 +102,16 @@ def _generate_adverse_action_for_record_type( adverse_action.licenseType = license_type.name adverse_action.actionAgainst = adverse_action_against_record_type adverse_action.encumbranceType = EncumbranceType(adverse_action_request['encumbranceType']) - adverse_action.clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategory( - adverse_action_request['clinicalPrivilegeActionCategory'] - ) + if 'clinicalPrivilegeActionCategory' in adverse_action_request: + # replicate data to both the deprecated and new fields + adverse_action.clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategory( + adverse_action_request['clinicalPrivilegeActionCategory'] + ) + adverse_action.clinicalPrivilegeActionCategories = [ + ClinicalPrivilegeActionCategory(adverse_action_request['clinicalPrivilegeActionCategory']) + ] + else: + adverse_action.clinicalPrivilegeActionCategories = adverse_action_request['clinicalPrivilegeActionCategories'] adverse_action.effectiveStartDate = encumbrance_effective_date adverse_action.submittingUser = _get_submitting_user_id(event) adverse_action.creationDate = config.current_standard_datetime @@ -150,7 +157,6 @@ def handle_license_encumbrance(event: dict) -> dict: provider_id=adverse_action.providerId, adverse_action_id=adverse_action.adverseActionId, jurisdiction=adverse_action.jurisdiction, - adverse_action_category=adverse_action.clinicalPrivilegeActionCategory, license_type_abbreviation=adverse_action.licenseTypeAbbreviation, effective_date=adverse_action.effectiveStartDate, ) diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py index 2e93119b7..abce39e51 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py @@ -163,7 +163,7 @@ def test_privilege_encumbrance_handler_adds_privilege_update_record_in_provider_ 'effectiveDate': datetime.fromisoformat(TEST_ENCUMBRANCE_EFFECTIVE_DATETIME), 'createDate': datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP), 'encumbranceDetails': { - 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', + 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], 'adverseActionId': loaded_privilege_update_data.encumbranceDetails['adverseActionId'], }, } @@ -331,9 +331,10 @@ def test_privilege_encumbrance_handler_migrates_clinical_privilege_action_catego # Load the adverse action record from the database loaded_adverse_action = AdverseActionData.from_database_record(item) + # TODO - remove this assertion as part of https://github.com/csg-org/CompactConnect/issues/1136 # Verify that the deprecated field is not present in the stored data - self.assertNotIn('clinicalPrivilegeActionCategory', item) - self.assertIsNone(loaded_adverse_action.clinicalPrivilegeActionCategory) + self.assertIn('clinicalPrivilegeActionCategory', item) + self.assertEqual('Unsafe Practice or Substandard Care', loaded_adverse_action.clinicalPrivilegeActionCategory) # Verify that the new list field contains the migrated value self.assertIn('clinicalPrivilegeActionCategories', item) @@ -612,9 +613,10 @@ def test_license_encumbrance_handler_migrates_clinical_privilege_action_category # Load the adverse action record from the database loaded_adverse_action = AdverseActionData.from_database_record(item) + # TODO - remove this assertion as part of https://github.com/csg-org/CompactConnect/issues/1136 # Verify that the deprecated field is not present in the stored data - self.assertNotIn('clinicalPrivilegeActionCategory', item) - self.assertIsNone(loaded_adverse_action.clinicalPrivilegeActionCategory) + self.assertIn('clinicalPrivilegeActionCategory', item) + self.assertEqual('Unsafe Practice or Substandard Care', loaded_adverse_action.clinicalPrivilegeActionCategory) # Verify that the new list field contains the migrated value self.assertIn('clinicalPrivilegeActionCategories', item) From 6edd87a70830fe9592a83d812fe14c0a34b199a9 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Tue, 7 Oct 2025 15:23:32 -0500 Subject: [PATCH 06/26] load adverse action data to get categories rather than pass this data through the event bus, this uses the AA id to grab the data directly to load the categories --- .../cc_common/data_model/data_client.py | 38 ++++++++++++++----- .../data_model/provider_record_util.py | 22 ++++++++++- .../handlers/encumbrance_events.py | 3 -- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py index fef07cd3a..672e8b1fa 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py @@ -2611,7 +2611,6 @@ def encumber_home_jurisdiction_license_privileges( compact: str, provider_id: str, jurisdiction: str, - adverse_action_category: str, adverse_action_id: str, license_type_abbreviation: str, effective_date: date, @@ -2625,10 +2624,9 @@ def encumber_home_jurisdiction_license_privileges( :param str compact: The compact name. :param str provider_id: The provider ID. :param str jurisdiction: The jurisdiction of the license. - :param adverse_action_category: The type of adverse action perpetrated - :param adverse_action_id: The ID of the adverse action - :param str license_type_abbreviation: The license type abbreviation - :param str effective_date: effective date of the encumbrance on the license and therefore privilege + :param adverse_action_id: The ID of the adverse action. + :param str license_type_abbreviation: The license type abbreviation. + :param str effective_date: effective date of the encumbrance on the license and therefore privilege. :return: List of privileges that were encumbered """ # Get all provider records @@ -2639,6 +2637,18 @@ def encumber_home_jurisdiction_license_privileges( # Validate the license type abbreviation self._validate_license_type_abbreviation(compact, license_type_abbreviation) + # get the adverse_action record based on the id + adverse_action = provider_user_records.get_adverse_action_by_id(adverse_action_id) + + if not adverse_action: + logger.error("Adverse Action not found by id", + provider_id=provider_id, + encumbered_license_jurisdiction=jurisdiction, + encumbered_license_type=license_type_abbreviation, + adverse_action_id=adverse_action_id) + raise CCInternalException("Adverse Action not found by id") + + # Find privileges associated with the license that which was encumbered, which themselves are not currently # encumbered unencumbered_privileges_associated_with_license = provider_user_records.get_privilege_records( @@ -2661,11 +2671,19 @@ def encumber_home_jurisdiction_license_privileges( 'Found privileges to encumber', privilege_count=len(unencumbered_privileges_associated_with_license) ) - encumbrance_details = { - 'clinicalPrivilegeActionCategory': adverse_action_category, - 'licenseJurisdiction': jurisdiction, - 'adverseActionId': adverse_action_id, - } + # TODO - replace with feature flag when available + if True: + encumbrance_details = { + 'clinicalPrivilegeActionCategories': adverse_action.clinicalPrivilegeActionCategories, + 'licenseJurisdiction': jurisdiction, + 'adverseActionId': adverse_action_id, + } + else: + encumbrance_details = { + 'clinicalPrivilegeActionCategory': adverse_action.clinicalPrivilegeActionCategory, + 'licenseJurisdiction': jurisdiction, + 'adverseActionId': adverse_action_id, + } # Build transaction items for all privileges transaction_items = [] diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/provider_record_util.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/provider_record_util.py index 1e9048f68..51ab1835e 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/provider_record_util.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/provider_record_util.py @@ -373,7 +373,15 @@ def construct_simplified_privilege_history_object( and event.get('encumbranceDetails') and should_include_encumbrance_details ): - event['note'] = event['encumbranceDetails']['clinicalPrivilegeActionCategory'] + # TODO - replace this with a feature flag when available + if True: + if 'clinicalPrivilegeActionCategory' in event['encumbranceDetails']: + event['note'] = event['encumbranceDetails'].get('clinicalPrivilegeActionCategory') + else: + # else we are using the new field, parse the list into a comma-separated string + event['note'] = ', '.join(event['encumbranceDetails']['clinicalPrivilegeActionCategories']) + else: + event['note'] = event['encumbranceDetails']['clinicalPrivilegeActionCategory'] elif event['updateType'] == UpdateCategory.DEACTIVATION and event.get('deactivationDetails'): event['note'] = event['deactivationDetails']['note'] @@ -511,6 +519,18 @@ def get_adverse_action_records_for_license( and (filter_condition is None or filter_condition(record)) ] + def get_adverse_action_by_id(self, adverse_action_id: str) -> AdverseActionData | None: + """ + Get an adverse action record by its ID. + + :param str adverse_action_id: The ID of the adverse action to find + :return: The found adverse action record if found, else None + """ + return next( + (record for record in self._adverse_action_records if record.adverseActionId == adverse_action_id), + None, + ) + def _get_latest_effective_lift_date_for_adverse_actions( self, adverse_actions: list[AdverseActionData] ) -> date | None: diff --git a/backend/compact-connect/lambdas/python/data-events/handlers/encumbrance_events.py b/backend/compact-connect/lambdas/python/data-events/handlers/encumbrance_events.py index e31663658..3d2d68ffb 100644 --- a/backend/compact-connect/lambdas/python/data-events/handlers/encumbrance_events.py +++ b/backend/compact-connect/lambdas/python/data-events/handlers/encumbrance_events.py @@ -197,7 +197,6 @@ def license_encumbrance_listener(message: dict): compact = detail['compact'] provider_id = detail['providerId'] jurisdiction = detail['jurisdiction'] - adverse_action_category = detail['adverseActionCategory'] adverse_action_id = detail['adverseActionId'] license_type_abbreviation = detail['licenseTypeAbbreviation'] effective_date = detail['effectiveDate'] @@ -208,7 +207,6 @@ def license_encumbrance_listener(message: dict): jurisdiction=jurisdiction, license_type_abbreviation=license_type_abbreviation, effective_date=effective_date, - adverse_action_category=adverse_action_category, adverse_action_id=adverse_action_id, ): logger.info('Processing license encumbrance event') @@ -218,7 +216,6 @@ def license_encumbrance_listener(message: dict): compact=compact, provider_id=provider_id, jurisdiction=jurisdiction, - adverse_action_category=adverse_action_category, license_type_abbreviation=license_type_abbreviation, adverse_action_id=adverse_action_id, effective_date=effective_date, From 8da5fb4367825a93acbfa4045800c0e6f1fe8742 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 8 Oct 2025 08:47:09 -0500 Subject: [PATCH 07/26] update smoke tests to use new field --- .../tests/smoke/encumbrance_smoke_tests.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py b/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py index 4eb9ca687..0542ab7ef 100644 --- a/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py +++ b/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py @@ -461,7 +461,7 @@ def test_license_encumbrance_workflow(): encumbrance_body = { 'encumbranceEffectiveDate': '2024-11-11', - 'clinicalPrivilegeActionCategory': 'Fraud, Deception, or Misrepresentation', + 'clinicalPrivilegeActionCategories': ['Fraud, Deception, or Misrepresentation'], } # First encumbrance @@ -518,7 +518,7 @@ def test_license_encumbrance_workflow(): # Second encumbrance second_encumbrance_body = { 'encumbranceEffectiveDate': '2025-01-01', - 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', + 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], } helper.encumber_license(second_encumbrance_body) logger.info('Second license encumbrance created successfully') @@ -537,7 +537,7 @@ def test_license_encumbrance_workflow(): # Step 3: Encumber Privilege privilege_encumbrance_body = { 'encumbranceEffectiveDate': '2025-05-09', - 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', + 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], } helper.encumber_privilege(privilege_encumbrance_body) @@ -653,7 +653,7 @@ def test_privilege_encumbrance_workflow(): encumbrance_body = { 'encumbranceEffectiveDate': '2024-12-12', - 'clinicalPrivilegeActionCategory': 'Fraud, Deception, or Misrepresentation', + 'clinicalPrivilegeActionCategories': ['Fraud, Deception, or Misrepresentation'], } # First encumbrance @@ -684,7 +684,7 @@ def test_privilege_encumbrance_workflow(): # Second encumbrance second_encumbrance_body = { 'encumbranceEffectiveDate': '2025-02-02', - 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', + 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], } helper.encumber_privilege(second_encumbrance_body) logger.info('Second privilege encumbrance created successfully') @@ -768,7 +768,7 @@ def test_privilege_encumbrance_status_changes_with_license_encumbrance_workflow( logger.info('Step 1: Creating privilege encumbrance...') privilege_encumbrance_body = { 'encumbranceEffectiveDate': '2024-01-15', - 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', + 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], } helper.encumber_privilege(privilege_encumbrance_body) @@ -787,7 +787,7 @@ def test_privilege_encumbrance_status_changes_with_license_encumbrance_workflow( logger.info('Step 2: Creating license encumbrance...') license_encumbrance_body = { 'encumbranceEffectiveDate': '2024-01-20', - 'clinicalPrivilegeActionCategory': 'Criminal Conviction or Adjudication', + 'clinicalPrivilegeActionCategories': ['Criminal Conviction or Adjudication'], } helper.encumber_license(license_encumbrance_body) From 1ff2538197f5503dde4b8931b2722d463a0d1077 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 8 Oct 2025 16:37:16 -0500 Subject: [PATCH 08/26] Update api model test snapshots to match new contracts --- .../GET_PROVIDER_RESPONSE_SCHEMA.json | 20 +++++++++++++++---- .../LICENSE_ENCUMBRANCE_REQUEST_SCHEMA.json | 12 ++++++++--- .../PRIVILEGE_ENCUMBRANCE_REQUEST_SCHEMA.json | 12 ++++++++--- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_RESPONSE_SCHEMA.json b/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_RESPONSE_SCHEMA.json index a336ff68b..b3fe43b29 100644 --- a/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_RESPONSE_SCHEMA.json +++ b/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_RESPONSE_SCHEMA.json @@ -628,6 +628,13 @@ "clinicalPrivilegeActionCategory": { "type": "string" }, + "clinicalPrivilegeActionCategories": { + "description": "The categories of clinical privilege action", + "items": { + "type": "string" + }, + "type": "array" + }, "liftingUser": { "type": "string" } @@ -644,8 +651,7 @@ "creationDate", "adverseActionId", "dateOfUpdate", - "encumbranceType", - "clinicalPrivilegeActionCategory" + "encumbranceType" ], "type": "object" }, @@ -1434,6 +1440,13 @@ "clinicalPrivilegeActionCategory": { "type": "string" }, + "clinicalPrivilegeActionCategories": { + "description": "The categories of clinical privilege action", + "items": { + "type": "string" + }, + "type": "array" + }, "liftingUser": { "type": "string" } @@ -1450,8 +1463,7 @@ "creationDate", "adverseActionId", "dateOfUpdate", - "encumbranceType", - "clinicalPrivilegeActionCategory" + "encumbranceType" ], "type": "object" }, diff --git a/backend/compact-connect/tests/resources/snapshots/LICENSE_ENCUMBRANCE_REQUEST_SCHEMA.json b/backend/compact-connect/tests/resources/snapshots/LICENSE_ENCUMBRANCE_REQUEST_SCHEMA.json index c46321a5a..cf81fc545 100644 --- a/backend/compact-connect/tests/resources/snapshots/LICENSE_ENCUMBRANCE_REQUEST_SCHEMA.json +++ b/backend/compact-connect/tests/resources/snapshots/LICENSE_ENCUMBRANCE_REQUEST_SCHEMA.json @@ -29,14 +29,20 @@ "type": "string" }, "clinicalPrivilegeActionCategory": { - "description": "The category of clinical privilege action", + "description": "(Deprecated) The category of clinical privilege action. Use clinicalPrivilegeActionCategories instead.", "type": "string" + }, + "clinicalPrivilegeActionCategories": { + "description": "The categories of clinical privilege action", + "items": { + "type": "string" + }, + "type": "array" } }, "required": [ "encumbranceEffectiveDate", - "encumbranceType", - "clinicalPrivilegeActionCategory" + "encumbranceType" ], "type": "object", "$schema": "http://json-schema.org/draft-04/schema#" diff --git a/backend/compact-connect/tests/resources/snapshots/PRIVILEGE_ENCUMBRANCE_REQUEST_SCHEMA.json b/backend/compact-connect/tests/resources/snapshots/PRIVILEGE_ENCUMBRANCE_REQUEST_SCHEMA.json index c46321a5a..cf81fc545 100644 --- a/backend/compact-connect/tests/resources/snapshots/PRIVILEGE_ENCUMBRANCE_REQUEST_SCHEMA.json +++ b/backend/compact-connect/tests/resources/snapshots/PRIVILEGE_ENCUMBRANCE_REQUEST_SCHEMA.json @@ -29,14 +29,20 @@ "type": "string" }, "clinicalPrivilegeActionCategory": { - "description": "The category of clinical privilege action", + "description": "(Deprecated) The category of clinical privilege action. Use clinicalPrivilegeActionCategories instead.", "type": "string" + }, + "clinicalPrivilegeActionCategories": { + "description": "The categories of clinical privilege action", + "items": { + "type": "string" + }, + "type": "array" } }, "required": [ "encumbranceEffectiveDate", - "encumbranceType", - "clinicalPrivilegeActionCategory" + "encumbranceType" ], "type": "object", "$schema": "http://json-schema.org/draft-04/schema#" From b438b8117b149415383b7de7166bafb94fdc7ea0 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 8 Oct 2025 16:46:46 -0500 Subject: [PATCH 09/26] Update provider user api model test snapshot --- .../PROVIDER_USER_RESPONSE_SCHEMA.json | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/backend/compact-connect/tests/resources/snapshots/PROVIDER_USER_RESPONSE_SCHEMA.json b/backend/compact-connect/tests/resources/snapshots/PROVIDER_USER_RESPONSE_SCHEMA.json index a336ff68b..b3fe43b29 100644 --- a/backend/compact-connect/tests/resources/snapshots/PROVIDER_USER_RESPONSE_SCHEMA.json +++ b/backend/compact-connect/tests/resources/snapshots/PROVIDER_USER_RESPONSE_SCHEMA.json @@ -628,6 +628,13 @@ "clinicalPrivilegeActionCategory": { "type": "string" }, + "clinicalPrivilegeActionCategories": { + "description": "The categories of clinical privilege action", + "items": { + "type": "string" + }, + "type": "array" + }, "liftingUser": { "type": "string" } @@ -644,8 +651,7 @@ "creationDate", "adverseActionId", "dateOfUpdate", - "encumbranceType", - "clinicalPrivilegeActionCategory" + "encumbranceType" ], "type": "object" }, @@ -1434,6 +1440,13 @@ "clinicalPrivilegeActionCategory": { "type": "string" }, + "clinicalPrivilegeActionCategories": { + "description": "The categories of clinical privilege action", + "items": { + "type": "string" + }, + "type": "array" + }, "liftingUser": { "type": "string" } @@ -1450,8 +1463,7 @@ "creationDate", "adverseActionId", "dateOfUpdate", - "encumbranceType", - "clinicalPrivilegeActionCategory" + "encumbranceType" ], "type": "object" }, From 005eb01b6c25f81da176dfcc722b870d3e57e765 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 8 Oct 2025 16:51:10 -0500 Subject: [PATCH 10/26] Move provider management lambdas into api lambda stack --- .../stacks/api_lambda_stack/__init__.py | 6 + .../api_lambda_stack/provider_management.py | 329 ++++++++++++++ .../stacks/api_stack/v1_api/api.py | 3 +- .../api_stack/v1_api/provider_management.py | 418 +----------------- .../test_api/test_provider_management_api.py | 147 +++--- ...ER_SSN_ANOMALY_DETECTION_ALARM_SCHEMA.json | 2 +- ...ER_SSN_ENDPOINT_DISABLED_ALARM_SCHEMA.json | 2 +- ...R_SSN_READS_RATE_LIMITED_ALARM_SCHEMA.json | 2 +- 8 files changed, 432 insertions(+), 477 deletions(-) create mode 100644 backend/compact-connect/stacks/api_lambda_stack/provider_management.py diff --git a/backend/compact-connect/stacks/api_lambda_stack/__init__.py b/backend/compact-connect/stacks/api_lambda_stack/__init__.py index 29b040d59..b208f6429 100644 --- a/backend/compact-connect/stacks/api_lambda_stack/__init__.py +++ b/backend/compact-connect/stacks/api_lambda_stack/__init__.py @@ -23,6 +23,7 @@ from .credentials import CredentialsLambdas from .feature_flags import FeatureFlagsLambdas from .post_licenses import PostLicensesLambdas +from .provider_management import ProviderManagementLambdas from .provider_users import ProviderUsersLambdas from .public_lookup_api import PublicLookupApiLambdas from .purchases import PurchasesLambdas @@ -118,6 +119,11 @@ def __init__( ) # Provider Management lambdas + self.provider_management_lambdas = ProviderManagementLambdas( + scope=self, + persistent_stack=persistent_stack, + data_event_bus=data_event_bus, + ) # Public lookup lambdas self.public_lookup_lambdas = PublicLookupApiLambdas( diff --git a/backend/compact-connect/stacks/api_lambda_stack/provider_management.py b/backend/compact-connect/stacks/api_lambda_stack/provider_management.py new file mode 100644 index 000000000..af3493e56 --- /dev/null +++ b/backend/compact-connect/stacks/api_lambda_stack/provider_management.py @@ -0,0 +1,329 @@ +from __future__ import annotations + +import os + +from aws_cdk import Duration +from aws_cdk.aws_cloudwatch import Alarm, CfnAlarm, ComparisonOperator, Metric, TreatMissingData +from aws_cdk.aws_cloudwatch_actions import SnsAction +from aws_cdk.aws_events import EventBus +from aws_cdk.aws_iam import Policy, PolicyStatement +from cdk_nag import NagSuppressions +from common_constructs.stack import Stack + +from common_constructs.python_function import PythonFunction +from stacks import persistent_stack as ps + + +class ProviderManagementLambdas: + def __init__( + self, + *, + scope: Stack, + persistent_stack: ps.PersistentStack, + data_event_bus: EventBus, + ) -> None: + self.scope = scope + self.persistent_stack = persistent_stack + self.data_event_bus = data_event_bus + + self.stack: Stack = Stack.of(scope) + lambda_environment = { + 'PROVIDER_TABLE_NAME': persistent_stack.provider_table.table_name, + 'PROV_FAM_GIV_MID_INDEX_NAME': persistent_stack.provider_table.provider_fam_giv_mid_index_name, + 'PROV_DATE_OF_UPDATE_INDEX_NAME': persistent_stack.provider_table.provider_date_of_update_index_name, + 'SSN_TABLE_NAME': persistent_stack.ssn_table.table_name, + 'SSN_INDEX_NAME': persistent_stack.ssn_table.ssn_index_name, + 'EVENT_BUS_NAME': data_event_bus.event_bus_name, + 'RATE_LIMITING_TABLE_NAME': persistent_stack.rate_limiting_table.table_name, + 'USER_POOL_ID': persistent_stack.staff_users.user_pool_id, + 'EMAIL_NOTIFICATION_SERVICE_LAMBDA_NAME': persistent_stack.email_notification_service_lambda.function_name, + 'USERS_TABLE_NAME': persistent_stack.staff_users.user_table.table_name, + 'PROVIDER_USER_BUCKET_NAME': persistent_stack.provider_users_bucket.bucket_name, + **self.stack.common_env_vars, + } + + # Create all the lambda handlers + self.get_provider_handler = self._get_provider_handler(lambda_environment) + self.query_providers_handler = self._query_providers_handler(lambda_environment) + self.get_provider_ssn_handler = self._get_provider_ssn_handler(lambda_environment) + self.deactivate_privilege_handler = self._deactivate_privilege_handler(lambda_environment) + self.provider_encumbrance_handler = self._add_provider_encumbrance_handler(lambda_environment) + + def _get_provider_handler( + self, + lambda_environment: dict, + ) -> PythonFunction: + handler = PythonFunction( + self.scope, + 'GetProviderHandler', + description='Get provider handler', + lambda_dir='provider-data-v1', + index=os.path.join('handlers', 'providers.py'), + handler='get_provider', + environment=lambda_environment, + alarm_topic=self.persistent_stack.alarm_topic, + ) + self.persistent_stack.shared_encryption_key.grant_decrypt(handler) + self.persistent_stack.provider_table.grant_read_data(handler) + self.persistent_stack.provider_users_bucket.grant_read(handler) + + NagSuppressions.add_resource_suppressions_by_path( + self.stack, + path=f'{handler.node.path}/ServiceRole/DefaultPolicy/Resource', + suppressions=[ + { + 'id': 'AwsSolutions-IAM5', + 'reason': 'The actions in this policy are specifically what this lambda needs to read ' + 'and is scoped to one table and encryption key.', + }, + ], + ) + return handler + + def _query_providers_handler( + self, + lambda_environment: dict, + ) -> PythonFunction: + handler = PythonFunction( + self.scope, + 'QueryProvidersHandler', + description='Query providers handler', + lambda_dir='provider-data-v1', + index=os.path.join('handlers', 'providers.py'), + handler='query_providers', + environment=lambda_environment, + alarm_topic=self.persistent_stack.alarm_topic, + ) + self.persistent_stack.shared_encryption_key.grant_decrypt(handler) + self.persistent_stack.provider_table.grant_read_data(handler) + + NagSuppressions.add_resource_suppressions_by_path( + Stack.of(handler.role), + path=f'{handler.role.node.path}/DefaultPolicy/Resource', + suppressions=[ + { + 'id': 'AwsSolutions-IAM5', + 'appliesTo': [ + 'Action::kms:GenerateDataKey*', + 'Action::kms:ReEncrypt*', + 'Resource::/index/*', + ], + 'reason': 'The actions in this policy are specifically what this lambda needs to read ' + 'and is scoped to one table and encryption key.', + }, + ], + ) + return handler + + def _get_provider_ssn_handler( + self, + lambda_environment: dict, + ) -> PythonFunction: + """Create and configure the Lambda handler for retrieving a provider's SSN.""" + handler = PythonFunction( + self.scope, + 'GetProviderSSNHandler', + description='Get provider SSN handler', + lambda_dir='provider-data-v1', + index=os.path.join('handlers', 'providers.py'), + handler='get_provider_ssn', + role=self.persistent_stack.ssn_table.api_query_role, + environment=lambda_environment, + alarm_topic=self.persistent_stack.alarm_topic, + ) + # The lambda needs to read providers from the provider table and the SSN from the ssn table + # Though, ssn table access is granted via resource policies on the table and key so `.grant()` + # calls are not needed here. + + # Grant permissions for rate limiting, provider table access, and staff user pool access + self.persistent_stack.rate_limiting_table.grant_read_write_data(handler) + self.persistent_stack.provider_table.grant_read_data(handler) + self.persistent_stack.staff_users.grant(handler, 'cognito-idp:AdminDisableUser') + + # Add permission for the lambda to update its own concurrency setting + function_arn = handler.function_arn + handler.role.attach_inline_policy( + Policy( + self.scope, + 'PutFunctionConcurrency', + statements=[ + PolicyStatement( + actions=['lambda:PutFunctionConcurrency'], + resources=[function_arn], + ) + ], + ) + ) + + NagSuppressions.add_resource_suppressions_by_path( + Stack.of(handler.role), + path=f'{handler.role.node.path}/DefaultPolicy/Resource', + suppressions=[ + { + 'id': 'AwsSolutions-IAM5', + 'reason': 'The wildcard actions in this policy are scoped to the rate-limiting table and ' + 'the provider data table.', + }, + ], + ) + + # Create a metric to track how many times this endpoint has been invoked with a day + daily_read_ssn_count_metric = Metric( + namespace='compact-connect', + metric_name='read-ssn', + statistic='SampleCount', + period=Duration.days(1), + dimensions_map={'service': 'common'}, + ) + + # We'll monitor longer access patterns to detect anomalies, over time + # The L2 construct, Alarm, doesn't yet support Anomaly Detection as a configuration + # so we're using the L1 construct, CfnAlarm + # This anomaly detector scans the count of requests to the ssn endpoint by + # the daily_read_ssn_count_metric and uses machine-learning and pattern recognition to + # establish baselines of typical usage. + # See https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/LogsAnomalyDetection.html + self.ssn_anomaly_detection_alarm = CfnAlarm( + handler, + 'ReadSSNAnomalyAlarm', + alarm_description=f'{handler.node.path} read-ssn anomaly detection. The GET provider SSN endpoint has been' + f'called an irregular number of times. Investigation required to ensure ssn endpoint is ' + f'not being abused.', + comparison_operator='GreaterThanUpperThreshold', + evaluation_periods=1, + treat_missing_data='notBreaching', + actions_enabled=True, + alarm_actions=[self.persistent_stack.alarm_topic.node.default_child.ref], + metrics=[ + CfnAlarm.MetricDataQueryProperty(id='ad1', expression='ANOMALY_DETECTION_BAND(m1, 2)'), + CfnAlarm.MetricDataQueryProperty( + id='m1', + metric_stat=CfnAlarm.MetricStatProperty( + metric=CfnAlarm.MetricProperty( + metric_name=daily_read_ssn_count_metric.metric_name, + namespace=daily_read_ssn_count_metric.namespace, + dimensions=[CfnAlarm.DimensionProperty(name='service', value='common')], + ), + period=3600, + stat='SampleCount', + ), + ), + ], + threshold_metric_id='ad1', + ) + + # Create a metric to track if any user is rate-limited while calling this endpoint + ssn_rate_limited_count_metric = Metric( + namespace='compact-connect', + metric_name='rate-limited-ssn-access', + statistic='SampleCount', + period=Duration.minutes(5), + dimensions_map={'service': 'common'}, + ) + + # This alarm will fire if any user is rate-limited by this endpoint + # This will help us determine if the limit needs to be raised or detect early abuse + self.ssn_rate_limited_alarm = Alarm( + handler, + 'SSNReadsRateLimitedAlarm', + metric=ssn_rate_limited_count_metric, + threshold=1, + evaluation_periods=1, + comparison_operator=ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + treat_missing_data=TreatMissingData.NOT_BREACHING, + alarm_description=f'{handler.node.path} ssn reads rate-limited alarm. The GET provider SSN endpoint has ' + f'been invoked more than an expected threshold within a 24 hour period. Investigation is ' + f'required to ensure access is not the result of abuse.', + ) + self.ssn_rate_limited_alarm.add_alarm_action(SnsAction(self.persistent_stack.alarm_topic)) + + # Create a metric to track if ssn endpoint has been disabled due to excessive requests + ssn_endpoint_disabled_count_metric = Metric( + namespace='compact-connect', + metric_name='ssn-endpoint-disabled', + statistic='SampleCount', + period=Duration.minutes(5), + dimensions_map={'service': 'common'}, + ) + # This alarm will fire if the ssn endpoint hits our global threshold and is disabled (concurrency set to 0) + self.ssn_endpoint_disabled_alarm = Alarm( + handler, + 'SSNEndpointDisabledAlarm', + metric=ssn_endpoint_disabled_count_metric, + threshold=1, + evaluation_periods=1, + comparison_operator=ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + treat_missing_data=TreatMissingData.NOT_BREACHING, + alarm_description=f'{handler.node.path} SECURITY ALERT: SSN ENDPOINT DISABLED. The GET provider SSN ' + 'endpoint has been disabled due to excessive requests. Immediate investigation required. ' + 'Endpoint will need to be manually reactivated before any further requests can be ' + 'processed.', + ) + self.ssn_endpoint_disabled_alarm.add_alarm_action(SnsAction(self.persistent_stack.alarm_topic)) + + return handler + + def _deactivate_privilege_handler( + self, + lambda_environment: dict, + ) -> PythonFunction: + """Create and configure the Lambda handler for deactivating a provider's privilege.""" + handler = PythonFunction( + self.scope, + 'DeactivatePrivilegeHandler', + description='Deactivate provider privilege handler', + lambda_dir='provider-data-v1', + index=os.path.join('handlers', 'privileges.py'), + handler='deactivate_privilege', + environment=lambda_environment, + alarm_topic=self.persistent_stack.alarm_topic, + ) + self.persistent_stack.provider_table.grant_read_write_data(handler) + self.persistent_stack.staff_users.user_table.grant_read_data(handler) + self.data_event_bus.grant_put_events_to(handler) + self.persistent_stack.email_notification_service_lambda.grant_invoke(handler) + + NagSuppressions.add_resource_suppressions_by_path( + Stack.of(handler.role), + path=f'{handler.role.node.path}/DefaultPolicy/Resource', + suppressions=[ + { + 'id': 'AwsSolutions-IAM5', + 'reason': 'The actions in this policy are specifically what this lambda needs to read/write ' + 'and is scoped to one table and event bus.', + }, + ], + ) + return handler + + def _add_provider_encumbrance_handler( + self, + lambda_environment: dict, + ) -> PythonFunction: + """Create and configure the Lambda handler for encumbering a provider's privilege or license.""" + handler = PythonFunction( + self.scope, + 'ProviderEncumbranceHandler', + description='Provider encumbrance handler', + lambda_dir='provider-data-v1', + index=os.path.join('handlers', 'encumbrance.py'), + handler='encumbrance_handler', + environment=lambda_environment, + alarm_topic=self.persistent_stack.alarm_topic, + ) + self.persistent_stack.provider_table.grant_read_write_data(handler) + self.persistent_stack.staff_users.user_table.grant_read_data(handler) + self.data_event_bus.grant_put_events_to(handler) + + NagSuppressions.add_resource_suppressions_by_path( + Stack.of(handler.role), + path=f'{handler.role.node.path}/DefaultPolicy/Resource', + suppressions=[ + { + 'id': 'AwsSolutions-IAM5', + 'reason': 'The actions in this policy are specifically what this lambda needs to read/write ' + 'and is scoped to the needed tables and event bus.', + }, + ], + ) + return handler diff --git a/backend/compact-connect/stacks/api_stack/v1_api/api.py b/backend/compact-connect/stacks/api_stack/v1_api/api.py index 53c3bfacd..93e310962 100644 --- a/backend/compact-connect/stacks/api_stack/v1_api/api.py +++ b/backend/compact-connect/stacks/api_stack/v1_api/api.py @@ -163,10 +163,9 @@ def __init__( method_options=read_auth_method_options, admin_method_options=admin_auth_method_options, ssn_method_options=read_ssn_auth_method_options, - persistent_stack=persistent_stack, api_model=self.api_model, - data_event_bus=data_event_bus, privilege_history_function=privilege_history_handler, + api_lambda_stack=api_lambda_stack, ) # GET /v1/compacts/{compact}/jurisdictions self.jurisdictions_resource = self.compact_resource.add_resource('jurisdictions') diff --git a/backend/compact-connect/stacks/api_stack/v1_api/provider_management.py b/backend/compact-connect/stacks/api_stack/v1_api/provider_management.py index 4dc6cfbc7..2582d8011 100644 --- a/backend/compact-connect/stacks/api_stack/v1_api/provider_management.py +++ b/backend/compact-connect/stacks/api_stack/v1_api/provider_management.py @@ -1,29 +1,18 @@ from __future__ import annotations -import os - from aws_cdk import Duration from aws_cdk.aws_apigateway import LambdaIntegration, MethodOptions, MethodResponse, Resource from aws_cdk.aws_cloudwatch import ( Alarm, - CfnAlarm, ComparisonOperator, Metric, TreatMissingData, ) from aws_cdk.aws_cloudwatch_actions import SnsAction -from aws_cdk.aws_dynamodb import Table -from aws_cdk.aws_events import EventBus -from aws_cdk.aws_iam import Policy, PolicyStatement -from aws_cdk.aws_kms import IKey -from cdk_nag import NagSuppressions -from common_constructs.stack import Stack from common_constructs.cc_api import CCApi -from common_constructs.nodejs_function import NodejsFunction from common_constructs.python_function import PythonFunction -from stacks import persistent_stack as ps -from stacks.persistent_stack import ProviderTable, ProviderUsersBucket, RateLimitingTable, SSNTable, StaffUsers +from stacks.api_lambda_stack import ApiLambdaStack from .api_model import ApiModel @@ -40,10 +29,9 @@ def __init__( method_options: MethodOptions, admin_method_options: MethodOptions, ssn_method_options: MethodOptions, - persistent_stack: ps.PersistentStack, - data_event_bus: EventBus, api_model: ApiModel, privilege_history_function: PythonFunction, + api_lambda_stack: ApiLambdaStack, ): super().__init__() @@ -51,23 +39,6 @@ def __init__( self.api: CCApi = resource.api self.api_model = api_model - stack: Stack = Stack.of(resource) - - lambda_environment = { - 'PROVIDER_TABLE_NAME': persistent_stack.provider_table.table_name, - 'PROV_FAM_GIV_MID_INDEX_NAME': persistent_stack.provider_table.provider_fam_giv_mid_index_name, - 'PROV_DATE_OF_UPDATE_INDEX_NAME': persistent_stack.provider_table.provider_date_of_update_index_name, - 'SSN_TABLE_NAME': persistent_stack.ssn_table.table_name, - 'SSN_INDEX_NAME': persistent_stack.ssn_table.ssn_index_name, - 'EVENT_BUS_NAME': data_event_bus.event_bus_name, - 'RATE_LIMITING_TABLE_NAME': persistent_stack.rate_limiting_table.table_name, - 'USER_POOL_ID': persistent_stack.staff_users.user_pool_id, - 'EMAIL_NOTIFICATION_SERVICE_LAMBDA_NAME': persistent_stack.email_notification_service_lambda.function_name, - 'USERS_TABLE_NAME': persistent_stack.staff_users.user_table.table_name, - 'PROVIDER_USER_BUCKET_NAME': persistent_stack.provider_users_bucket.bucket_name, - **stack.common_env_vars, - } - # Create the nested resources used by endpoints self.provider_resource = self.resource.add_resource('{providerId}') self.privileges_resource = self.provider_resource.add_resource('privileges') @@ -86,42 +57,17 @@ def __init__( 'licenseType' ).add_resource('{licenseType}') - self._add_query_providers( - method_options=method_options, - data_encryption_key=persistent_stack.shared_encryption_key, - provider_data_table=persistent_stack.provider_table, - lambda_environment=lambda_environment, - ) - self._add_get_provider( - method_options=method_options, - data_encryption_key=persistent_stack.shared_encryption_key, - provider_data_table=persistent_stack.provider_table, - provider_users_bucket=persistent_stack.provider_users_bucket, - lambda_environment=lambda_environment, - ) - self._add_get_provider_ssn( - method_options=ssn_method_options, - ssn_table=persistent_stack.ssn_table, - staff_user_pool=persistent_stack.staff_users, - rate_limiting_table=persistent_stack.rate_limiting_table, - provider_table=persistent_stack.provider_table, - lambda_environment=lambda_environment, - ) - self._add_deactivate_privilege( - method_options=admin_method_options, - provider_data_table=persistent_stack.provider_table, - event_bus=data_event_bus, - email_service_lambda=persistent_stack.email_notification_service_lambda, - staff_users_table=persistent_stack.staff_users.user_table, - lambda_environment=lambda_environment, - ) + # Reference lambda handlers from api_lambda_stack + self.get_provider_handler = api_lambda_stack.provider_management_lambdas.get_provider_handler + self.query_providers_handler = api_lambda_stack.provider_management_lambdas.query_providers_handler + self.get_provider_ssn_handler = api_lambda_stack.provider_management_lambdas.get_provider_ssn_handler + self.deactivate_privilege_handler = api_lambda_stack.provider_management_lambdas.deactivate_privilege_handler + self.provider_encumbrance_handler = api_lambda_stack.provider_management_lambdas.provider_encumbrance_handler - self.provider_encumbrance_handler = self._add_provider_encumbrance_handler( - provider_data_table=persistent_stack.provider_table, - staff_users_table=persistent_stack.staff_users.user_table, - event_bus=data_event_bus, - lambda_environment=lambda_environment, - ) + self._add_query_providers(method_options=method_options) + self._add_get_provider(method_options=method_options) + self._add_get_provider_ssn(method_options=ssn_method_options) + self._add_deactivate_privilege(method_options=admin_method_options) self._add_encumber_privilege(method_options=admin_method_options) @@ -135,17 +81,8 @@ def __init__( def _add_get_provider( self, method_options: MethodOptions, - data_encryption_key: IKey, - provider_data_table: ProviderTable, - provider_users_bucket: ProviderUsersBucket, - lambda_environment: dict, ): - self.get_provider_handler = self._get_provider_handler( - data_encryption_key=data_encryption_key, - provider_data_table=provider_data_table, - lambda_environment=lambda_environment, - ) - provider_users_bucket.grant_read(self.get_provider_handler) + self.api.log_groups.append(self.get_provider_handler.log_group) self.provider_resource.add_method( 'GET', @@ -166,17 +103,10 @@ def _add_get_provider( def _add_query_providers( self, method_options: MethodOptions, - data_encryption_key: IKey, - provider_data_table: ProviderTable, - lambda_environment: dict, ): query_resource = self.resource.add_resource('query') - handler = self._query_providers_handler( - data_encryption_key=data_encryption_key, - provider_data_table=provider_data_table, - lambda_environment=lambda_environment, - ) + self.api.log_groups.append(self.query_providers_handler.log_group) query_resource.add_method( 'POST', @@ -188,115 +118,19 @@ def _add_query_providers( response_models={'application/json': self.api_model.query_providers_response_model}, ), ], - integration=LambdaIntegration(handler, timeout=Duration.seconds(29)), + integration=LambdaIntegration(self.query_providers_handler, timeout=Duration.seconds(29)), request_parameters={'method.request.header.Authorization': True}, authorization_type=method_options.authorization_type, authorizer=method_options.authorizer, authorization_scopes=method_options.authorization_scopes, ) - def _get_provider_handler( - self, - data_encryption_key: IKey, - provider_data_table: ProviderTable, - lambda_environment: dict, - ) -> PythonFunction: - stack = Stack.of(self.resource) - handler = PythonFunction( - self.resource, - 'GetProviderHandler', - description='Get provider handler', - lambda_dir='provider-data-v1', - index=os.path.join('handlers', 'providers.py'), - handler='get_provider', - environment=lambda_environment, - alarm_topic=self.api.alarm_topic, - ) - data_encryption_key.grant_decrypt(handler) - provider_data_table.grant_read_data(handler) - - NagSuppressions.add_resource_suppressions_by_path( - stack, - path=f'{handler.role.node.path}/DefaultPolicy/Resource', - suppressions=[ - { - 'id': 'AwsSolutions-IAM5', - 'reason': 'The actions in this policy are specifically what this lambda needs to read ' - 'and is scoped to one table and encryption key.', - }, - ], - ) - return handler - - def _query_providers_handler( - self, - data_encryption_key: IKey, - provider_data_table: ProviderTable, - lambda_environment: dict, - ) -> PythonFunction: - self.query_providers_handler = PythonFunction( - self.resource, - 'QueryProvidersHandler', - description='Query providers handler', - lambda_dir='provider-data-v1', - index=os.path.join('handlers', 'providers.py'), - handler='query_providers', - environment=lambda_environment, - alarm_topic=self.api.alarm_topic, - ) - data_encryption_key.grant_decrypt(self.query_providers_handler) - provider_data_table.grant_read_data(self.query_providers_handler) - - NagSuppressions.add_resource_suppressions_by_path( - Stack.of(self.query_providers_handler.role), - path=f'{self.query_providers_handler.role.node.path}/DefaultPolicy/Resource', - suppressions=[ - { - 'id': 'AwsSolutions-IAM5', - 'appliesTo': [ - 'Action::kms:GenerateDataKey*', - 'Action::kms:ReEncrypt*', - 'Resource::/index/*', - ], - 'reason': 'The actions in this policy are specifically what this lambda needs to read ' - 'and is scoped to one table and encryption key.', - }, - ], - ) - return self.query_providers_handler - def _add_get_provider_ssn( self, method_options: MethodOptions, - ssn_table: SSNTable, - staff_user_pool: StaffUsers, - rate_limiting_table: RateLimitingTable, - provider_table: ProviderTable, - lambda_environment: dict, ): """Add GET /providers/{providerId}/ssn endpoint to retrieve a provider's SSN.""" - handler = self._get_provider_ssn_handler( - ssn_table=ssn_table, - lambda_environment=lambda_environment, - ) - # these permissions are needed to read and write items on the rate-limiting table - rate_limiting_table.grant_read_write_data(handler) - # these permissions are needed to query provider records on the provider table - provider_table.grant_read_data(handler) - # here we grant the lambda the ability to disable staff users if they exceed the rate limit - staff_user_pool.grant(handler, 'cognito-idp:AdminDisableUser') - - NagSuppressions.add_resource_suppressions_by_path( - Stack.of(handler.role), - path=f'{handler.role.node.path}/DefaultPolicy/Resource', - suppressions=[ - { - 'id': 'AwsSolutions-IAM5', - 'reason': 'The wildcard actions in this policy are scoped to the rate-limiting table and ' - 'the provider data table.', - }, - ], - ) + self.api.log_groups.append(self.get_provider_ssn_handler.log_group) # Add the SSN endpoint as a sub-resource of the provider self.ssn_resource = self.provider_resource.add_resource('ssn') @@ -309,107 +143,13 @@ def _add_get_provider_ssn( response_models={'application/json': self.api_model.get_provider_ssn_response_model}, ), ], - integration=LambdaIntegration(handler, timeout=Duration.seconds(29)), + integration=LambdaIntegration(self.get_provider_ssn_handler, timeout=Duration.seconds(29)), request_parameters={'method.request.header.Authorization': True}, authorization_type=method_options.authorization_type, authorizer=method_options.authorizer, authorization_scopes=method_options.authorization_scopes, ) - # Create a metric to track how many times this endpoint has been invoked with a day - daily_read_ssn_count_metric = Metric( - namespace='compact-connect', - metric_name='read-ssn', - statistic='SampleCount', - period=Duration.days(1), - dimensions_map={'service': 'common'}, - ) - - # We'll monitor longer access patterns to detect anomalies, over time - # The L2 construct, Alarm, doesn't yet support Anomaly Detection as a configuration - # so we're using the L1 construct, CfnAlarm - # This anomaly detector scans the count of requests to the ssn endpoint by - # the daily_read_ssn_count_metric and uses machine-learning and pattern recognition to - # establish baselines of typical usage. - # See https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/LogsAnomalyDetection.html - self.ssn_anomaly_detection_alarm = CfnAlarm( - self.api, - 'ReadSSNAnomalyAlarm', - alarm_description=f'{self.api.node.path} read-ssn anomaly detection. The GET provider SSN endpoint has been' - f'called an irregular number of times. Investigation required to ensure ssn endpoint is ' - f'not being abused.', - comparison_operator='GreaterThanUpperThreshold', - evaluation_periods=1, - treat_missing_data='notBreaching', - actions_enabled=True, - alarm_actions=[self.api.alarm_topic.node.default_child.ref], - metrics=[ - CfnAlarm.MetricDataQueryProperty(id='ad1', expression='ANOMALY_DETECTION_BAND(m1, 2)'), - CfnAlarm.MetricDataQueryProperty( - id='m1', - metric_stat=CfnAlarm.MetricStatProperty( - metric=CfnAlarm.MetricProperty( - metric_name=daily_read_ssn_count_metric.metric_name, - namespace=daily_read_ssn_count_metric.namespace, - dimensions=[CfnAlarm.DimensionProperty(name='service', value='common')], - ), - period=3600, - stat='SampleCount', - ), - ), - ], - threshold_metric_id='ad1', - ) - - # Create a metric to track if any user is rate-limited while calling this endpoint - ssn_rate_limited_count_metric = Metric( - namespace='compact-connect', - metric_name='rate-limited-ssn-access', - statistic='SampleCount', - period=Duration.minutes(5), - dimensions_map={'service': 'common'}, - ) - - # This alarm will fire if any user is rate-limited by this endpoint - # This will help us determine if the limit needs to be raised or detect early abuse - self.ssn_rate_limited_alarm = Alarm( - self.api, - 'SSNReadsRateLimitedAlarm', - metric=ssn_rate_limited_count_metric, - threshold=1, - evaluation_periods=1, - comparison_operator=ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, - treat_missing_data=TreatMissingData.NOT_BREACHING, - alarm_description=f'{self.api.node.path} ssn reads rate-limited alarm. The GET provider SSN endpoint has ' - f'been invoked more than an expected threshold within a 24 hour period. Investigation is required to ensure' - f' access is not the result of abuse.', - ) - self.ssn_rate_limited_alarm.add_alarm_action(SnsAction(self.api.alarm_topic)) - - # Create a metric to track if ssn endpoint has been disabled due to excessive requests - ssn_endpoint_disabled_count_metric = Metric( - namespace='compact-connect', - metric_name='ssn-endpoint-disabled', - statistic='SampleCount', - period=Duration.minutes(5), - dimensions_map={'service': 'common'}, - ) - # This alarm will fire if the ssn endpoint hits our global threshold and is disabled (concurrency set to 0) - self.ssn_endpoint_disabled_alarm = Alarm( - self.api, - 'SSNEndpointDisabledAlarm', - metric=ssn_endpoint_disabled_count_metric, - threshold=1, - evaluation_periods=1, - comparison_operator=ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, - treat_missing_data=TreatMissingData.NOT_BREACHING, - alarm_description=f'{self.api.node.path} SECURITY ALERT: SSN ENDPOINT DISABLED. The GET provider SSN ' - 'endpoint has been disabled due to excessive requests. Immediate investigation required. ' - 'Endpoint will need to be manually reactivated before any further requests can be ' - 'processed.', - ) - self.ssn_endpoint_disabled_alarm.add_alarm_action(SnsAction(self.api.alarm_topic)) - # Add an alarm for 4xx responses from the SSN endpoint self.ssn_api_throttling_alarm = Alarm( self.api, @@ -436,61 +176,13 @@ def _add_get_provider_ssn( ) self.ssn_api_throttling_alarm.add_alarm_action(SnsAction(self.api.alarm_topic)) - def _get_provider_ssn_handler( - self, - ssn_table: SSNTable, - lambda_environment: dict, - ) -> PythonFunction: - """Create and configure the Lambda handler for retrieving a provider's SSN.""" - self.get_provider_ssn_handler = PythonFunction( - self.resource, - 'GetProviderSSNHandler', - description='Get provider SSN handler', - lambda_dir='provider-data-v1', - index=os.path.join('handlers', 'providers.py'), - handler='get_provider_ssn', - role=ssn_table.api_query_role, - environment=lambda_environment, - alarm_topic=self.api.alarm_topic, - ) - # The lambda needs to read providers from the provider table and the SSN from the ssn table - # Though, ssn table access is granted via resource policies on the table and key so `.grant()` - # calls are not needed here. - - # Add permission for the lambda to update its own concurrency setting - function_arn = self.get_provider_ssn_handler.function_arn - self.get_provider_ssn_handler.role.attach_inline_policy( - Policy( - self.resource, - 'PutFunctionConcurrency', - statements=[ - PolicyStatement( - actions=['lambda:PutFunctionConcurrency'], - resources=[function_arn], - ) - ], - ) - ) - return self.get_provider_ssn_handler - def _add_deactivate_privilege( self, method_options: MethodOptions, - event_bus: EventBus, - provider_data_table: ProviderTable, - email_service_lambda: NodejsFunction, - staff_users_table: Table, - lambda_environment: dict, ): """Add POST /providers/{providerId}/privileges/jurisdiction/{jurisdiction} /licenseType/{licenseType}/deactivate endpoint.""" - handler = self._deactivate_privilege_handler( - provider_data_table=provider_data_table, - event_bus=event_bus, - email_service_lambda=email_service_lambda, - staff_users_table=staff_users_table, - lambda_environment=lambda_environment, - ) + self.api.log_groups.append(self.deactivate_privilege_handler.log_group) deactivate_resource = self.privilege_jurisdiction_license_type_resource.add_resource('deactivate') @@ -528,85 +220,13 @@ def _add_deactivate_privilege( response_models={'application/json': self.api_model.message_response_model}, ), ], - integration=LambdaIntegration(handler, timeout=Duration.seconds(29)), + integration=LambdaIntegration(self.deactivate_privilege_handler, timeout=Duration.seconds(29)), request_parameters={'method.request.header.Authorization': True}, authorization_type=method_options.authorization_type, authorizer=method_options.authorizer, authorization_scopes=method_options.authorization_scopes, ) - def _deactivate_privilege_handler( - self, - provider_data_table: ProviderTable, - event_bus: EventBus, - email_service_lambda: NodejsFunction, - staff_users_table: Table, - lambda_environment: dict, - ) -> PythonFunction: - """Create and configure the Lambda handler for deactivating a provider's privilege.""" - self.deactivate_privilege_handler = PythonFunction( - self.resource, - 'DeactivatePrivilegeHandler', - description='Deactivate provider privilege handler', - lambda_dir='provider-data-v1', - index=os.path.join('handlers', 'privileges.py'), - handler='deactivate_privilege', - environment=lambda_environment, - alarm_topic=self.api.alarm_topic, - ) - provider_data_table.grant_read_write_data(self.deactivate_privilege_handler) - staff_users_table.grant_read_data(self.deactivate_privilege_handler) - event_bus.grant_put_events_to(self.deactivate_privilege_handler) - email_service_lambda.grant_invoke(self.deactivate_privilege_handler) - - NagSuppressions.add_resource_suppressions_by_path( - Stack.of(self.deactivate_privilege_handler.role), - path=f'{self.deactivate_privilege_handler.role.node.path}/DefaultPolicy/Resource', - suppressions=[ - { - 'id': 'AwsSolutions-IAM5', - 'reason': 'The actions in this policy are specifically what this lambda needs to read/write ' - 'and is scoped to one table and event bus.', - }, - ], - ) - return self.deactivate_privilege_handler - - def _add_provider_encumbrance_handler( - self, - provider_data_table: ProviderTable, - staff_users_table: Table, - event_bus: EventBus, - lambda_environment: dict, - ) -> PythonFunction: - """Create and configure the Lambda handler for encumbering a provider's privilege or license.""" - encumbrance_handler = PythonFunction( - self.resource, - 'ProviderEncumbranceHandler', - description='Provider encumbrance handler', - lambda_dir='provider-data-v1', - index=os.path.join('handlers', 'encumbrance.py'), - handler='encumbrance_handler', - environment=lambda_environment, - alarm_topic=self.api.alarm_topic, - ) - provider_data_table.grant_read_write_data(encumbrance_handler) - staff_users_table.grant_read_data(encumbrance_handler) - event_bus.grant_put_events_to(encumbrance_handler) - - NagSuppressions.add_resource_suppressions_by_path( - Stack.of(encumbrance_handler.role), - path=f'{encumbrance_handler.role.node.path}/DefaultPolicy/Resource', - suppressions=[ - { - 'id': 'AwsSolutions-IAM5', - 'reason': 'The actions in this policy are specifically what this lambda needs to read/write ' - 'and is scoped to the needed tables and event bus.', - }, - ], - ) - return encumbrance_handler - def _add_encumber_privilege( self, method_options: MethodOptions, diff --git a/backend/compact-connect/tests/app/test_api/test_provider_management_api.py b/backend/compact-connect/tests/app/test_api/test_provider_management_api.py index b8e10925c..6404f8f76 100644 --- a/backend/compact-connect/tests/app/test_api/test_provider_management_api.py +++ b/backend/compact-connect/tests/app/test_api/test_provider_management_api.py @@ -198,6 +198,8 @@ def test_synth_generates_get_provider_endpoint(self): """Test that the GET /providers/{providerId} endpoint is configured correctly.""" api_stack = self.app.sandbox_backend_stage.api_stack api_stack_template = Template.from_stack(api_stack) + api_lambda_stack = self.app.sandbox_backend_stage.api_lambda_stack + api_lambda_stack_template = Template.from_stack(api_lambda_stack) # Ensure the resource is created with expected path api_stack_template.has_resource_properties( @@ -213,13 +215,11 @@ def test_synth_generates_get_provider_endpoint(self): ) # Ensure the lambda is created with expected code path - get_handler = TestApi.get_resource_properties_by_logical_id( - api_stack.get_logical_id(api_stack.api.v1_api.provider_management.get_provider_handler.node.default_child), - api_stack_template.find_resources(CfnFunction.CFN_RESOURCE_TYPE_NAME), + api_lambda_stack_template.has_resource_properties( + type=CfnFunction.CFN_RESOURCE_TYPE_NAME, + props={'Handler': 'handlers.providers.get_provider'}, ) - self.assertEqual(get_handler['Handler'], 'handlers.providers.get_provider') - # Capture model logical ID for verification response_model_logical_id_capture = Capture() @@ -231,10 +231,10 @@ def test_synth_generates_get_provider_endpoint(self): 'AuthorizerId': { 'Ref': api_stack.get_logical_id(api_stack.api.staff_users_authorizer.node.default_child), }, - 'Integration': TestApi.generate_expected_integration_object( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.get_provider_handler.node.default_child, - ), + 'Integration': TestApi.generate_expected_integration_object_for_imported_lambda( + api_lambda_stack, + api_lambda_stack_template, + api_lambda_stack.provider_management_lambdas.get_provider_handler, ), 'MethodResponses': [ { @@ -260,6 +260,8 @@ def test_synth_generates_query_providers_endpoint(self): """Test that the POST /providers/query endpoint is configured correctly.""" api_stack = self.app.sandbox_backend_stage.api_stack api_stack_template = Template.from_stack(api_stack) + api_lambda_stack = self.app.sandbox_backend_stage.api_lambda_stack + api_lambda_stack_template = Template.from_stack(api_lambda_stack) # Ensure the resource is created with expected path api_stack_template.has_resource_properties( @@ -276,15 +278,11 @@ def test_synth_generates_query_providers_endpoint(self): ) # Ensure the lambda is created with expected code path - query_handler = TestApi.get_resource_properties_by_logical_id( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.query_providers_handler.node.default_child - ), - api_stack_template.find_resources(CfnFunction.CFN_RESOURCE_TYPE_NAME), + api_lambda_stack_template.has_resource_properties( + type=CfnFunction.CFN_RESOURCE_TYPE_NAME, + props={'Handler': 'handlers.providers.query_providers'}, ) - self.assertEqual(query_handler['Handler'], 'handlers.providers.query_providers') - # Capture model logical IDs for verification request_model_logical_id_capture = Capture() response_model_logical_id_capture = Capture() @@ -297,10 +295,10 @@ def test_synth_generates_query_providers_endpoint(self): 'AuthorizerId': { 'Ref': api_stack.get_logical_id(api_stack.api.staff_users_authorizer.node.default_child), }, - 'Integration': TestApi.generate_expected_integration_object( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.query_providers_handler.node.default_child, - ), + 'Integration': TestApi.generate_expected_integration_object_for_imported_lambda( + api_lambda_stack, + api_lambda_stack_template, + api_lambda_stack.provider_management_lambdas.query_providers_handler, ), 'RequestModels': { 'application/json': {'Ref': request_model_logical_id_capture}, @@ -340,6 +338,8 @@ def test_synth_generates_get_provider_ssn_endpoint(self): """Test that the GET /providers/{providerId}/ssn endpoint is configured correctly.""" api_stack = self.app.sandbox_backend_stage.api_stack api_stack_template = Template.from_stack(api_stack) + api_lambda_stack = self.app.sandbox_backend_stage.api_lambda_stack + api_lambda_stack_template = Template.from_stack(api_lambda_stack) # Ensure the resource is created with expected path api_stack_template.has_resource_properties( @@ -355,15 +355,11 @@ def test_synth_generates_get_provider_ssn_endpoint(self): ) # Ensure the lambda is created with expected code path - ssn_handler = TestApi.get_resource_properties_by_logical_id( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.get_provider_ssn_handler.node.default_child - ), - api_stack_template.find_resources(CfnFunction.CFN_RESOURCE_TYPE_NAME), + api_lambda_stack_template.has_resource_properties( + type=CfnFunction.CFN_RESOURCE_TYPE_NAME, + props={'Handler': 'handlers.providers.get_provider_ssn'}, ) - self.assertEqual(ssn_handler['Handler'], 'handlers.providers.get_provider_ssn') - # Capture model logical ID for verification response_model_logical_id_capture = Capture() @@ -375,10 +371,10 @@ def test_synth_generates_get_provider_ssn_endpoint(self): 'AuthorizerId': { 'Ref': api_stack.get_logical_id(api_stack.api.staff_users_authorizer.node.default_child), }, - 'Integration': TestApi.generate_expected_integration_object( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.get_provider_ssn_handler.node.default_child, - ), + 'Integration': TestApi.generate_expected_integration_object_for_imported_lambda( + api_lambda_stack, + api_lambda_stack_template, + api_lambda_stack.provider_management_lambdas.get_provider_ssn_handler, ), 'MethodResponses': [ { @@ -404,11 +400,13 @@ def test_synth_generates_get_provider_ssn_alarms(self): """Test that the GET /providers/{providerId}/ssn alarms are configured correctly.""" api_stack = self.app.sandbox_backend_stage.api_stack api_stack_template = Template.from_stack(api_stack) + api_lambda_stack = self.app.sandbox_backend_stage.api_lambda_stack + api_lambda_stack_template = Template.from_stack(api_lambda_stack) # Ensure the anomaly detection alarm is created - alarms = api_stack_template.find_resources(CfnAlarm.CFN_RESOURCE_TYPE_NAME) + alarms = api_lambda_stack_template.find_resources(CfnAlarm.CFN_RESOURCE_TYPE_NAME) anomaly_alarm = TestApi.get_resource_properties_by_logical_id( - api_stack.get_logical_id(api_stack.api.v1_api.provider_management.ssn_anomaly_detection_alarm), + api_lambda_stack.get_logical_id(api_lambda_stack.provider_management_lambdas.ssn_anomaly_detection_alarm), alarms, ) @@ -425,8 +423,8 @@ def test_synth_generates_get_provider_ssn_alarms(self): # Ensure the ssn read rate-limited alarm is created ssn_read_rate_limited_alarm = TestApi.get_resource_properties_by_logical_id( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.ssn_rate_limited_alarm.node.default_child + api_lambda_stack.get_logical_id( + api_lambda_stack.provider_management_lambdas.ssn_rate_limited_alarm.node.default_child ), alarms, ) @@ -442,8 +440,8 @@ def test_synth_generates_get_provider_ssn_alarms(self): # Ensure the ssn endpoint disabled alarm is created ssn_endpoint_disabled_alarm = TestApi.get_resource_properties_by_logical_id( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.ssn_endpoint_disabled_alarm.node.default_child + api_lambda_stack.get_logical_id( + api_lambda_stack.provider_management_lambdas.ssn_endpoint_disabled_alarm.node.default_child ), alarms, ) @@ -457,12 +455,13 @@ def test_synth_generates_get_provider_ssn_alarms(self): overwrite_snapshot=False, ) - # Ensure the 4xx API alarm is created + # Ensure the 4xx API alarm is created (still in api_stack) + api_stack_alarms = api_stack_template.find_resources(CfnAlarm.CFN_RESOURCE_TYPE_NAME) throttling_alarm = TestApi.get_resource_properties_by_logical_id( api_stack.get_logical_id( api_stack.api.v1_api.provider_management.ssn_api_throttling_alarm.node.default_child ), - alarms, + api_stack_alarms, ) actions = throttling_alarm.pop('AlarmActions', []) @@ -479,17 +478,15 @@ def test_synth_generates_deactivate_privilege_endpoint(self): /licenseType/{licenseType}/deactivate endpoint is configured correctly.""" api_stack = self.app.sandbox_backend_stage.api_stack api_stack_template = Template.from_stack(api_stack) + api_lambda_stack = self.app.sandbox_backend_stage.api_lambda_stack + api_lambda_stack_template = Template.from_stack(api_lambda_stack) # Ensure the lambda is created with expected code path - deactivate_handler = TestApi.get_resource_properties_by_logical_id( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.deactivate_privilege_handler.node.default_child - ), - api_stack_template.find_resources(CfnFunction.CFN_RESOURCE_TYPE_NAME), + api_lambda_stack_template.has_resource_properties( + type=CfnFunction.CFN_RESOURCE_TYPE_NAME, + props={'Handler': 'handlers.privileges.deactivate_privilege'}, ) - self.assertEqual(deactivate_handler['Handler'], 'handlers.privileges.deactivate_privilege') - request_model_logical_id_capture = Capture() # Ensure the POST method is configured correctly @@ -500,10 +497,10 @@ def test_synth_generates_deactivate_privilege_endpoint(self): 'AuthorizerId': { 'Ref': api_stack.get_logical_id(api_stack.api.staff_users_authorizer.node.default_child), }, - 'Integration': TestApi.generate_expected_integration_object( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.deactivate_privilege_handler.node.default_child, - ), + 'Integration': TestApi.generate_expected_integration_object_for_imported_lambda( + api_lambda_stack, + api_lambda_stack_template, + api_lambda_stack.provider_management_lambdas.deactivate_privilege_handler, ), 'RequestModels': { 'application/json': {'Ref': request_model_logical_id_capture}, @@ -576,17 +573,15 @@ def test_synth_generates_privilege_encumbrance_endpoint(self): /licenseType/{licenseType}/encumbrance endpoint is configured correctly.""" api_stack = self.app.sandbox_backend_stage.api_stack api_stack_template = Template.from_stack(api_stack) + api_lambda_stack = self.app.sandbox_backend_stage.api_lambda_stack + api_lambda_stack_template = Template.from_stack(api_lambda_stack) # Ensure the lambda is created with expected code path - encumbrance_handler = TestApi.get_resource_properties_by_logical_id( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.provider_encumbrance_handler.node.default_child - ), - api_stack_template.find_resources(CfnFunction.CFN_RESOURCE_TYPE_NAME), + api_lambda_stack_template.has_resource_properties( + type=CfnFunction.CFN_RESOURCE_TYPE_NAME, + props={'Handler': 'handlers.encumbrance.encumbrance_handler'}, ) - self.assertEqual(encumbrance_handler['Handler'], 'handlers.encumbrance.encumbrance_handler') - # Verify the privilege encumbrance resource path is created correctly encumbrance_resource_logical_id = self._get_privilege_encumbrance_resource_id(api_stack_template, api_stack) @@ -600,10 +595,10 @@ def test_synth_generates_privilege_encumbrance_endpoint(self): 'AuthorizerId': { 'Ref': api_stack.get_logical_id(api_stack.api.staff_users_authorizer.node.default_child), }, - 'Integration': TestApi.generate_expected_integration_object( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.provider_encumbrance_handler.node.default_child, - ), + 'Integration': TestApi.generate_expected_integration_object_for_imported_lambda( + api_lambda_stack, + api_lambda_stack_template, + api_lambda_stack.provider_management_lambdas.provider_encumbrance_handler, ), 'RequestModels': { 'application/json': {'Ref': request_model_logical_id_capture}, @@ -639,6 +634,8 @@ def test_synth_generates_license_encumbrance_endpoint(self): /licenseType/{licenseType}/encumbrance endpoint is configured correctly.""" api_stack = self.app.sandbox_backend_stage.api_stack api_stack_template = Template.from_stack(api_stack) + api_lambda_stack = self.app.sandbox_backend_stage.api_lambda_stack + api_lambda_stack_template = Template.from_stack(api_lambda_stack) # Verify the license encumbrance resource path is created correctly encumbrance_resource_logical_id = self._get_license_encumbrance_resource_id(api_stack_template, api_stack) @@ -653,10 +650,10 @@ def test_synth_generates_license_encumbrance_endpoint(self): 'AuthorizerId': { 'Ref': api_stack.get_logical_id(api_stack.api.staff_users_authorizer.node.default_child), }, - 'Integration': TestApi.generate_expected_integration_object( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.provider_encumbrance_handler.node.default_child, - ), + 'Integration': TestApi.generate_expected_integration_object_for_imported_lambda( + api_lambda_stack, + api_lambda_stack_template, + api_lambda_stack.provider_management_lambdas.provider_encumbrance_handler, ), 'RequestModels': { 'application/json': {'Ref': request_model_logical_id_capture}, @@ -692,6 +689,8 @@ def test_synth_generates_privilege_encumbrance_lifting_endpoint(self): /licenseType/{licenseType}/encumbrance/{encumbranceId} endpoint is configured correctly.""" api_stack = self.app.sandbox_backend_stage.api_stack api_stack_template = Template.from_stack(api_stack) + api_lambda_stack = self.app.sandbox_backend_stage.api_lambda_stack + api_lambda_stack_template = Template.from_stack(api_lambda_stack) # Get the encumbrance resource logical ID encumbrance_resource_logical_id = self._get_privilege_encumbrance_resource_id(api_stack_template, api_stack) @@ -719,10 +718,10 @@ def test_synth_generates_privilege_encumbrance_lifting_endpoint(self): 'AuthorizerId': { 'Ref': api_stack.get_logical_id(api_stack.api.staff_users_authorizer.node.default_child), }, - 'Integration': TestApi.generate_expected_integration_object( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.provider_encumbrance_handler.node.default_child, - ), + 'Integration': TestApi.generate_expected_integration_object_for_imported_lambda( + api_lambda_stack, + api_lambda_stack_template, + api_lambda_stack.provider_management_lambdas.provider_encumbrance_handler, ), 'RequestModels': { 'application/json': {'Ref': request_model_logical_id_capture}, @@ -758,6 +757,8 @@ def test_synth_generates_license_encumbrance_lifting_endpoint(self): /licenseType/{licenseType}/encumbrance/{encumbranceId} endpoint is configured correctly.""" api_stack = self.app.sandbox_backend_stage.api_stack api_stack_template = Template.from_stack(api_stack) + api_lambda_stack = self.app.sandbox_backend_stage.api_lambda_stack + api_lambda_stack_template = Template.from_stack(api_lambda_stack) # Find the license encumbrance resource encumbrance_resource_logical_id = self._get_license_encumbrance_resource_id(api_stack_template, api_stack) @@ -785,10 +786,10 @@ def test_synth_generates_license_encumbrance_lifting_endpoint(self): 'AuthorizerId': { 'Ref': api_stack.get_logical_id(api_stack.api.staff_users_authorizer.node.default_child), }, - 'Integration': TestApi.generate_expected_integration_object( - api_stack.get_logical_id( - api_stack.api.v1_api.provider_management.provider_encumbrance_handler.node.default_child, - ), + 'Integration': TestApi.generate_expected_integration_object_for_imported_lambda( + api_lambda_stack, + api_lambda_stack_template, + api_lambda_stack.provider_management_lambdas.provider_encumbrance_handler, ), 'RequestModels': { 'application/json': {'Ref': request_model_logical_id_capture}, diff --git a/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_ANOMALY_DETECTION_ALARM_SCHEMA.json b/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_ANOMALY_DETECTION_ALARM_SCHEMA.json index 840d335a8..0fa791e18 100644 --- a/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_ANOMALY_DETECTION_ALARM_SCHEMA.json +++ b/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_ANOMALY_DETECTION_ALARM_SCHEMA.json @@ -1,6 +1,6 @@ { "ActionsEnabled": true, - "AlarmDescription": "Sandbox/APIStack/LicenseApi read-ssn anomaly detection. The GET provider SSN endpoint has beencalled an irregular number of times. Investigation required to ensure ssn endpoint is not being abused.", + "AlarmDescription": "Sandbox/ApiLambdaStack/GetProviderSSNHandler read-ssn anomaly detection. The GET provider SSN endpoint has beencalled an irregular number of times. Investigation required to ensure ssn endpoint is not being abused.", "ComparisonOperator": "GreaterThanUpperThreshold", "EvaluationPeriods": 1, "Metrics": [ diff --git a/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_ENDPOINT_DISABLED_ALARM_SCHEMA.json b/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_ENDPOINT_DISABLED_ALARM_SCHEMA.json index 45552e3cd..7f0ee4302 100644 --- a/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_ENDPOINT_DISABLED_ALARM_SCHEMA.json +++ b/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_ENDPOINT_DISABLED_ALARM_SCHEMA.json @@ -1,5 +1,5 @@ { - "AlarmDescription": "Sandbox/APIStack/LicenseApi SECURITY ALERT: SSN ENDPOINT DISABLED. The GET provider SSN endpoint has been disabled due to excessive requests. Immediate investigation required. Endpoint will need to be manually reactivated before any further requests can be processed.", + "AlarmDescription": "Sandbox/ApiLambdaStack/GetProviderSSNHandler SECURITY ALERT: SSN ENDPOINT DISABLED. The GET provider SSN endpoint has been disabled due to excessive requests. Immediate investigation required. Endpoint will need to be manually reactivated before any further requests can be processed.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { diff --git a/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_READS_RATE_LIMITED_ALARM_SCHEMA.json b/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_READS_RATE_LIMITED_ALARM_SCHEMA.json index 855005459..1e27801c3 100644 --- a/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_READS_RATE_LIMITED_ALARM_SCHEMA.json +++ b/backend/compact-connect/tests/resources/snapshots/GET_PROVIDER_SSN_READS_RATE_LIMITED_ALARM_SCHEMA.json @@ -1,5 +1,5 @@ { - "AlarmDescription": "Sandbox/APIStack/LicenseApi ssn reads rate-limited alarm. The GET provider SSN endpoint has been invoked more than an expected threshold within a 24 hour period. Investigation is required to ensure access is not the result of abuse.", + "AlarmDescription": "Sandbox/ApiLambdaStack/GetProviderSSNHandler ssn reads rate-limited alarm. The GET provider SSN endpoint has been invoked more than an expected threshold within a 24 hour period. Investigation is required to ensure access is not the result of abuse.", "ComparisonOperator": "GreaterThanOrEqualToThreshold", "Dimensions": [ { From 4146d34ab7485605781487b19a44942c8686d72e Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 8 Oct 2025 16:52:36 -0500 Subject: [PATCH 11/26] formatting --- .../common/cc_common/data_model/data_client.py | 15 ++++++++------- .../data_model/schema/adverse_action/record.py | 3 ++- .../data_model/schema/privilege/record.py | 8 +++++--- .../provider-data-v1/handlers/encumbrance.py | 4 ++-- .../function/test_handlers/test_encumbrance.py | 4 ++-- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py index 672e8b1fa..5e10cb8e0 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py @@ -2641,13 +2641,14 @@ def encumber_home_jurisdiction_license_privileges( adverse_action = provider_user_records.get_adverse_action_by_id(adverse_action_id) if not adverse_action: - logger.error("Adverse Action not found by id", - provider_id=provider_id, - encumbered_license_jurisdiction=jurisdiction, - encumbered_license_type=license_type_abbreviation, - adverse_action_id=adverse_action_id) - raise CCInternalException("Adverse Action not found by id") - + logger.error( + 'Adverse Action not found by id', + provider_id=provider_id, + encumbered_license_jurisdiction=jurisdiction, + encumbered_license_type=license_type_abbreviation, + adverse_action_id=adverse_action_id, + ) + raise CCInternalException('Adverse Action not found by id') # Find privileges associated with the license that which was encumbered, which themselves are not currently # encumbered diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py index b8b09307d..cfd645249 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py @@ -49,7 +49,8 @@ class AdverseActionRecordSchema(BaseRecordSchema): # TODO - remove this hook once migration is complete to the new field # noqa: FIX002 @pre_load def migrate_clinical_privilege_action_category_on_load(self, in_data, **_kwargs): - """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list when loading from database.""" + """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list + when loading from database.""" # If the deprecated field exists and the new field doesn't, migrate it if 'clinicalPrivilegeActionCategory' in in_data and 'clinicalPrivilegeActionCategories' not in in_data: in_data['clinicalPrivilegeActionCategories'] = [in_data['clinicalPrivilegeActionCategory']] diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py index 7b808c6ec..8cb08caa5 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py @@ -56,6 +56,7 @@ class EncumbranceDetailsSchema(Schema): """ Schema for tracking details about an encumbrance. """ + clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) adverseActionId = UUID(required=True, allow_none=False) # present if update is created by upstream license encumbrance @@ -63,18 +64,19 @@ class EncumbranceDetailsSchema(Schema): # TODO - remove this field as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) - # TODO - remove these hooks as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 @pre_load def migrate_clinical_privilege_action_category_on_load(self, in_data, **_kwargs): - """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list when loading from database.""" + """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list + when loading from database.""" if 'clinicalPrivilegeActionCategory' in in_data and 'clinicalPrivilegeActionCategories' not in in_data: in_data['clinicalPrivilegeActionCategories'] = [in_data['clinicalPrivilegeActionCategory']] return in_data @pre_dump def migrate_clinical_privilege_action_category_on_dump(self, in_data, **_kwargs): - """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list when dumping to database.""" + """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list + when dumping to database.""" if 'clinicalPrivilegeActionCategory' in in_data and 'clinicalPrivilegeActionCategories' not in in_data: in_data['clinicalPrivilegeActionCategories'] = [in_data['clinicalPrivilegeActionCategory']] return in_data diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py index 0cfdf5ae8..3d23cb245 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py @@ -105,8 +105,8 @@ def _generate_adverse_action_for_record_type( if 'clinicalPrivilegeActionCategory' in adverse_action_request: # replicate data to both the deprecated and new fields adverse_action.clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategory( - adverse_action_request['clinicalPrivilegeActionCategory'] - ) + adverse_action_request['clinicalPrivilegeActionCategory'] + ) adverse_action.clinicalPrivilegeActionCategories = [ ClinicalPrivilegeActionCategory(adverse_action_request['clinicalPrivilegeActionCategory']) ] diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py index abce39e51..39547ee6c 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py @@ -331,7 +331,7 @@ def test_privilege_encumbrance_handler_migrates_clinical_privilege_action_catego # Load the adverse action record from the database loaded_adverse_action = AdverseActionData.from_database_record(item) - # TODO - remove this assertion as part of https://github.com/csg-org/CompactConnect/issues/1136 + # TODO - remove this assertion as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 # Verify that the deprecated field is not present in the stored data self.assertIn('clinicalPrivilegeActionCategory', item) self.assertEqual('Unsafe Practice or Substandard Care', loaded_adverse_action.clinicalPrivilegeActionCategory) @@ -613,7 +613,7 @@ def test_license_encumbrance_handler_migrates_clinical_privilege_action_category # Load the adverse action record from the database loaded_adverse_action = AdverseActionData.from_database_record(item) - # TODO - remove this assertion as part of https://github.com/csg-org/CompactConnect/issues/1136 + # TODO - remove this assertion as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 # Verify that the deprecated field is not present in the stored data self.assertIn('clinicalPrivilegeActionCategory', item) self.assertEqual('Unsafe Practice or Substandard Care', loaded_adverse_action.clinicalPrivilegeActionCategory) From 2d8f4a3934ed41e94dbb096d68a3c692e923e382 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Thu, 9 Oct 2025 17:03:56 -0500 Subject: [PATCH 12/26] Add feature flag for gating new behavior --- .../cc_common/data_model/data_client.py | 11 +- .../data_model/provider_record_util.py | 7 +- .../data_model/schema/privilege/record.py | 17 --- .../test_schema/test_adverse_action.py | 1 + .../tests/unit/test_provider_record_util.py | 11 +- .../tests/function/test_encumbrance_events.py | 105 +++++++++++++++++- .../provider-data-v1/handlers/encumbrance.py | 1 + .../test_handlers/test_encumbrance.py | 51 ++++++++- .../test_handlers/test_privilege_history.py | 8 +- .../stacks/feature_flag_stack/__init__.py | 11 ++ 10 files changed, 193 insertions(+), 30 deletions(-) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py index 5e10cb8e0..a4c3b5142 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py @@ -1427,8 +1427,10 @@ def encumber_privilege(self, adverse_action: AdverseActionData) -> None: ) now = config.current_standard_datetime - # TODO - replace with a feature flag when available - if True: + # TODO - remove the flag as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + from cc_common.feature_flag_client import is_feature_enabled + + if is_feature_enabled('encumbrance-multi-category-flag'): encumbrance_details = { 'clinicalPrivilegeActionCategories': adverse_action.clinicalPrivilegeActionCategories, 'adverseActionId': adverse_action.adverseActionId, @@ -2671,9 +2673,10 @@ def encumber_home_jurisdiction_license_privileges( logger.info( 'Found privileges to encumber', privilege_count=len(unencumbered_privileges_associated_with_license) ) + # TODO - remove the flag as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + from cc_common.feature_flag_client import is_feature_enabled - # TODO - replace with feature flag when available - if True: + if is_feature_enabled('encumbrance-multi-category-flag'): encumbrance_details = { 'clinicalPrivilegeActionCategories': adverse_action.clinicalPrivilegeActionCategories, 'licenseJurisdiction': jurisdiction, diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/provider_record_util.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/provider_record_util.py index 51ab1835e..ded200d6f 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/provider_record_util.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/provider_record_util.py @@ -373,8 +373,11 @@ def construct_simplified_privilege_history_object( and event.get('encumbranceDetails') and should_include_encumbrance_details ): - # TODO - replace this with a feature flag when available - if True: + # TODO - remove the flag as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + # as well as check for deprecated field + from cc_common.feature_flag_client import is_feature_enabled + + if is_feature_enabled('encumbrance-multi-category-flag'): if 'clinicalPrivilegeActionCategory' in event['encumbranceDetails']: event['note'] = event['encumbranceDetails'].get('clinicalPrivilegeActionCategory') else: diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py index 8cb08caa5..cfacf242c 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py @@ -64,23 +64,6 @@ class EncumbranceDetailsSchema(Schema): # TODO - remove this field as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) - # TODO - remove these hooks as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 - @pre_load - def migrate_clinical_privilege_action_category_on_load(self, in_data, **_kwargs): - """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list - when loading from database.""" - if 'clinicalPrivilegeActionCategory' in in_data and 'clinicalPrivilegeActionCategories' not in in_data: - in_data['clinicalPrivilegeActionCategories'] = [in_data['clinicalPrivilegeActionCategory']] - return in_data - - @pre_dump - def migrate_clinical_privilege_action_category_on_dump(self, in_data, **_kwargs): - """Migrate deprecated clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories list - when dumping to database.""" - if 'clinicalPrivilegeActionCategory' in in_data and 'clinicalPrivilegeActionCategories' not in in_data: - in_data['clinicalPrivilegeActionCategories'] = [in_data['clinicalPrivilegeActionCategory']] - return in_data - @BaseRecordSchema.register_schema('privilege') class PrivilegeRecordSchema(BaseRecordSchema, ValidatesLicenseTypeMixin): diff --git a/backend/compact-connect/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py b/backend/compact-connect/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py index 3a395e64e..52c725abb 100644 --- a/backend/compact-connect/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py +++ b/backend/compact-connect/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py @@ -111,6 +111,7 @@ def test_adverse_action_data_class_outputs_expected_database_object(self): 'actionAgainst': 'privilege', 'adverseActionId': '98765432-9876-9876-9876-987654321098', 'encumbranceType': 'suspension', + 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', 'compact': 'aslp', 'creationDate': '2024-11-08T23:59:59+00:00', diff --git a/backend/compact-connect/lambdas/python/common/tests/unit/test_provider_record_util.py b/backend/compact-connect/lambdas/python/common/tests/unit/test_provider_record_util.py index 37b588128..324f5ff23 100644 --- a/backend/compact-connect/lambdas/python/common/tests/unit/test_provider_record_util.py +++ b/backend/compact-connect/lambdas/python/common/tests/unit/test_provider_record_util.py @@ -911,7 +911,9 @@ def test_construct_simplified_privilege_history_object_returns_deactivation_note self.maxDiff = None self.assertEqual(expected_history, history) - def test_construct_simplified_privilege_history_object_returns_encumbrance_notes_if_requested(self): + # TODO - remove mock flag as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=True) + def test_construct_simplified_privilege_history_object_returns_encumbrance_notes_if_requested(self, mock_flag): # noqa: ARG002 """Test that construct_simplified_privilege_history_object extracts the encumbrance notes successfully""" from cc_common.data_model.provider_record_util import ProviderRecordUtility @@ -989,7 +991,12 @@ def test_construct_simplified_privilege_history_object_returns_encumbrance_notes self.maxDiff = None self.assertEqual(expected_history, history) - def test_construct_simplified_privilege_history_object_does_not_return_encumbrance_notes_if_not_requested(self): + # TODO - remove mock flag as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=True) + def test_construct_simplified_privilege_history_object_does_not_return_encumbrance_notes_if_not_requested( + self, + mock_flag, # noqa: ARG002 + ): """Test that construct_simplified_privilege_history_object does not extract the encumbrance notes if it should not""" from cc_common.data_model.provider_record_util import ProviderRecordUtility diff --git a/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py b/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py index c462421e1..83ea743be 100644 --- a/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py +++ b/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py @@ -80,6 +80,11 @@ def test_license_encumbrance_listener_encumbers_unencumbered_privileges_successf } ) + # add adverse action item for license + self.test_data_generator.put_default_adverse_action_record_in_provider_table( + value_overrides={'actionAgainst': 'license'} + ) + message = self._generate_license_encumbrance_message() event = self._create_sqs_event(message) @@ -190,8 +195,14 @@ def test_license_encumbrance_listener_handles_no_matching_privileges(self, mock_ # Verify no privilege encumbrance events were published since no privileges were affected mock_publish_event.assert_not_called() + # TODO - remove the mock flag as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=True) @patch('cc_common.event_bus_client.EventBusClient._publish_event') - def test_license_encumbrance_listener_handles_all_privileges_already_encumbered(self, mock_publish_event): + def test_license_encumbrance_listener_handles_all_privileges_already_encumbered( + self, + mock_publish_event, + mock_flag, # noqa: ARG002 + ): """Test that license encumbrance event handles case where all matching privileges are already encumbered.""" from cc_common.data_model.schema.common import PrivilegeEncumberedStatusEnum from handlers.encumbrance_events import license_encumbrance_listener @@ -208,6 +219,79 @@ def test_license_encumbrance_listener_handles_all_privileges_already_encumbered( } ) + # add adverse action item for license + self.test_data_generator.put_default_adverse_action_record_in_provider_table( + value_overrides={'actionAgainst': 'license'} + ) + + message = self._generate_license_encumbrance_message() + event = self._create_sqs_event(message) + + # Execute the handler + license_encumbrance_listener(event, self.mock_context) + + # Verify privilege status remains unchanged + provider_records = self.config.data_client.get_provider_user_records( + compact=DEFAULT_COMPACT, + provider_id=DEFAULT_PROVIDER_ID, + ) + + privileges = provider_records.get_privilege_records() + self.assertEqual(1, len(privileges)) + + serialized_privilege = privilege.serialize_to_database_record() + self.assertEqual(PrivilegeEncumberedStatusEnum.ENCUMBERED, privileges[0].encumberedStatus) + + privilege_update_records = self._provider_table.query( + Select='ALL_ATTRIBUTES', + KeyConditionExpression=Key('pk').eq(serialized_privilege['pk']) + & Key('sk').begins_with(f'{serialized_privilege["sk"]}UPDATE'), + ) + + self.assertEqual(1, len(privilege_update_records['Items'])) + update_record = privilege_update_records['Items'][0] + update_encumbrance_details = update_record['encumbranceDetails'] + self.assertEqual( + { + 'adverseActionId': DEFAULT_ADVERSE_ACTION_ID, + 'licenseJurisdiction': 'oh', + 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], + }, + update_encumbrance_details, + ) + + # Verify one event was published for the privilege update + mock_publish_event.assert_called_once() + + # TODO - remove this test when flag is removed # noqa: FIX002 + @patch('cc_common.event_bus_client.EventBusClient._publish_event') + @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=False) + def test_license_encumbrance_listener_handles_all_privileges_already_encumbered_with_experiment_disabled( + self, + mock_flag, + mock_publish_event, # noqa: ARG002 + ): + """Test that license encumbrance event handles case where all matching privileges are already encumbered.""" + from cc_common.data_model.schema.common import PrivilegeEncumberedStatusEnum + from handlers.encumbrance_events import license_encumbrance_listener + + # Set up test data + self.test_data_generator.put_default_provider_record_in_provider_table() + + # Create privileges that are already encumbered + privilege = self.test_data_generator.put_default_privilege_record_in_provider_table( + value_overrides={ + 'licenseJurisdiction': DEFAULT_LICENSE_JURISDICTION, + 'licenseTypeAbbreviation': DEFAULT_LICENSE_TYPE_ABBREVIATION, + 'encumberedStatus': 'encumbered', + } + ) + + # add adverse action item for license + self.test_data_generator.put_default_adverse_action_record_in_provider_table( + value_overrides={'actionAgainst': 'license'} + ) + message = self._generate_license_encumbrance_message() event = self._create_sqs_event(message) @@ -254,6 +338,10 @@ def test_license_encumbrance_listener_creates_privilege_update_records(self): # Set up test data self.test_data_generator.put_default_provider_record_in_provider_table() privilege = self.test_data_generator.put_default_privilege_record_in_provider_table() + # add adverse action item for license + self.test_data_generator.put_default_adverse_action_record_in_provider_table( + value_overrides={'actionAgainst': 'license'} + ) message = self._generate_license_encumbrance_message() event = self._create_sqs_event(message) @@ -493,6 +581,11 @@ def test_license_encumbrance_listener_handles_multiple_matching_privileges(self, } ) + # add adverse action item for license + self.test_data_generator.put_default_adverse_action_record_in_provider_table( + value_overrides={'actionAgainst': 'license'} + ) + message = self._generate_license_encumbrance_message() event = self._create_sqs_event(message) @@ -634,6 +727,11 @@ def test_license_encumbrance_listener_handles_mixed_license_types(self): } ) + # add adverse action item for license + self.test_data_generator.put_default_adverse_action_record_in_provider_table( + value_overrides={'actionAgainst': 'license'} + ) + message = self._generate_license_encumbrance_message() event = self._create_sqs_event(message) @@ -683,6 +781,11 @@ def test_license_encumbrance_listener_handles_mixed_license_jurisdictions(self): } ) + # add adverse action item for license + self.test_data_generator.put_default_adverse_action_record_in_provider_table( + value_overrides={'actionAgainst': 'license'} + ) + message = self._generate_license_encumbrance_message() event = self._create_sqs_event(message) diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py index 3d23cb245..3b2b14609 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py @@ -102,6 +102,7 @@ def _generate_adverse_action_for_record_type( adverse_action.licenseType = license_type.name adverse_action.actionAgainst = adverse_action_against_record_type adverse_action.encumbranceType = EncumbranceType(adverse_action_request['encumbranceType']) + # TODO - remove the if condition as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 if 'clinicalPrivilegeActionCategory' in adverse_action_request: # replicate data to both the deprecated and new fields adverse_action.clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategory( diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py index 39547ee6c..2c52d5d21 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py @@ -133,7 +133,8 @@ def test_privilege_encumbrance_handler_adds_adverse_action_record_in_provider_da loaded_adverse_action.to_dict(), ) - def test_privilege_encumbrance_handler_adds_privilege_update_record_in_provider_data_table(self): + @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=True) + def test_privilege_encumbrance_handler_adds_privilege_update_record_in_provider_data_table(self, mock_flag): # noqa: ARG002 from cc_common.data_model.schema.privilege import PrivilegeUpdateData from handlers.encumbrance import encumbrance_handler @@ -175,6 +176,53 @@ def test_privilege_encumbrance_handler_adds_privilege_update_record_in_provider_ ) self.assertEqual({'encumberedStatus': 'encumbered'}, loaded_privilege_update_data.updatedValues) + # TODO - remove the test as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=False) + def test_privilege_encumbrance_handler_adds_privilege_update_record_in_provider_data_table_flag_off( + self, + mock_flag, # noqa: ARG002 + ): + from cc_common.data_model.schema.privilege import PrivilegeUpdateData + from handlers.encumbrance import encumbrance_handler + + event, test_privilege_record = self._when_testing_privilege_encumbrance() + + response = encumbrance_handler(event, self.mock_context) + self.assertEqual(200, response['statusCode'], msg=json.loads(response['body'])) + + # Verify that the encumbrance record was added to the provider data table + # Perform a query to list all encumbrances for the provider using the starts_with key condition + privilege_update_records = self._provider_table.query( + Select='ALL_ATTRIBUTES', + KeyConditionExpression=Key('pk').eq(test_privilege_record.serialize_to_database_record()['pk']) + & Key('sk').begins_with( + f'{test_privilege_record.compact}#PROVIDER#privilege/{test_privilege_record.jurisdiction}/slp#UPDATE' + ), + ) + self.assertEqual(1, len(privilege_update_records['Items'])) + item = privilege_update_records['Items'][0] + + loaded_privilege_update_data = PrivilegeUpdateData.from_database_record(item) + + expected_privilege_update_data = self.test_data_generator.generate_default_privilege_update( + value_overrides={ + 'updateType': 'encumbrance', + 'updatedValues': {'encumberedStatus': 'encumbered'}, + 'effectiveDate': datetime.fromisoformat(TEST_ENCUMBRANCE_EFFECTIVE_DATETIME), + 'createDate': datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP), + 'encumbranceDetails': { + 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', + 'adverseActionId': loaded_privilege_update_data.encumbranceDetails['adverseActionId'], + }, + } + ) + + self.assertEqual( + expected_privilege_update_data.to_dict(), + loaded_privilege_update_data.to_dict(), + ) + self.assertEqual({'encumberedStatus': 'encumbered'}, loaded_privilege_update_data.updatedValues) + def test_privilege_encumbrance_handler_sets_privilege_record_to_inactive_in_provider_data_table(self): from cc_common.data_model.schema.common import PrivilegeEncumberedStatusEnum from cc_common.data_model.schema.privilege import PrivilegeData @@ -370,6 +418,7 @@ def test_privilege_encumbrance_handler_returns_400_if_both_category_fields_provi @mock_aws +@patch('cc_common.feature_flag_client.is_feature_enabled', True) @patch('cc_common.config._Config.current_standard_datetime', datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP)) class TestPostLicenseEncumbrance(TstFunction): """Test suite for license encumbrance endpoints.""" diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_privilege_history.py b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_privilege_history.py index a0ac2315d..ce926f7ac 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_privilege_history.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_privilege_history.py @@ -80,7 +80,7 @@ def _when_testing_staff_endpoint(self): value_overrides={ 'updateType': 'encumbrance', 'encumbranceDetails': { - 'clinicalPrivilegeActionCategory': 'Non-compliance With Requirements', + 'clinicalPrivilegeActionCategories': ['Non-compliance With Requirements', 'Misconduct or Abuse'], 'licenseJurisdiction': 'oh', 'adverseActionId': DEFAULT_ADVERSE_ACTION_ID, }, @@ -222,7 +222,9 @@ def test_get_privilege_history_public_returns_expected_history(self): self.assertEqual(expected_history, history_data) - def test_get_privilege_history_staff_returns_expected_history(self): + # TODO - remove the mock flag as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=True) + def test_get_privilege_history_staff_returns_expected_history(self, mock_flag): # noqa: ARG002 from handlers.privilege_history import privilege_history_handler event = self._when_testing_staff_endpoint() @@ -255,7 +257,7 @@ def test_get_privilege_history_staff_returns_expected_history(self): 'effectiveDate': '2022-05-05T12:59:59+00:00', 'type': 'privilegeUpdate', 'updateType': 'encumbrance', - 'note': 'Non-compliance With Requirements', + 'note': 'Non-compliance With Requirements, Misconduct or Abuse', }, ], 'jurisdiction': 'ne', diff --git a/backend/compact-connect/stacks/feature_flag_stack/__init__.py b/backend/compact-connect/stacks/feature_flag_stack/__init__.py index 348dc4708..301d9536d 100644 --- a/backend/compact-connect/stacks/feature_flag_stack/__init__.py +++ b/backend/compact-connect/stacks/feature_flag_stack/__init__.py @@ -113,6 +113,17 @@ def __init__( environment_name=environment_name, ) + self.encumbrance_multiple_category_flag = FeatureFlagResource( + self, + 'EncumbranceMultiCategoryFlag', + provider=self.provider, + flag_name='encumbrance-multi-category-flag', + auto_enable_envs=[ + FeatureFlagEnvironmentName.TEST, + ], + environment_name=environment_name, + ) + def _create_common_provider(self, environment_name: str) -> Provider: # Create shared Lambda function for managing all feature flags # This function is reused across all FeatureFlagResource instances From deeed86b39a9ff14d26ff4b42729ef01759d1e6e Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Fri, 10 Oct 2025 10:42:52 -0500 Subject: [PATCH 13/26] Add feature flag for gating new behavior on POST --- .../provider-data-v1/handlers/encumbrance.py | 22 ++++++++++++------- .../test_handlers/test_encumbrance.py | 6 +++-- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py index 3b2b14609..bc2d72930 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py @@ -102,17 +102,23 @@ def _generate_adverse_action_for_record_type( adverse_action.licenseType = license_type.name adverse_action.actionAgainst = adverse_action_against_record_type adverse_action.encumbranceType = EncumbranceType(adverse_action_request['encumbranceType']) - # TODO - remove the if condition as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 - if 'clinicalPrivilegeActionCategory' in adverse_action_request: - # replicate data to both the deprecated and new fields + # TODO - remove the flag conditions as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + from cc_common.feature_flag_client import is_feature_enabled + if is_feature_enabled('encumbrance-multi-category-flag'): + if 'clinicalPrivilegeActionCategory' in adverse_action_request: + # replicate data to both the deprecated and new fields + adverse_action.clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategory( + adverse_action_request['clinicalPrivilegeActionCategory'] + ) + adverse_action.clinicalPrivilegeActionCategories = [ + ClinicalPrivilegeActionCategory(adverse_action_request['clinicalPrivilegeActionCategory']) + ] + else: + adverse_action.clinicalPrivilegeActionCategories = adverse_action_request['clinicalPrivilegeActionCategories'] + else: adverse_action.clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategory( adverse_action_request['clinicalPrivilegeActionCategory'] ) - adverse_action.clinicalPrivilegeActionCategories = [ - ClinicalPrivilegeActionCategory(adverse_action_request['clinicalPrivilegeActionCategory']) - ] - else: - adverse_action.clinicalPrivilegeActionCategories = adverse_action_request['clinicalPrivilegeActionCategories'] adverse_action.effectiveStartDate = encumbrance_effective_date adverse_action.submittingUser = _get_submitting_user_id(event) adverse_action.creationDate = config.current_standard_datetime diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py index 2c52d5d21..4c2d4c627 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py @@ -1,6 +1,6 @@ import json from datetime import UTC, date, datetime, timedelta -from unittest.mock import patch +from unittest.mock import patch, MagicMock from boto3.dynamodb.conditions import Key from cc_common.exceptions import CCInternalException @@ -416,9 +416,11 @@ def test_privilege_encumbrance_handler_returns_400_if_both_category_fields_provi response_body['message'], ) +mock_flag_client = MagicMock() +mock_flag_client.return_value = True @mock_aws -@patch('cc_common.feature_flag_client.is_feature_enabled', True) +@patch('cc_common.feature_flag_client.is_feature_enabled', mock_flag_client) @patch('cc_common.config._Config.current_standard_datetime', datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP)) class TestPostLicenseEncumbrance(TstFunction): """Test suite for license encumbrance endpoints.""" From f9397f47ff872d27b57fc15e0912d0adba73cb6b Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Mon, 13 Oct 2025 08:57:53 -0500 Subject: [PATCH 14/26] Add encumbrance type to smoke test requests --- .../tests/smoke/encumbrance_smoke_tests.py | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py b/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py index 0542ab7ef..9bc776be7 100644 --- a/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py +++ b/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py @@ -318,6 +318,7 @@ def validate_privilege_encumbered_state( f'"{self.license_jurisdiction}" and license type "{self.license_type}"' ) else: + logger.info('matching privilege found', matching_privilege=matching_privilege) actual_status = matching_privilege.get('encumberedStatus') logger.info( f'Attempt {attempts}/{max_attempts}: Privilege encumberedStatus is "{actual_status}", ' @@ -461,6 +462,7 @@ def test_license_encumbrance_workflow(): encumbrance_body = { 'encumbranceEffectiveDate': '2024-11-11', + 'encumbranceType': 'surrender of license', 'clinicalPrivilegeActionCategories': ['Fraud, Deception, or Misrepresentation'], } @@ -518,6 +520,7 @@ def test_license_encumbrance_workflow(): # Second encumbrance second_encumbrance_body = { 'encumbranceEffectiveDate': '2025-01-01', + 'encumbranceType': 'denial', 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], } helper.encumber_license(second_encumbrance_body) @@ -537,7 +540,8 @@ def test_license_encumbrance_workflow(): # Step 3: Encumber Privilege privilege_encumbrance_body = { 'encumbranceEffectiveDate': '2025-05-09', - 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], + 'encumbranceType': 'reprimand', + 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care', 'Misconduct or Abuse'], } helper.encumber_privilege(privilege_encumbrance_body) @@ -653,6 +657,7 @@ def test_privilege_encumbrance_workflow(): encumbrance_body = { 'encumbranceEffectiveDate': '2024-12-12', + 'encumbranceType': 'fine', 'clinicalPrivilegeActionCategories': ['Fraud, Deception, or Misrepresentation'], } @@ -684,6 +689,7 @@ def test_privilege_encumbrance_workflow(): # Second encumbrance second_encumbrance_body = { 'encumbranceEffectiveDate': '2025-02-02', + 'encumbranceType': 'completion of continuing education', 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], } helper.encumber_privilege(second_encumbrance_body) @@ -768,7 +774,11 @@ def test_privilege_encumbrance_status_changes_with_license_encumbrance_workflow( logger.info('Step 1: Creating privilege encumbrance...') privilege_encumbrance_body = { 'encumbranceEffectiveDate': '2024-01-15', - 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], + 'encumbranceType': 'probation', + 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care', + 'Non-compliance With Requirements', + 'Fraud, Deception, or Misrepresentation' + ], } helper.encumber_privilege(privilege_encumbrance_body) @@ -787,7 +797,12 @@ def test_privilege_encumbrance_status_changes_with_license_encumbrance_workflow( logger.info('Step 2: Creating license encumbrance...') license_encumbrance_body = { 'encumbranceEffectiveDate': '2024-01-20', - 'clinicalPrivilegeActionCategories': ['Criminal Conviction or Adjudication'], + 'encumbranceType': 'suspension', + 'clinicalPrivilegeActionCategories': [ + 'Criminal Conviction or Adjudication', + 'Improper Supervision or Allowing Unlicensed Practice', + 'Other' + ], } helper.encumber_license(license_encumbrance_body) From aec1e50c19e86ef60b5733d3aee91096702045ae Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Tue, 14 Oct 2025 12:06:57 -0500 Subject: [PATCH 15/26] update smoke tests to check status from DB directly --- .../tests/smoke/encumbrance_smoke_tests.py | 175 ++++++++---------- .../tests/smoke/smoke_common.py | 17 ++ 2 files changed, 97 insertions(+), 95 deletions(-) diff --git a/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py b/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py index 9bc776be7..77815e390 100644 --- a/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py +++ b/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py @@ -19,6 +19,7 @@ get_all_provider_database_records, get_license_type_abbreviation, get_provider_user_dynamodb_table, + get_provider_user_records, get_staff_user_auth_headers, load_smoke_test_env, logger, @@ -89,25 +90,6 @@ def setup_test_environment(): logger.info('Test environment setup complete') -def _get_license_data_from_provider_response(provider_data: dict, jurisdiction: str, license_type: str): - return next( - ( - lic - for lic in provider_data['licenses'] - if lic['jurisdiction'] == jurisdiction and lic['licenseType'] == license_type - ), - None, - ) - - -def _get_privilege_data_from_provider_response(provider_data: dict, jurisdiction: str): - privileges = provider_data.get('privileges', []) - if not privileges: - raise SmokeTestFailureException('No privileges found for provider') - - return next((privilege for privilege in privileges if privilege['jurisdiction'] == jurisdiction), None) - - class EncumbranceTestHelper: """Helper class to manage encumbrance test operations with pre-configured staff users and URLs.""" @@ -122,14 +104,22 @@ def __init__(self, provider_data: dict): self.provider_id = provider_data['providerId'] # Get jurisdiction information from Nebraska privilege (smoke tests purchase privilege in NE) - privilege_record = _get_privilege_data_from_provider_response(provider_data, jurisdiction='ne') - if not privilege_record: + # Query database directly for privilege records + provider_user_records = get_provider_user_records(self.compact, self.provider_id) + + # Find the Nebraska privilege + ne_privileges = provider_user_records.get_privilege_records( + filter_condition=lambda priv: priv.jurisdiction == 'ne' + ) + + if not ne_privileges: raise SmokeTestFailureException('Nebraska privilege not found for provider') - - self.privilege_jurisdiction = privilege_record['jurisdiction'] - self.license_jurisdiction = privilege_record['licenseJurisdiction'] - self.license_type = privilege_record['licenseType'] - self.license_type_abbreviation = get_license_type_abbreviation(self.license_type) + + privilege_record = ne_privileges[0] + self.privilege_jurisdiction = privilege_record.jurisdiction + self.license_jurisdiction = privilege_record.licenseJurisdiction + self.license_type = privilege_record.licenseType + self.license_type_abbreviation = privilege_record.licenseTypeAbbreviation # Track created users for cleanup self.created_staff_users = [] @@ -250,21 +240,24 @@ def _call_privilege_encumbrance_endpoint(self, request_body: dict, encumbrance_i def validate_license_encumbered_state(self, expected_status: str = 'encumbered'): """Validate license encumbered status and related fields.""" - provider_data = call_provider_users_me_endpoint() - updated_license = _get_license_data_from_provider_response( - provider_data, self.license_jurisdiction, self.license_type + # Get all provider records directly from DynamoDB + provider_user_records = get_provider_user_records(self.compact, self.provider_id) + + # Get the specific license record + license_record = provider_user_records.get_specific_license_record( + self.license_jurisdiction, self.license_type_abbreviation ) - if not updated_license: + if not license_record: raise SmokeTestFailureException('License not found after encumbrance operation') - actual_status = updated_license.get('encumberedStatus') + actual_status = license_record.encumberedStatus if actual_status != expected_status: raise SmokeTestFailureException( f"License encumberedStatus should be '{expected_status}', got: {actual_status}" ) - return updated_license + return license_record def validate_privilege_encumbered_state( self, expected_status: str = 'encumbered', max_wait_time: int = 60, check_interval: int = 10 @@ -272,7 +265,7 @@ def validate_privilege_encumbered_state( """ Validate that the privilege encumberedStatus matches the expected value. - This method will poll the provider me endpoint every check_interval seconds + This method will poll the provider records every check_interval seconds for up to max_wait_time seconds, checking if the privilege has the expected encumberedStatus. This accounts for eventual consistency in downstream processing. @@ -296,30 +289,22 @@ def validate_privilege_encumbered_state( attempts += 1 try: - # Get current provider data - provider_data = call_provider_users_me_endpoint() + # Get current provider records directly from DynamoDB + provider_user_records = get_provider_user_records(self.compact, self.provider_id) # Find the privilege that matches the license jurisdiction and type - privileges = provider_data.get('privileges', []) - matching_privilege = None - - for privilege in privileges: - # Match by license jurisdiction and license type - if ( - privilege.get('licenseJurisdiction') == self.license_jurisdiction - and privilege.get('licenseType') == self.license_type - ): - matching_privilege = privilege - break + matching_privilege = provider_user_records.get_specific_privilege_record( + self.privilege_jurisdiction, self.license_type_abbreviation + ) if not matching_privilege: logger.warning( - f'Attempt {attempts}/{max_attempts}: No privilege found matching license jurisdiction ' - f'"{self.license_jurisdiction}" and license type "{self.license_type}"' + f'Attempt {attempts}/{max_attempts}: No privilege found matching jurisdiction ' + f'"{self.privilege_jurisdiction}" and license type "{self.license_type_abbreviation}"' ) else: logger.info('matching privilege found', matching_privilege=matching_privilege) - actual_status = matching_privilege.get('encumberedStatus') + actual_status = matching_privilege.encumberedStatus logger.info( f'Attempt {attempts}/{max_attempts}: Privilege encumberedStatus is "{actual_status}", ' f'expecting "{expected_status}"' @@ -352,43 +337,40 @@ def validate_privilege_encumbered_state( def validate_provider_encumbered_state(self, expected_status: str = 'encumbered'): """Validate provider encumbered status.""" - provider_data = call_provider_users_me_endpoint() - if provider_data.get('encumberedStatus') != expected_status: + # Get all provider records directly from DynamoDB + provider_user_records = get_provider_user_records(self.compact, self.provider_id) + provider_record = provider_user_records.get_provider_record() + + if provider_record.encumberedStatus != expected_status: raise SmokeTestFailureException( - f"Provider encumberedStatus should be '{expected_status}', got: {provider_data.get('encumberedStatus')}" + f"Provider encumberedStatus should be '{expected_status}', got: {provider_record.encumberedStatus}" ) def get_license_adverse_actions(self): """Get all license adverse actions for this provider.""" - provider_data = call_provider_users_me_endpoint() - updated_license = _get_license_data_from_provider_response( - provider_data, self.license_jurisdiction, self.license_type + # Get all provider records directly from DynamoDB + provider_user_records = get_provider_user_records(self.compact, self.provider_id) + + # Get adverse actions for this specific license + adverse_actions = provider_user_records.get_adverse_action_records_for_license( + self.license_jurisdiction, self.license_type_abbreviation ) - - if not updated_license: - return [] - - adverse_actions = updated_license.get('adverseActions', []) - return [ - aa - for aa in adverse_actions - if aa.get('actionAgainst') == 'license' and aa.get('jurisdiction') == self.license_jurisdiction - ] + + # Convert to dict format for compatibility with existing code + return [aa.to_dict() for aa in adverse_actions] def get_privilege_adverse_actions(self): """Get all privilege adverse actions for this provider.""" - provider_data = call_provider_users_me_endpoint() - updated_privilege = _get_privilege_data_from_provider_response(provider_data, self.privilege_jurisdiction) - - if not updated_privilege: - return [] - - adverse_actions = updated_privilege.get('adverseActions', []) - return [ - aa - for aa in adverse_actions - if aa.get('actionAgainst') == 'privilege' and aa.get('jurisdiction') == self.privilege_jurisdiction - ] + # Get all provider records directly from DynamoDB + provider_user_records = get_provider_user_records(self.compact, self.provider_id) + + # Get adverse actions for this specific privilege + adverse_actions = provider_user_records.get_adverse_action_records_for_privilege( + self.privilege_jurisdiction, self.license_type_abbreviation + ) + + # Convert to dict format for compatibility with existing code + return [aa.to_dict() for aa in adverse_actions] def _generate_license_encumbrance_url(self, encumbrance_id: str = None): """Generate license encumbrance URL.""" @@ -471,37 +453,38 @@ def test_license_encumbrance_workflow(): logger.info('First license encumbrance created successfully') # Verify provider state after first encumbrance - provider_data = call_provider_users_me_endpoint() - updated_license = _get_license_data_from_provider_response( - provider_data, helper.license_jurisdiction, helper.license_type + provider_user_records = get_provider_user_records(helper.compact, helper.provider_id) + updated_license = provider_user_records.get_specific_license_record( + helper.license_jurisdiction, helper.license_type_abbreviation ) if not updated_license: raise SmokeTestFailureException('License not found after encumbrance') - if updated_license.get('encumberedStatus') != 'encumbered': + if updated_license.encumberedStatus != 'encumbered': raise SmokeTestFailureException( - f"License encumberedStatus should be 'encumbered', got: {updated_license.get('encumberedStatus')}" + f"License encumberedStatus should be 'encumbered', got: {updated_license.encumberedStatus}" ) - if updated_license.get('compactEligibility') != 'ineligible': + if updated_license.compactEligibility != 'ineligible': raise SmokeTestFailureException( - f"License compactEligibility should be 'ineligible', got: {updated_license.get('compactEligibility')}" + f"License compactEligibility should be 'ineligible', got: {updated_license.compactEligibility}" ) - if updated_license.get('licenseStatus') != 'inactive': + if updated_license.licenseStatus != 'inactive': raise SmokeTestFailureException( - f"License licenseStatus should be 'inactive', got: {updated_license.get('licenseStatus')}" + f"License licenseStatus should be 'inactive', got: {updated_license.licenseStatus}" ) # Check provider status - if provider_data.get('encumberedStatus') != 'encumbered': + provider_record = provider_user_records.get_provider_record() + if provider_record.encumberedStatus != 'encumbered': raise SmokeTestFailureException( - f"Provider encumberedStatus should be 'encumbered', got: {provider_data.get('encumberedStatus')}" + f"Provider encumberedStatus should be 'encumbered', got: {provider_record.encumberedStatus}" ) - if provider_data.get('compactEligibility') != 'ineligible': + if provider_record.compactEligibility != 'ineligible': raise SmokeTestFailureException( - f"Provider compactEligibility should be 'ineligible', got: {provider_data.get('compactEligibility')}" + f"Provider compactEligibility should be 'ineligible', got: {provider_record.compactEligibility}" ) # Verify adverse action exists @@ -868,15 +851,17 @@ def test_privilege_encumbrance_status_changes_with_license_encumbrance_workflow( logger.info('Verified privilege is now fully unencumbered') # Final verification: Check that provider is also unencumbered - provider_data = call_provider_users_me_endpoint() - if provider_data.get('encumberedStatus') != 'unencumbered': + provider_user_records = get_provider_user_records(helper.compact, helper.provider_id) + provider_record = provider_user_records.get_provider_record() + + if provider_record.encumberedStatus != 'unencumbered': raise SmokeTestFailureException( - f"Provider encumberedStatus should be 'unencumbered', got: {provider_data.get('encumberedStatus')}" + f"Provider encumberedStatus should be 'unencumbered', got: {provider_record.encumberedStatus}" ) - if provider_data.get('compactEligibility') != 'eligible': + if provider_record.compactEligibility != 'eligible': raise SmokeTestFailureException( - f"Provider compactEligibility should be 'eligible', got: {provider_data.get('compactEligibility')}" + f"Provider compactEligibility should be 'eligible', got: {provider_record.compactEligibility}" ) logger.info('Complex privilege and license encumbrance workflow test completed successfully') diff --git a/backend/compact-connect/tests/smoke/smoke_common.py b/backend/compact-connect/tests/smoke/smoke_common.py index 05be5b55c..622bc2a29 100644 --- a/backend/compact-connect/tests/smoke/smoke_common.py +++ b/backend/compact-connect/tests/smoke/smoke_common.py @@ -33,6 +33,7 @@ def __init__(self, message): # We have to import this after we've added the common lib to our path and environment from cc_common.data_model.schema.user.record import UserRecordSchema # noqa: E402 +from cc_common.data_model.provider_record_util import ProviderUserRecords _TEST_STAFF_USER_PASSWORD = 'TestPass123!' # noqa: S105 test credential for test staff user _TEMP_STAFF_PASSWORD = 'TempPass123!' # noqa: S105 temporary password for creating test staff users @@ -246,6 +247,22 @@ def get_all_provider_database_records(): return query_result['Items'] +def get_provider_user_records(compact: str, provider_id: str) -> ProviderUserRecords: + """ + Get all provider records from DynamoDB and return as ProviderUserRecords utility class. + + :param compact: The compact identifier + :param provider_id: The provider's ID + :return: ProviderUserRecords instance containing all records for this provider + """ + # Query the provider database for all records + query_result = config.provider_user_dynamodb_table.query( + KeyConditionExpression=Key('pk').eq(f'{compact}#PROVIDER#{provider_id}') + ) + + return ProviderUserRecords(query_result['Items']) + + def upload_license_record(staff_headers: dict, compact: str, jurisdiction: str, data_overrides: dict = None): """Upload a license record using the API with default test data that can be overridden. From 77bf06e1f34d3f775898691518885a01c304c6e3 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 15 Oct 2025 09:26:27 -0500 Subject: [PATCH 16/26] Add env var for feature flag client --- .../compact-connect/stacks/event_listener_stack/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/compact-connect/stacks/event_listener_stack/__init__.py b/backend/compact-connect/stacks/event_listener_stack/__init__.py index f0f006aa8..a47edc3a8 100644 --- a/backend/compact-connect/stacks/event_listener_stack/__init__.py +++ b/backend/compact-connect/stacks/event_listener_stack/__init__.py @@ -35,6 +35,11 @@ def __init__( ): super().__init__(scope, construct_id, environment_name=environment_name, **kwargs) data_event_bus = SSMParameterUtility.load_data_event_bus_from_ssm_parameter(self) + # we only pass the API_BASE_URL env var if the API_DOMAIN_NAME is set + # this is because the API_BASE_URL is used by the feature flag client to call the flag check endpoint + if persistent_stack.api_domain_name: + self.common_env_vars.update({'API_BASE_URL': f'https://{persistent_stack.api_domain_name}'}) + self.event_processors = {} self._add_license_encumbrance_listener(persistent_stack, data_event_bus) self._add_lifting_license_encumbrance_listener(persistent_stack, data_event_bus) From 139204a8813d084106c7f905ef7145dc8a1099b5 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 15 Oct 2025 09:27:04 -0500 Subject: [PATCH 17/26] Update smoke tests to check for matching adverse action record --- .../tests/smoke/encumbrance_smoke_tests.py | 113 +++++++++++++++--- .../tests/smoke/smoke_common.py | 3 +- 2 files changed, 100 insertions(+), 16 deletions(-) diff --git a/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py b/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py index 77815e390..41197cf1c 100644 --- a/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py +++ b/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py @@ -106,15 +106,15 @@ def __init__(self, provider_data: dict): # Get jurisdiction information from Nebraska privilege (smoke tests purchase privilege in NE) # Query database directly for privilege records provider_user_records = get_provider_user_records(self.compact, self.provider_id) - + # Find the Nebraska privilege ne_privileges = provider_user_records.get_privilege_records( filter_condition=lambda priv: priv.jurisdiction == 'ne' ) - + if not ne_privileges: raise SmokeTestFailureException('Nebraska privilege not found for provider') - + privilege_record = ne_privileges[0] self.privilege_jurisdiction = privilege_record.jurisdiction self.license_jurisdiction = privilege_record.licenseJurisdiction @@ -242,7 +242,7 @@ def validate_license_encumbered_state(self, expected_status: str = 'encumbered') """Validate license encumbered status and related fields.""" # Get all provider records directly from DynamoDB provider_user_records = get_provider_user_records(self.compact, self.provider_id) - + # Get the specific license record license_record = provider_user_records.get_specific_license_record( self.license_jurisdiction, self.license_type_abbreviation @@ -340,7 +340,7 @@ def validate_provider_encumbered_state(self, expected_status: str = 'encumbered' # Get all provider records directly from DynamoDB provider_user_records = get_provider_user_records(self.compact, self.provider_id) provider_record = provider_user_records.get_provider_record() - + if provider_record.encumberedStatus != expected_status: raise SmokeTestFailureException( f"Provider encumberedStatus should be '{expected_status}', got: {provider_record.encumberedStatus}" @@ -350,12 +350,12 @@ def get_license_adverse_actions(self): """Get all license adverse actions for this provider.""" # Get all provider records directly from DynamoDB provider_user_records = get_provider_user_records(self.compact, self.provider_id) - + # Get adverse actions for this specific license adverse_actions = provider_user_records.get_adverse_action_records_for_license( self.license_jurisdiction, self.license_type_abbreviation ) - + # Convert to dict format for compatibility with existing code return [aa.to_dict() for aa in adverse_actions] @@ -363,15 +363,73 @@ def get_privilege_adverse_actions(self): """Get all privilege adverse actions for this provider.""" # Get all provider records directly from DynamoDB provider_user_records = get_provider_user_records(self.compact, self.provider_id) - + # Get adverse actions for this specific privilege adverse_actions = provider_user_records.get_adverse_action_records_for_privilege( self.privilege_jurisdiction, self.license_type_abbreviation ) - + # Convert to dict format for compatibility with existing code return [aa.to_dict() for aa in adverse_actions] + @staticmethod + def verify_adverse_action_matches_request(adverse_actions: list[dict], request_payload: dict) -> dict: + """ + Verify that at least one adverse action matches the request payload. + + :param adverse_actions: List of adverse action records + :param request_payload: The request payload that was sent (containing encumbranceType and + clinicalPrivilegeActionCategories) + :return: The matching adverse action record + :raises SmokeTestFailureException: If no matching adverse action is found + """ + expected_encumbrance_type = request_payload.get('encumbranceType') + expected_categories = set(request_payload.get('clinicalPrivilegeActionCategories', [])) + + logger.info( + f'Verifying adverse action matches request: encumbranceType={expected_encumbrance_type}, ' + f'categories={expected_categories}' + ) + + matching_actions = [] + for adverse_action in adverse_actions: + action_type = adverse_action.get('encumbranceType') + action_categories = set(adverse_action.get('clinicalPrivilegeActionCategories', [])) + + if action_type == expected_encumbrance_type and action_categories == expected_categories: + matching_actions.append(adverse_action) + + if not matching_actions: + raise SmokeTestFailureException( + f'No adverse action found matching request payload. ' + f'Expected encumbranceType="{expected_encumbrance_type}" and ' + f'categories={expected_categories}. ' + f'Found adverse actions: {adverse_actions}' + ) + + logger.info(f'✅ Found {len(matching_actions)} matching adverse action(s)') + return matching_actions[0] + + def verify_license_adverse_action_matches_request(self, request_payload: dict) -> dict: + """ + Verify that a license adverse action matches the request payload. + + :param request_payload: The request payload that was sent + :return: The matching adverse action record + """ + license_adverse_actions = self.get_license_adverse_actions() + return self.verify_adverse_action_matches_request(license_adverse_actions, request_payload) + + def verify_privilege_adverse_action_matches_request(self, request_payload: dict) -> dict: + """ + Verify that a privilege adverse action matches the request payload. + + :param request_payload: The request payload that was sent + :return: The matching adverse action record + """ + privilege_adverse_actions = self.get_privilege_adverse_actions() + return self.verify_adverse_action_matches_request(privilege_adverse_actions, request_payload) + def _generate_license_encumbrance_url(self, encumbrance_id: str = None): """Generate license encumbrance URL.""" base_url = ( @@ -493,6 +551,9 @@ def test_license_encumbrance_workflow(): raise SmokeTestFailureException(f'Expected 1 license adverse action, found: {len(license_adverse_actions)}') first_adverse_action_id = license_adverse_actions[0]['adverseActionId'] + + # Verify the adverse action matches the request payload + helper.verify_license_adverse_action_matches_request(encumbrance_body) logger.info('First license encumbrance verified successfully') # Step 2: Verify that the associated privilege is also encumbered with 'licenseEncumbered' status @@ -520,6 +581,10 @@ def test_license_encumbrance_workflow(): aa['adverseActionId'] for aa in license_adverse_actions if aa['adverseActionId'] != first_adverse_action_id ) + # Verify the second adverse action matches the request payload + helper.verify_license_adverse_action_matches_request(second_encumbrance_body) + logger.info('Second license encumbrance verified successfully') + # Step 3: Encumber Privilege privilege_encumbrance_body = { 'encumbranceEffectiveDate': '2025-05-09', @@ -538,6 +603,10 @@ def test_license_encumbrance_workflow(): check_interval=1, ) + # Verify the privilege adverse action matches the request payload + helper.verify_privilege_adverse_action_matches_request(privilege_encumbrance_body) + logger.info('Privilege encumbrance verified successfully') + # Step 4: Lift first encumbrance (license should remain encumbered) logger.info('Step 4: Lifting first license encumbrance...') @@ -667,6 +736,9 @@ def test_privilege_encumbrance_workflow(): ) first_adverse_action_id = privilege_adverse_actions[0]['adverseActionId'] + + # Verify the adverse action matches the request payload + helper.verify_privilege_adverse_action_matches_request(encumbrance_body) logger.info('First privilege encumbrance verified successfully') # Second encumbrance @@ -691,6 +763,10 @@ def test_privilege_encumbrance_workflow(): if aa['adverseActionId'] != first_adverse_action_id ) + # Verify the second adverse action matches the request payload + helper.verify_privilege_adverse_action_matches_request(second_encumbrance_body) + logger.info('Second privilege encumbrance verified successfully') + # Step 2: Lift first encumbrance (privilege should remain encumbered) logger.info('Step 2: Lifting first privilege encumbrance...') @@ -758,10 +834,11 @@ def test_privilege_encumbrance_status_changes_with_license_encumbrance_workflow( privilege_encumbrance_body = { 'encumbranceEffectiveDate': '2024-01-15', 'encumbranceType': 'probation', - 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care', - 'Non-compliance With Requirements', - 'Fraud, Deception, or Misrepresentation' - ], + 'clinicalPrivilegeActionCategories': [ + 'Unsafe Practice or Substandard Care', + 'Non-compliance With Requirements', + 'Fraud, Deception, or Misrepresentation', + ], } helper.encumber_privilege(privilege_encumbrance_body) @@ -774,6 +851,9 @@ def test_privilege_encumbrance_status_changes_with_license_encumbrance_workflow( max_wait_time=1, check_interval=1, ) + + # Verify the privilege adverse action matches the request payload + helper.verify_privilege_adverse_action_matches_request(privilege_encumbrance_body) logger.info('Verified privilege is directly encumbered') # Step 2: Encumber the associated license @@ -784,13 +864,16 @@ def test_privilege_encumbrance_status_changes_with_license_encumbrance_workflow( 'clinicalPrivilegeActionCategories': [ 'Criminal Conviction or Adjudication', 'Improper Supervision or Allowing Unlicensed Practice', - 'Other' + 'Other', ], } helper.encumber_license(license_encumbrance_body) logger.info('License encumbrance created successfully') + # Verify the license adverse action matches the request payload + helper.verify_license_adverse_action_matches_request(license_encumbrance_body) + # wait 1 minute for downstream processing to complete # to ensure it doesn't change the privilege record helper.wait_for_downstream_processing() @@ -853,7 +936,7 @@ def test_privilege_encumbrance_status_changes_with_license_encumbrance_workflow( # Final verification: Check that provider is also unencumbered provider_user_records = get_provider_user_records(helper.compact, helper.provider_id) provider_record = provider_user_records.get_provider_record() - + if provider_record.encumberedStatus != 'unencumbered': raise SmokeTestFailureException( f"Provider encumberedStatus should be 'unencumbered', got: {provider_record.encumberedStatus}" diff --git a/backend/compact-connect/tests/smoke/smoke_common.py b/backend/compact-connect/tests/smoke/smoke_common.py index 622bc2a29..cd6399011 100644 --- a/backend/compact-connect/tests/smoke/smoke_common.py +++ b/backend/compact-connect/tests/smoke/smoke_common.py @@ -30,10 +30,11 @@ def __init__(self, message): os.environ['COMPACTS'] = json.dumps(COMPACTS) os.environ['JURISDICTIONS'] = json.dumps(JURISDICTIONS) +os.environ['LICENSE_TYPES'] = json.dumps(LICENSE_TYPES) # We have to import this after we've added the common lib to our path and environment -from cc_common.data_model.schema.user.record import UserRecordSchema # noqa: E402 from cc_common.data_model.provider_record_util import ProviderUserRecords +from cc_common.data_model.schema.user.record import UserRecordSchema # noqa: E402 _TEST_STAFF_USER_PASSWORD = 'TestPass123!' # noqa: S105 test credential for test staff user _TEMP_STAFF_PASSWORD = 'TempPass123!' # noqa: S105 temporary password for creating test staff users From edeec5b82be733d74e83191fa707bd19f869a225 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 15 Oct 2025 09:32:00 -0500 Subject: [PATCH 18/26] Formatting / linter --- .../data-events/tests/function/test_encumbrance_events.py | 4 ++-- .../lambdas/python/provider-data-v1/handlers/encumbrance.py | 5 ++++- .../tests/function/test_handlers/test_encumbrance.py | 4 +++- .../compact-connect/tests/smoke/encumbrance_smoke_tests.py | 1 - backend/compact-connect/tests/smoke/smoke_common.py | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py b/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py index 83ea743be..88f4d2fbd 100644 --- a/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py +++ b/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py @@ -268,8 +268,8 @@ def test_license_encumbrance_listener_handles_all_privileges_already_encumbered( @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=False) def test_license_encumbrance_listener_handles_all_privileges_already_encumbered_with_experiment_disabled( self, - mock_flag, - mock_publish_event, # noqa: ARG002 + mock_flag, # noqa: ARG002 + mock_publish_event, ): """Test that license encumbrance event handles case where all matching privileges are already encumbered.""" from cc_common.data_model.schema.common import PrivilegeEncumberedStatusEnum diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py index bc2d72930..2a394b04f 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py @@ -104,6 +104,7 @@ def _generate_adverse_action_for_record_type( adverse_action.encumbranceType = EncumbranceType(adverse_action_request['encumbranceType']) # TODO - remove the flag conditions as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 from cc_common.feature_flag_client import is_feature_enabled + if is_feature_enabled('encumbrance-multi-category-flag'): if 'clinicalPrivilegeActionCategory' in adverse_action_request: # replicate data to both the deprecated and new fields @@ -114,7 +115,9 @@ def _generate_adverse_action_for_record_type( ClinicalPrivilegeActionCategory(adverse_action_request['clinicalPrivilegeActionCategory']) ] else: - adverse_action.clinicalPrivilegeActionCategories = adverse_action_request['clinicalPrivilegeActionCategories'] + adverse_action.clinicalPrivilegeActionCategories = adverse_action_request[ + 'clinicalPrivilegeActionCategories' + ] else: adverse_action.clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategory( adverse_action_request['clinicalPrivilegeActionCategory'] diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py index 4c2d4c627..93cac9de6 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py @@ -1,6 +1,6 @@ import json from datetime import UTC, date, datetime, timedelta -from unittest.mock import patch, MagicMock +from unittest.mock import MagicMock, patch from boto3.dynamodb.conditions import Key from cc_common.exceptions import CCInternalException @@ -416,9 +416,11 @@ def test_privilege_encumbrance_handler_returns_400_if_both_category_fields_provi response_body['message'], ) + mock_flag_client = MagicMock() mock_flag_client.return_value = True + @mock_aws @patch('cc_common.feature_flag_client.is_feature_enabled', mock_flag_client) @patch('cc_common.config._Config.current_standard_datetime', datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP)) diff --git a/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py b/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py index 41197cf1c..2f4c0b946 100644 --- a/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py +++ b/backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py @@ -17,7 +17,6 @@ create_test_staff_user, delete_test_staff_user, get_all_provider_database_records, - get_license_type_abbreviation, get_provider_user_dynamodb_table, get_provider_user_records, get_staff_user_auth_headers, diff --git a/backend/compact-connect/tests/smoke/smoke_common.py b/backend/compact-connect/tests/smoke/smoke_common.py index cd6399011..9caded8c4 100644 --- a/backend/compact-connect/tests/smoke/smoke_common.py +++ b/backend/compact-connect/tests/smoke/smoke_common.py @@ -33,7 +33,7 @@ def __init__(self, message): os.environ['LICENSE_TYPES'] = json.dumps(LICENSE_TYPES) # We have to import this after we've added the common lib to our path and environment -from cc_common.data_model.provider_record_util import ProviderUserRecords +from cc_common.data_model.provider_record_util import ProviderUserRecords # noqa: E402 from cc_common.data_model.schema.user.record import UserRecordSchema # noqa: E402 _TEST_STAFF_USER_PASSWORD = 'TestPass123!' # noqa: S105 test credential for test staff user From 01fdebe9201d41078b4b45ccdcd48498cb79c3a0 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 15 Oct 2025 16:53:54 -0500 Subject: [PATCH 19/26] PR feedback - doc string fix --- .../lambdas/python/common/cc_common/data_model/data_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py index a4c3b5142..84483a716 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/data_client.py @@ -2628,7 +2628,7 @@ def encumber_home_jurisdiction_license_privileges( :param str jurisdiction: The jurisdiction of the license. :param adverse_action_id: The ID of the adverse action. :param str license_type_abbreviation: The license type abbreviation. - :param str effective_date: effective date of the encumbrance on the license and therefore privilege. + :param date effective_date: effective date of the encumbrance on the license and therefore privilege. :return: List of privileges that were encumbered """ # Get all provider records From 6d84880691abe7a1196e61b4d301377a7d3eadf1 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 15 Oct 2025 23:19:26 -0500 Subject: [PATCH 20/26] Update test defaults to only include new field --- .../common/common_test/test_data_generator.py | 2 +- .../test_schema/test_adverse_action.py | 3 +-- .../tests/function/test_encumbrance_events.py | 21 ++++++++++++++----- .../test_handlers/test_encumbrance.py | 10 +++++++-- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/backend/compact-connect/lambdas/python/common/common_test/test_data_generator.py b/backend/compact-connect/lambdas/python/common/common_test/test_data_generator.py index bd2c5f6a9..26283462e 100644 --- a/backend/compact-connect/lambdas/python/common/common_test/test_data_generator.py +++ b/backend/compact-connect/lambdas/python/common/common_test/test_data_generator.py @@ -139,7 +139,7 @@ def generate_default_adverse_action(value_overrides: dict | None = None) -> Adve 'licenseType': DEFAULT_LICENSE_TYPE, 'actionAgainst': DEFAULT_ACTION_AGAINST_PRIVILEGE, 'encumbranceType': DEFAULT_ENCUMBRANCE_TYPE, - 'clinicalPrivilegeActionCategory': DEFAULT_CLINICAL_PRIVILEGE_ACTION_CATEGORY, + 'clinicalPrivilegeActionCategories': [DEFAULT_CLINICAL_PRIVILEGE_ACTION_CATEGORY], 'effectiveStartDate': date.fromisoformat(DEFAULT_CREATION_EFFECTIVE_DATE), 'submittingUser': DEFAULT_AA_SUBMITTING_USER_ID, 'creationDate': datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP), diff --git a/backend/compact-connect/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py b/backend/compact-connect/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py index 52c725abb..b67a423ba 100644 --- a/backend/compact-connect/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py +++ b/backend/compact-connect/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py @@ -93,7 +93,7 @@ def test_adverse_action_data_class_getters_return_expected_values(self): self.assertEqual(adverse_action.licenseTypeAbbreviation, adverse_action_data['licenseTypeAbbreviation']) self.assertEqual(adverse_action.actionAgainst, adverse_action_data['actionAgainst']) self.assertEqual( - adverse_action.clinicalPrivilegeActionCategory, adverse_action_data['clinicalPrivilegeActionCategory'] + adverse_action.clinicalPrivilegeActionCategories, adverse_action_data['clinicalPrivilegeActionCategories'] ) self.assertEqual(adverse_action.effectiveStartDate.isoformat(), adverse_action_data['effectiveStartDate']) self.assertEqual(str(adverse_action.submittingUser), adverse_action_data['submittingUser']) @@ -112,7 +112,6 @@ def test_adverse_action_data_class_outputs_expected_database_object(self): 'adverseActionId': '98765432-9876-9876-9876-987654321098', 'encumbranceType': 'suspension', 'clinicalPrivilegeActionCategories': ['Unsafe Practice or Substandard Care'], - 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', 'compact': 'aslp', 'creationDate': '2024-11-08T23:59:59+00:00', 'effectiveStartDate': '2024-02-15', diff --git a/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py b/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py index 88f4d2fbd..aed5fbdd6 100644 --- a/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py +++ b/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py @@ -1,6 +1,6 @@ import json from datetime import date, datetime, time -from unittest.mock import patch +from unittest.mock import MagicMock, patch from uuid import UUID from boto3.dynamodb.conditions import Key @@ -20,8 +20,14 @@ from . import TstFunction +# TODO - remove the mock flag as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 +mock_feature_client = MagicMock() +mock_feature_client.return_value = True + @mock_aws +# TODO - remove the mock flag as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 +@patch('cc_common.feature_flag_client.is_feature_enabled', mock_feature_client) @patch('cc_common.config._Config.current_standard_datetime', datetime.fromisoformat(DEFAULT_DATE_OF_UPDATE_TIMESTAMP)) class TestEncumbranceEvents(TstFunction): """Test suite for license encumbrance event handlers.""" @@ -263,14 +269,13 @@ def test_license_encumbrance_listener_handles_all_privileges_already_encumbered( # Verify one event was published for the privilege update mock_publish_event.assert_called_once() - # TODO - remove this test when flag is removed # noqa: FIX002 + # TODO - remove this test as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 @patch('cc_common.event_bus_client.EventBusClient._publish_event') - @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=False) def test_license_encumbrance_listener_handles_all_privileges_already_encumbered_with_experiment_disabled( self, - mock_flag, # noqa: ARG002 mock_publish_event, ): + mock_feature_client.return_value = False """Test that license encumbrance event handles case where all matching privileges are already encumbered.""" from cc_common.data_model.schema.common import PrivilegeEncumberedStatusEnum from handlers.encumbrance_events import license_encumbrance_listener @@ -289,7 +294,10 @@ def test_license_encumbrance_listener_handles_all_privileges_already_encumbered_ # add adverse action item for license self.test_data_generator.put_default_adverse_action_record_in_provider_table( - value_overrides={'actionAgainst': 'license'} + value_overrides={ + 'actionAgainst': 'license', + 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', + } ) message = self._generate_license_encumbrance_message() @@ -331,6 +339,9 @@ def test_license_encumbrance_listener_handles_all_privileges_already_encumbered_ # Verify one event was published for the privilege update mock_publish_event.assert_called_once() + # reset the flag client for the other tests + mock_feature_client.return_value = True + def test_license_encumbrance_listener_creates_privilege_update_records(self): """Test that license encumbrance event creates appropriate privilege update records.""" from handlers.encumbrance_events import license_encumbrance_listener diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py index 93cac9de6..1185472d0 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py @@ -97,7 +97,8 @@ def test_privilege_encumbrance_handler_returns_ok_message_with_valid_body(self): response_body, ) - def test_privilege_encumbrance_handler_adds_adverse_action_record_in_provider_data_table(self): + @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=True) + def test_privilege_encumbrance_handler_adds_adverse_action_record_in_provider_data_table(self, mock_flag): # noqa: ARG002 from cc_common.data_model.schema.adverse_action import AdverseActionData from handlers.encumbrance import encumbrance_handler @@ -124,6 +125,8 @@ def test_privilege_encumbrance_handler_adds_adverse_action_record_in_provider_da 'encumbranceType': DEFAULT_ENCUMBRANCE_TYPE, 'effectiveStartDate': date.fromisoformat(TEST_ENCUMBRANCE_EFFECTIVE_DATE), 'jurisdiction': DEFAULT_PRIVILEGE_JURISDICTION, + # TODO - remove this as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', } ) loaded_adverse_action = AdverseActionData.from_database_record(item) @@ -470,7 +473,8 @@ def test_license_encumbrance_handler_returns_ok_message_with_valid_body(self): response_body, ) - def test_license_encumbrance_handler_adds_adverse_action_record_in_provider_data_table(self): + @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=True) + def test_license_encumbrance_handler_adds_adverse_action_record_in_provider_data_table(self, mock_flag): # noqa: ARG002 from cc_common.data_model.schema.adverse_action import AdverseActionData from handlers.encumbrance import encumbrance_handler @@ -498,6 +502,8 @@ def test_license_encumbrance_handler_adds_adverse_action_record_in_provider_data 'encumbranceType': DEFAULT_ENCUMBRANCE_TYPE, 'effectiveStartDate': date.fromisoformat(TEST_ENCUMBRANCE_EFFECTIVE_DATE), 'jurisdiction': DEFAULT_LICENSE_JURISDICTION, + # TODO - remove this as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 + 'clinicalPrivilegeActionCategory': 'Unsafe Practice or Substandard Care', } ) loaded_adverse_action = AdverseActionData.from_database_record(item) From 28d66d753f23e69d607d29afebf3df8dc4c003fa Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Wed, 15 Oct 2025 23:35:08 -0500 Subject: [PATCH 21/26] PR feedback - clean comments/patches --- .../data-events/tests/function/test_encumbrance_events.py | 4 ---- .../tests/function/test_handlers/test_encumbrance.py | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py b/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py index aed5fbdd6..e53e96ba6 100644 --- a/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py +++ b/backend/compact-connect/lambdas/python/data-events/tests/function/test_encumbrance_events.py @@ -131,7 +131,6 @@ def test_license_encumbrance_listener_encumbers_unencumbered_privileges_successf self.assertIsInstance(called_event_batch_writer_1, EventBatchWriter) self.assertIsInstance(called_event_batch_writer_2, EventBatchWriter) - # Now verify the rest with comprehensive assertion # Now verify the rest with comprehensive assertion self.assertEqual( { @@ -201,13 +200,10 @@ def test_license_encumbrance_listener_handles_no_matching_privileges(self, mock_ # Verify no privilege encumbrance events were published since no privileges were affected mock_publish_event.assert_not_called() - # TODO - remove the mock flag as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 - @patch('cc_common.feature_flag_client.is_feature_enabled', return_value=True) @patch('cc_common.event_bus_client.EventBusClient._publish_event') def test_license_encumbrance_listener_handles_all_privileges_already_encumbered( self, mock_publish_event, - mock_flag, # noqa: ARG002 ): """Test that license encumbrance event handles case where all matching privileges are already encumbered.""" from cc_common.data_model.schema.common import PrivilegeEncumberedStatusEnum diff --git a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py index 1185472d0..911bfc774 100644 --- a/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py +++ b/backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py @@ -383,7 +383,7 @@ def test_privilege_encumbrance_handler_migrates_clinical_privilege_action_catego loaded_adverse_action = AdverseActionData.from_database_record(item) # TODO - remove this assertion as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 - # Verify that the deprecated field is not present in the stored data + # Verify that the deprecated field is present in the stored data self.assertIn('clinicalPrivilegeActionCategory', item) self.assertEqual('Unsafe Practice or Substandard Care', loaded_adverse_action.clinicalPrivilegeActionCategory) @@ -673,7 +673,7 @@ def test_license_encumbrance_handler_migrates_clinical_privilege_action_category loaded_adverse_action = AdverseActionData.from_database_record(item) # TODO - remove this assertion as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 - # Verify that the deprecated field is not present in the stored data + # Verify that the deprecated field is present in the stored data self.assertIn('clinicalPrivilegeActionCategory', item) self.assertEqual('Unsafe Practice or Substandard Care', loaded_adverse_action.clinicalPrivilegeActionCategory) From d64d0ff342b97917dc4a8b651a440b78a2fe7934 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Mon, 20 Oct 2025 16:32:18 -0500 Subject: [PATCH 22/26] move api log assignment to lambda stack --- .../compact-connect/stacks/api_lambda_stack/__init__.py | 1 + .../stacks/api_lambda_stack/provider_management.py | 9 ++++++++- .../stacks/api_stack/v1_api/provider_management.py | 8 -------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/backend/compact-connect/stacks/api_lambda_stack/__init__.py b/backend/compact-connect/stacks/api_lambda_stack/__init__.py index b208f6429..1b2128bae 100644 --- a/backend/compact-connect/stacks/api_lambda_stack/__init__.py +++ b/backend/compact-connect/stacks/api_lambda_stack/__init__.py @@ -123,6 +123,7 @@ def __init__( scope=self, persistent_stack=persistent_stack, data_event_bus=data_event_bus, + api_lambda_stack=self, ) # Public lookup lambdas diff --git a/backend/compact-connect/stacks/api_lambda_stack/provider_management.py b/backend/compact-connect/stacks/api_lambda_stack/provider_management.py index af3493e56..343c37f55 100644 --- a/backend/compact-connect/stacks/api_lambda_stack/provider_management.py +++ b/backend/compact-connect/stacks/api_lambda_stack/provider_management.py @@ -11,6 +11,7 @@ from common_constructs.stack import Stack from common_constructs.python_function import PythonFunction +from stacks import api_lambda_stack as als from stacks import persistent_stack as ps @@ -21,6 +22,7 @@ def __init__( scope: Stack, persistent_stack: ps.PersistentStack, data_event_bus: EventBus, + api_lambda_stack: als.ApiLambdaStack, ) -> None: self.scope = scope self.persistent_stack = persistent_stack @@ -44,10 +46,15 @@ def __init__( # Create all the lambda handlers self.get_provider_handler = self._get_provider_handler(lambda_environment) + api_lambda_stack.log_groups.append(self.get_provider_handler) self.query_providers_handler = self._query_providers_handler(lambda_environment) + api_lambda_stack.log_groups.append(self.query_providers_handler) self.get_provider_ssn_handler = self._get_provider_ssn_handler(lambda_environment) + api_lambda_stack.log_groups.append(self.get_provider_ssn_handler) self.deactivate_privilege_handler = self._deactivate_privilege_handler(lambda_environment) + api_lambda_stack.log_groups.append(self.deactivate_privilege_handler) self.provider_encumbrance_handler = self._add_provider_encumbrance_handler(lambda_environment) + api_lambda_stack.log_groups.append(self.provider_encumbrance_handler) def _get_provider_handler( self, @@ -69,7 +76,7 @@ def _get_provider_handler( NagSuppressions.add_resource_suppressions_by_path( self.stack, - path=f'{handler.node.path}/ServiceRole/DefaultPolicy/Resource', + path=f'{handler.role.node.path}/DefaultPolicy/Resource', suppressions=[ { 'id': 'AwsSolutions-IAM5', diff --git a/backend/compact-connect/stacks/api_stack/v1_api/provider_management.py b/backend/compact-connect/stacks/api_stack/v1_api/provider_management.py index 2582d8011..db7eedd4e 100644 --- a/backend/compact-connect/stacks/api_stack/v1_api/provider_management.py +++ b/backend/compact-connect/stacks/api_stack/v1_api/provider_management.py @@ -82,8 +82,6 @@ def _add_get_provider( self, method_options: MethodOptions, ): - self.api.log_groups.append(self.get_provider_handler.log_group) - self.provider_resource.add_method( 'GET', request_validator=self.api.parameter_body_validator, @@ -106,8 +104,6 @@ def _add_query_providers( ): query_resource = self.resource.add_resource('query') - self.api.log_groups.append(self.query_providers_handler.log_group) - query_resource.add_method( 'POST', request_validator=self.api.parameter_body_validator, @@ -130,8 +126,6 @@ def _add_get_provider_ssn( method_options: MethodOptions, ): """Add GET /providers/{providerId}/ssn endpoint to retrieve a provider's SSN.""" - self.api.log_groups.append(self.get_provider_ssn_handler.log_group) - # Add the SSN endpoint as a sub-resource of the provider self.ssn_resource = self.provider_resource.add_resource('ssn') self.ssn_resource.add_method( @@ -182,8 +176,6 @@ def _add_deactivate_privilege( ): """Add POST /providers/{providerId}/privileges/jurisdiction/{jurisdiction} /licenseType/{licenseType}/deactivate endpoint.""" - self.api.log_groups.append(self.deactivate_privilege_handler.log_group) - deactivate_resource = self.privilege_jurisdiction_license_type_resource.add_resource('deactivate') # Create a metric to track privilege deactivation notification failures From 1880cdf2e84f45e827ce2b289975d2a376f2aeb5 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Tue, 21 Oct 2025 09:17:58 -0500 Subject: [PATCH 23/26] Retain all lambda layer versions for all environments --- .../common_constructs/python_common_layer_versions.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/compact-connect/common_constructs/python_common_layer_versions.py b/backend/compact-connect/common_constructs/python_common_layer_versions.py index 4bf9e0a99..37cf1b464 100644 --- a/backend/compact-connect/common_constructs/python_common_layer_versions.py +++ b/backend/compact-connect/common_constructs/python_common_layer_versions.py @@ -50,9 +50,7 @@ def __init__( # we will likely need to add a custom resource to track these versions, and clean up versions that are # older than a certain date. That is out of scope for our current effort, but we're leaving this comment # here to remind us that this will need to be addressed at a later date. - removal_policy=RemovalPolicy.RETAIN - if not self.node.try_get_context('sandbox') - else RemovalPolicy.DESTROY, + removal_policy=RemovalPolicy.RETAIN, **kwargs, ) From 40eca5423a2dd755af3ea0fbe785125178c83ee0 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Tue, 21 Oct 2025 09:21:04 -0500 Subject: [PATCH 24/26] Update API spec to latest after rebase --- .../api-specification/latest-oas30.json | 7412 ++++++++--------- .../internal/postman/postman-collection.json | 432 +- 2 files changed, 3800 insertions(+), 4044 deletions(-) diff --git a/backend/compact-connect/docs/internal/api-specification/latest-oas30.json b/backend/compact-connect/docs/internal/api-specification/latest-oas30.json index ca3814bff..60e772c96 100644 --- a/backend/compact-connect/docs/internal/api-specification/latest-oas30.json +++ b/backend/compact-connect/docs/internal/api-specification/latest-oas30.json @@ -2,7 +2,7 @@ "openapi": "3.0.1", "info": { "title": "LicenseApi", - "version": "2025-10-10T20:12:46Z" + "version": "2025-10-20T22:42:50Z" }, "servers": [ { @@ -36,7 +36,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenBxfAXNgCl0f1" + "$ref": "#/components/schemas/SandboLicenwpDMqHaHBxLL" } } } @@ -75,7 +75,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenrzUhY3WW0Y7L" + "$ref": "#/components/schemas/SandboLicenqVKYQ6QCUUYV" } } }, @@ -87,7 +87,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -167,7 +167,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenHcuQxywUvhOh" + "$ref": "#/components/schemas/SandboLicenFBKwuejTjcRR" } } } @@ -204,7 +204,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenLPepHoMLi1aj" + "$ref": "#/components/schemas/SandboLicen74bwm5yy6E5W" } } }, @@ -216,7 +216,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenou5OKotlJ6Ez" + "$ref": "#/components/schemas/SandboLicenT1eMkx5ptE5k" } } } @@ -288,7 +288,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenHX8YNrOpPZbZ" + "$ref": "#/components/schemas/SandboLicenfM0YyXB9i4El" } } } @@ -339,7 +339,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenbGNGFVLD0EDE" + "$ref": "#/components/schemas/SandboLicene2a50HkoiVOX" } } } @@ -386,7 +386,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenTi9BrhAERjPp" + "$ref": "#/components/schemas/SandboLicenXxQQC9wWjThg" } } }, @@ -398,7 +398,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -444,96 +444,6 @@ ] } }, - "/v1/compacts/{compact}/jurisdictions/{jurisdiction}/licenses": { - "post": { - "parameters": [ - { - "name": "Authorization", - "in": "header", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "compact", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "jurisdiction", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "400": { - "description": "400 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboLicenMiDI81d6EYvq" - } - } - } - }, - "200": { - "description": "200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" - } - } - } - } - }, - "security": [ - { - "SandboxAPIStackLicenseApiStaffUsersPoolAuthorizer14A84A9B": [ - "aslp/write", - "al/aslp.write", - "ak/aslp.write", - "ar/aslp.write", - "co/aslp.write", - "de/aslp.write", - "ky/aslp.write", - "la/aslp.write", - "me/aslp.write", - "md/aslp.write", - "mn/aslp.write", - "ms/aslp.write", - "mo/aslp.write", - "ne/aslp.write", - "oh/aslp.write", - "octp/write", - "al/octp.write", - "ar/octp.write", - "ky/octp.write", - "la/octp.write", - "ms/octp.write", - "ne/octp.write", - "oh/octp.write", - "coun/write", - "al/coun.write", - "ar/coun.write", - "fl/coun.write", - "ga/coun.write", - "ky/coun.write", - "ne/coun.write", - "oh/coun.write", - "ut/coun.write" - ] - } - ] - } - }, "/v1/compacts/{compact}/jurisdictions/{jurisdiction}/licenses/bulk-upload": { "get": { "parameters": [ @@ -568,7 +478,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenJIK60DVCsApb" + "$ref": "#/components/schemas/SandboLicenYSm3tRorgR8v" } } } @@ -638,7 +548,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenYwiFMNF2Vu7Z" + "$ref": "#/components/schemas/SandboLicen14sjN2dXfQbr" } } }, @@ -650,7 +560,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLiceno12FSfDWBzow" + "$ref": "#/components/schemas/SandboLicenaYqlozRvql5b" } } } @@ -701,7 +611,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenr5TVmpxKfPGq" + "$ref": "#/components/schemas/SandboLicen6yHAPPYOdJ3t" } } } @@ -766,7 +676,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenEAecRKtirVZk" + "$ref": "#/components/schemas/SandboLicen3QxrBb8JFDnT" } } }, @@ -778,7 +688,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -880,7 +790,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicen3zolh21hPpCk" + "$ref": "#/components/schemas/SandboLicenwjDvDRZGRaqT" } } }, @@ -892,7 +802,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -986,7 +896,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenPAsEF1Ia4s7g" + "$ref": "#/components/schemas/SandboLicenUTb3zNObrjW5" } } }, @@ -998,7 +908,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -1092,7 +1002,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicen6bEbVSG2KkBx" + "$ref": "#/components/schemas/SandboLicenk1ql1I81jsMY" } } }, @@ -1104,7 +1014,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -1206,7 +1116,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenVZHLGnXN7APB" + "$ref": "#/components/schemas/SandboLicenGkLIz61xmgWo" } } }, @@ -1218,7 +1128,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -1314,7 +1224,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenobivPmYh5SvH" + "$ref": "#/components/schemas/SandboLicenZVm9nad5vQW4" } } } @@ -1365,7 +1275,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicen2x5yTuN7Vce5" + "$ref": "#/components/schemas/SandboLicenBNvp4YDeh5rF" } } } @@ -1436,7 +1346,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenLLx7v2Sq2Nku" + "$ref": "#/components/schemas/SandboLicenjksXkBC6cpMT" } } } @@ -1496,7 +1406,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenDb8Dl04rAoPD" + "$ref": "#/components/schemas/SandboLicen15BtNCg0ttcx" } } }, @@ -1515,7 +1425,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicen2VPoPHwDEcqq" + "$ref": "#/components/schemas/SandboLicenuLEzkOrUfJeb" } } } @@ -1587,7 +1497,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -1604,7 +1514,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicen2VPoPHwDEcqq" + "$ref": "#/components/schemas/SandboLicenuLEzkOrUfJeb" } } } @@ -1674,7 +1584,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -1684,7 +1594,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -1752,7 +1662,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenC1PiOZAh5Usx" + "$ref": "#/components/schemas/SandboLicens8zWlw8e3VjA" } } }, @@ -1764,7 +1674,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -1781,7 +1691,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicen2VPoPHwDEcqq" + "$ref": "#/components/schemas/SandboLicenuLEzkOrUfJeb" } } } @@ -1853,7 +1763,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -1863,7 +1773,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -1925,7 +1835,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenJJIxiEwTVetd" + "$ref": "#/components/schemas/SandboLicenS3OpuzvlfqIR" } } }, @@ -1937,7 +1847,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicen9LUz5xMGHXhV" + "$ref": "#/components/schemas/SandboLiceno4zXe3APQ07E" } } } @@ -1951,7 +1861,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenpPZOnBEPSaJL" + "$ref": "#/components/schemas/SandboLicen2TYOnVghC533" } } }, @@ -1963,7 +1873,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -1989,7 +1899,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenr5TVmpxKfPGq" + "$ref": "#/components/schemas/SandboLicen6yHAPPYOdJ3t" } } } @@ -2018,7 +1928,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenaSmGZue6afyn" + "$ref": "#/components/schemas/SandboLiceno1FF4B6IPNWg" } } }, @@ -2030,7 +1940,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -2059,7 +1969,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenbcsmAhiZJZ0Q" + "$ref": "#/components/schemas/SandboLicen34TBFk9LdAJJ" } } }, @@ -2071,7 +1981,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -2100,7 +2010,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicen8QcYRI7AzDyX" + "$ref": "#/components/schemas/SandboLicenaFsmBhKzUkNI" } } }, @@ -2112,7 +2022,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -2159,7 +2069,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenobivPmYh5SvH" + "$ref": "#/components/schemas/SandboLicenZVm9nad5vQW4" } } } @@ -2188,7 +2098,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenJZNKekBSUCl5" + "$ref": "#/components/schemas/SandboLicenOJHHzc75m2Dh" } } }, @@ -2200,7 +2110,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenUzZJQKKk5goL" + "$ref": "#/components/schemas/SandboLicenbmJo5pJTGNyk" } } } @@ -2227,7 +2137,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicendERazg9NeEsA" + "$ref": "#/components/schemas/SandboLicenDDeRKnGCOQFv" } } }, @@ -2239,7 +2149,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -2258,7 +2168,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenwoqrSnm0rsGM" + "$ref": "#/components/schemas/SandboLicenUascxyoiRHZo" } } }, @@ -2270,7 +2180,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -2284,7 +2194,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenirtyanNQfXka" + "$ref": "#/components/schemas/SandboLicenbvbpTeGqjAcZ" } } }, @@ -2296,7 +2206,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -2322,7 +2232,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenHX8YNrOpPZbZ" + "$ref": "#/components/schemas/SandboLicenfM0YyXB9i4El" } } } @@ -2346,7 +2256,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenYwiFMNF2Vu7Z" + "$ref": "#/components/schemas/SandboLicen14sjN2dXfQbr" } } }, @@ -2358,7 +2268,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenBxXRobaYJSR9" + "$ref": "#/components/schemas/SandboLicenxSf6anmMiZUl" } } } @@ -2392,7 +2302,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicendF8CsBCXAU1x" + "$ref": "#/components/schemas/SandboLicenkPqluVn6dJHe" } } } @@ -2442,7 +2352,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenobivPmYh5SvH" + "$ref": "#/components/schemas/SandboLicenZVm9nad5vQW4" } } } @@ -2466,7 +2376,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenBWZgN83iyevY" + "$ref": "#/components/schemas/SandboLicenLhkhDxX4fiIg" } } }, @@ -2478,7 +2388,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLiceng72nqBB23bmL" + "$ref": "#/components/schemas/SandboLicenrZuAY9tZ4fCA" } } } @@ -2509,7 +2419,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenI2vqm7fRdSBi" + "$ref": "#/components/schemas/SandboLicenBqFE7Lkpte9Z" } } } @@ -2530,7 +2440,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -2547,7 +2457,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicen2VPoPHwDEcqq" + "$ref": "#/components/schemas/SandboLicenuLEzkOrUfJeb" } } } @@ -2566,7 +2476,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicenI4CqYMff5SWl" + "$ref": "#/components/schemas/SandboLicenQrINPgMnQioZ" } } }, @@ -2578,7 +2488,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicengeanQqZ1NjKt" + "$ref": "#/components/schemas/SandboLicenaLbwv28ZqyH6" } } } @@ -2595,7 +2505,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboLicen2VPoPHwDEcqq" + "$ref": "#/components/schemas/SandboLicenuLEzkOrUfJeb" } } } @@ -2613,7 +2523,7 @@ }, "components": { "schemas": { - "SandboLicen2x5yTuN7Vce5": { + "SandboLicenBNvp4YDeh5rF": { "required": [ "ssn" ], @@ -2626,428 +2536,295 @@ } } }, - "SandboLicenbcsmAhiZJZ0Q": { - "required": [ - "verificationCode" - ], - "type": "object", - "properties": { - "verificationCode": { - "pattern": "^[0-9]{4}$", - "type": "string", - "description": "4-digit verification code" - } - }, - "additionalProperties": false - }, - "SandboLicenJIK60DVCsApb": { + "SandboLicenXxQQC9wWjThg": { "required": [ - "upload" + "jurisdictionAdverseActionsNotificationEmails", + "jurisdictionOperationsTeamEmails", + "jurisdictionSummaryReportNotificationEmails", + "jurisprudenceRequirements", + "licenseeRegistrationEnabled", + "privilegeFees" ], "type": "object", "properties": { - "upload": { + "privilegeFees": { + "type": "array", + "description": "The fees for the privileges by license type", + "items": { + "required": [ + "amount", + "licenseTypeAbbreviation" + ], + "type": "object", + "properties": { + "amount": { + "minimum": 0, + "type": "number" + }, + "militaryRate": { + "description": "Optional military rate for the privilege fee.", + "oneOf": [ + { + "minimum": 0, + "type": "number" + }, + null + ] + }, + "licenseTypeAbbreviation": { + "type": "string", + "enum": [ + "aud", + "slp", + "ot", + "ota", + "lpc" + ] + } + }, + "additionalProperties": false + } + }, + "jurisdictionAdverseActionsNotificationEmails": { + "maxItems": 10, + "minItems": 1, + "uniqueItems": true, + "type": "array", + "description": "List of email addresses for adverse actions notifications", + "items": { + "type": "string", + "format": "email" + } + }, + "jurisdictionOperationsTeamEmails": { + "maxItems": 10, + "minItems": 1, + "uniqueItems": true, + "type": "array", + "description": "List of email addresses for operations team notifications", + "items": { + "type": "string", + "format": "email" + } + }, + "jurisprudenceRequirements": { "required": [ - "fields", - "url" + "required" ], "type": "object", "properties": { - "fields": { - "type": "object", - "additionalProperties": { - "type": "string" - } + "linkToDocumentation": { + "description": "Optional link to jurisprudence documentation", + "oneOf": [ + { + "type": "string" + }, + null + ] }, - "url": { - "type": "string" + "required": { + "type": "boolean", + "description": "Whether jurisprudence requirements exist" } + }, + "additionalProperties": false + }, + "licenseeRegistrationEnabled": { + "type": "boolean", + "description": "Denotes whether licensee registration is enabled" + }, + "jurisdictionSummaryReportNotificationEmails": { + "maxItems": 10, + "minItems": 1, + "uniqueItems": true, + "type": "array", + "description": "List of email addresses for summary report notifications", + "items": { + "type": "string", + "format": "email" } } - } + }, + "additionalProperties": false }, - "SandboLicen6bEbVSG2KkBx": { + "SandboLicenUascxyoiRHZo": { "required": [ - "clinicalPrivilegeActionCategory", - "encumbranceEffectiveDate", - "encumbranceType" + "compact", + "dob", + "email", + "familyName", + "givenName", + "jurisdiction", + "licenseType", + "partialSocial", + "token" ], "type": "object", "properties": { - "encumbranceEffectiveDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "description": "The effective date of the encumbrance", - "format": "date" - }, - "encumbranceType": { + "licenseType": { + "maxLength": 500, "type": "string", - "description": "The type of encumbrance", + "description": "Type of license", "enum": [ - "fine", - "reprimand", - "required supervision", - "completion of continuing education", - "public reprimand", - "probation", - "injunctive action", - "suspension", - "revocation", - "denial", - "surrender of license", - "modification of previous action-extension", - "modification of previous action-reduction", - "other monitoring", - "other adjudicated action not listed" + "audiologist", + "speech-language pathologist", + "occupational therapist", + "occupational therapy assistant", + "licensed professional counselor" ] }, - "clinicalPrivilegeActionCategory": { + "compact": { + "maxLength": 100, "type": "string", - "description": "The category of clinical privilege action" - } - }, - "additionalProperties": false - }, - "SandboLicenVZHLGnXN7APB": { - "required": [ - "effectiveLiftDate" - ], - "type": "object", - "properties": { - "effectiveLiftDate": { + "description": "Compact name" + }, + "dob": { "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", "type": "string", - "description": "The effective date when the encumbrance will be lifted", - "format": "date" - } - }, - "additionalProperties": false - }, - "SandboLicenirtyanNQfXka": { - "required": [ - "compact", - "providerId", - "recaptchaToken", - "recoveryToken" - ], - "type": "object", - "properties": { - "compact": { + "description": "Date of birth in YYYY-MM-DD format" + }, + "givenName": { + "maxLength": 200, "type": "string", - "description": "Compact abbreviation", + "description": "Provider's given name" + }, + "familyName": { + "maxLength": 200, + "type": "string", + "description": "Provider's family name" + }, + "jurisdiction": { + "maxLength": 2, + "minLength": 2, + "type": "string", + "description": "Two-letter jurisdiction code", "enum": [ - "aslp", - "octp", - "coun" + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" ] }, - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "partialSocial": { + "maxLength": 4, + "minLength": 4, "type": "string", - "description": "Provider UUID" + "description": "Last 4 digits of SSN" }, - "recaptchaToken": { - "minLength": 1, + "email": { + "maxLength": 100, + "minLength": 5, "type": "string", - "description": "ReCAPTCHA token for verification" + "description": "Provider's email address", + "format": "email" }, - "recoveryToken": { - "maxLength": 256, - "minLength": 1, + "token": { "type": "string", - "description": "Recovery token from the email link" + "description": "ReCAPTCHA token" } - }, - "additionalProperties": false + } }, - "SandboLicen2VPoPHwDEcqq": { + "SandboLicenYSm3tRorgR8v": { "required": [ - "attributes", - "permissions", - "status", - "userId" + "upload" ], "type": "object", "properties": { - "permissions": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "actions": { - "type": "object", - "properties": { - "readPrivate": { - "type": "boolean" - }, - "admin": { - "type": "boolean" - }, - "readSSN": { - "type": "boolean" - } - } - }, - "jurisdictions": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "actions": { - "type": "object", - "properties": { - "readPrivate": { - "type": "boolean" - }, - "admin": { - "type": "boolean" - }, - "write": { - "type": "boolean" - }, - "readSSN": { - "type": "boolean" - } - }, - "additionalProperties": false - } - } - } - } - }, - "additionalProperties": false - } - }, - "attributes": { + "upload": { "required": [ - "email", - "familyName", - "givenName" + "fields", + "url" ], "type": "object", "properties": { - "givenName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "familyName": { - "maxLength": 100, - "minLength": 1, - "type": "string" + "fields": { + "type": "object", + "additionalProperties": { + "type": "string" + } }, - "email": { - "maxLength": 100, - "minLength": 5, + "url": { "type": "string" } - }, - "additionalProperties": false - }, - "userId": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "active", - "inactive" - ] + } } - }, - "additionalProperties": false + } }, - "SandboLicenUzZJQKKk5goL": { + "SandboLicenaYqlozRvql5b": { "required": [ - "affiliationType", - "dateOfUpdate", - "dateOfUpload", - "documentUploadFields", - "status" + "pagination", + "providers" ], "type": "object", "properties": { - "dateOfUpload": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "description": "The date the document was uploaded", - "format": "date" - }, - "affiliationType": { - "type": "string", - "description": "The type of military affiliation", - "enum": [ - "militaryMember", - "militaryMemberSpouse" - ] - }, - "fileNames": { - "type": "array", - "description": "List of military affiliation file names", - "items": { - "type": "string", - "description": "The name of the file being uploaded" - } - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "description": "The date the document was last updated", - "format": "date" - }, - "status": { - "type": "string", - "description": "The status of the military affiliation" - }, - "documentUploadFields": { - "type": "array", - "description": "The fields used to upload documents", - "items": { - "type": "object", - "properties": { - "fields": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "The form fields used to upload the document" - }, - "url": { - "type": "string", - "description": "The url to upload the document to" - } - }, - "description": "The fields used to upload a specific document" - } - } - } - }, - "SandboLicenMiDI81d6EYvq": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Message indicating success or failure" - }, - "errors": { - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": { - "type": "array", - "description": "List of error messages for a field", - "items": { - "type": "string" - } - }, - "description": "Errors for a specific record" - }, - "description": "Validation errors by record index" - } - } - }, - "SandboLicenYwiFMNF2Vu7Z": { - "required": [ - "query" - ], - "type": "object", - "properties": { - "pagination": { - "type": "object", - "properties": { - "lastKey": { - "maxLength": 1024, - "minLength": 1, - "type": "string" - }, - "pageSize": { - "maximum": 100, - "minimum": 5, - "type": "integer" - } - }, - "additionalProperties": false - }, - "query": { - "type": "object", - "properties": { - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string", - "description": "Internal UUID for the provider" - }, - "jurisdiction": { - "type": "string", - "description": "Filter for providers with privilege/license in a jurisdiction", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "givenName": { - "maxLength": 100, - "type": "string", - "description": "Filter for providers with a given name (familyName is required if givenName is provided)" - }, - "familyName": { - "maxLength": 100, - "type": "string", - "description": "Filter for providers with a family name" - } - }, - "additionalProperties": false, - "description": "The query parameters" + "pagination": { + "type": "object", + "properties": { + "prevLastKey": { + "maxLength": 1024, + "minLength": 1, + "type": "object" + }, + "lastKey": { + "maxLength": 1024, + "minLength": 1, + "type": "object" + }, + "pageSize": { + "maximum": 100, + "minimum": 5, + "type": "integer" + } + } }, "sorting": { "required": [ @@ -3073,345 +2850,30 @@ } }, "description": "How to sort results" - } - }, - "additionalProperties": false - }, - "SandboLicenHX8YNrOpPZbZ": { - "type": "array", - "items": { - "required": [ - "compact", - "jurisdictionName", - "postalAbbreviation" - ], - "type": "object", - "properties": { - "postalAbbreviation": { - "type": "string", - "description": "The postal abbreviation of the jurisdiction" - }, - "compact": { - "type": "string" - }, - "jurisdictionName": { - "type": "string", - "description": "The name of the jurisdiction" - } - } - } - }, - "SandboLicengeanQqZ1NjKt": { - "required": [ - "message" - ], - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "A message about the request" - } - } - }, - "SandboLicenTi9BrhAERjPp": { - "required": [ - "jurisdictionAdverseActionsNotificationEmails", - "jurisdictionOperationsTeamEmails", - "jurisdictionSummaryReportNotificationEmails", - "jurisprudenceRequirements", - "licenseeRegistrationEnabled", - "privilegeFees" - ], - "type": "object", - "properties": { - "privilegeFees": { + }, + "providers": { + "maxLength": 100, "type": "array", - "description": "The fees for the privileges by license type", "items": { "required": [ - "amount", - "licenseTypeAbbreviation" + "birthMonthDay", + "compact", + "compactEligibility", + "dateOfExpiration", + "dateOfUpdate", + "familyName", + "givenName", + "jurisdictionUploadedCompactEligibility", + "jurisdictionUploadedLicenseStatus", + "licenseJurisdiction", + "licenseStatus", + "privilegeJurisdictions", + "providerId", + "type" ], "type": "object", "properties": { - "amount": { - "minimum": 0, - "type": "number" - }, - "militaryRate": { - "description": "Optional military rate for the privilege fee.", - "oneOf": [ - { - "minimum": 0, - "type": "number" - }, - null - ] - }, - "licenseTypeAbbreviation": { - "type": "string", - "enum": [ - "aud", - "slp", - "ot", - "ota", - "lpc" - ] - } - }, - "additionalProperties": false - } - }, - "jurisdictionAdverseActionsNotificationEmails": { - "maxItems": 10, - "minItems": 1, - "uniqueItems": true, - "type": "array", - "description": "List of email addresses for adverse actions notifications", - "items": { - "type": "string", - "format": "email" - } - }, - "jurisdictionOperationsTeamEmails": { - "maxItems": 10, - "minItems": 1, - "uniqueItems": true, - "type": "array", - "description": "List of email addresses for operations team notifications", - "items": { - "type": "string", - "format": "email" - } - }, - "jurisprudenceRequirements": { - "required": [ - "required" - ], - "type": "object", - "properties": { - "linkToDocumentation": { - "description": "Optional link to jurisprudence documentation", - "oneOf": [ - { - "type": "string" - }, - null - ] - }, - "required": { - "type": "boolean", - "description": "Whether jurisprudence requirements exist" - } - }, - "additionalProperties": false - }, - "licenseeRegistrationEnabled": { - "type": "boolean", - "description": "Denotes whether licensee registration is enabled" - }, - "jurisdictionSummaryReportNotificationEmails": { - "maxItems": 10, - "minItems": 1, - "uniqueItems": true, - "type": "array", - "description": "List of email addresses for summary report notifications", - "items": { - "type": "string", - "format": "email" - } - } - }, - "additionalProperties": false - }, - "SandboLicen3zolh21hPpCk": { - "required": [ - "effectiveLiftDate" - ], - "type": "object", - "properties": { - "effectiveLiftDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "description": "The effective date when the encumbrance will be lifted", - "format": "date" - } - }, - "additionalProperties": false - }, - "SandboLicenJJIxiEwTVetd": { - "type": "object", - "properties": { - "context": { - "type": "object", - "properties": { - "userId": { - "maxLength": 100, - "minLength": 1, - "type": "string", - "description": "Optional user ID for feature flag evaluation" - }, - "customAttributes": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "Optional custom attributes for feature flag evaluation" - } - }, - "additionalProperties": false, - "description": "Optional context for feature flag evaluation" - } - }, - "additionalProperties": false - }, - "SandboLicenBxXRobaYJSR9": { - "required": [ - "pagination", - "providers" - ], - "type": "object", - "properties": { - "pagination": { - "type": "object", - "properties": { - "prevLastKey": { - "maxLength": 1024, - "minLength": 1, - "type": "object" - }, - "lastKey": { - "maxLength": 1024, - "minLength": 1, - "type": "object" - }, - "pageSize": { - "maximum": 100, - "minimum": 5, - "type": "integer" - } - } - }, - "query": { - "type": "object", - "properties": { - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string", - "description": "Internal UUID for the provider" - }, - "jurisdiction": { - "type": "string", - "description": "Filter for providers with privilege/license in a jurisdiction", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "givenName": { - "maxLength": 100, - "type": "string", - "description": "Filter for providers with a given name" - }, - "familyName": { - "maxLength": 100, - "type": "string", - "description": "Filter for providers with a family name" - } - } - }, - "sorting": { - "required": [ - "key" - ], - "type": "object", - "properties": { - "key": { - "type": "string", - "description": "The key to sort results by", - "enum": [ - "dateOfUpdate", - "familyName" - ] - }, - "direction": { - "type": "string", - "description": "Direction to sort results by", - "enum": [ - "ascending", - "descending" - ] - } - }, - "description": "How to sort results" - }, - "providers": { - "maxLength": 100, - "type": "array", - "items": { - "required": [ - "compact", - "familyName", - "givenName", - "licenseJurisdiction", - "privilegeJurisdictions", - "providerId", - "type" - ], - "type": "object", - "properties": { - "licenseJurisdiction": { + "licenseJurisdiction": { "type": "string", "enum": [ "al", @@ -3477,10 +2939,6 @@ "coun" ] }, - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string" - }, "npi": { "pattern": "^[0-9]{10}$", "type": "string" @@ -3490,15 +2948,31 @@ "minLength": 1, "type": "string" }, - "familyName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "middleName": { - "maxLength": 100, - "minLength": 1, - "type": "string" + "compactEligibility": { + "type": "string", + "enum": [ + "eligible", + "ineligible" + ] + }, + "jurisdictionUploadedCompactEligibility": { + "type": "string", + "enum": [ + "eligible", + "ineligible" + ] + }, + "dateOfBirth": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "jurisdictionUploadedLicenseStatus": { + "type": "string", + "enum": [ + "active", + "inactive" + ] }, "privilegeJurisdictions": { "type": "array", @@ -3633,6 +3107,47 @@ "unknown" ] }, + "ssnLastFour": { + "pattern": "^[0-9]{4}$", + "type": "string" + }, + "dateOfExpiration": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string" + }, + "licenseStatus": { + "type": "string", + "enum": [ + "active", + "inactive" + ] + }, + "familyName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "middleName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "birthMonthDay": { + "pattern": "^[01]{1}[0-9]{1}-[0-3]{1}[0-9]{1}$", + "type": "string", + "format": "date" + }, + "compactConnectRegisteredEmailAddress": { + "maxLength": 100, + "minLength": 5, + "type": "string", + "format": "email" + }, "dateOfUpdate": { "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", "type": "string", @@ -3643,233 +3158,205 @@ } } }, - "SandboLicenou5OKotlJ6Ez": { + "SandboLicenwpDMqHaHBxLL": { "required": [ - "message" + "compactAbbr", + "compactAdverseActionsNotificationEmails", + "compactCommissionFee", + "compactName", + "compactOperationsTeamEmails", + "compactSummaryReportNotificationEmails", + "configuredStates", + "licenseeRegistrationEnabled" ], "type": "object", "properties": { - "message": { + "configuredStates": { + "type": "array", + "description": "List of states that have submitted configurations and their live status", + "items": { + "required": [ + "isLive", + "postalAbbreviation" + ], + "type": "object", + "properties": { + "postalAbbreviation": { + "type": "string", + "description": "The postal abbreviation of the jurisdiction", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] + }, + "isLive": { + "type": "boolean", + "description": "Whether the state is live and available for registrations." + } + } + } + }, + "compactCommissionFee": { + "required": [ + "feeAmount", + "feeType" + ], + "type": "object", + "properties": { + "feeAmount": { + "type": "number" + }, + "feeType": { + "type": "string", + "enum": [ + "FLAT_RATE" + ] + } + } + }, + "compactSummaryReportNotificationEmails": { + "type": "array", + "description": "List of email addresses for summary report notifications", + "items": { + "type": "string", + "format": "email" + } + }, + "compactAdverseActionsNotificationEmails": { + "type": "array", + "description": "List of email addresses for adverse actions notifications", + "items": { + "type": "string", + "format": "email" + } + }, + "licenseeRegistrationEnabled": { + "type": "boolean", + "description": "Denotes whether licensee registration is enabled" + }, + "compactAbbr": { "type": "string", - "description": "A message about the request" + "description": "The abbreviation of the compact" + }, + "transactionFeeConfiguration": { + "type": "object", + "properties": { + "licenseeCharges": { + "required": [ + "active", + "chargeAmount", + "chargeType" + ], + "type": "object", + "properties": { + "chargeType": { + "type": "string", + "description": "The type of transaction fee charge", + "enum": [ + "FLAT_FEE_PER_PRIVILEGE" + ] + }, + "active": { + "type": "boolean", + "description": "Whether the compact is charging licensees transaction fees" + }, + "chargeAmount": { + "type": "number", + "description": "The amount to charge per privilege purchased" + } + } + } + } + }, + "compactName": { + "type": "string", + "description": "The full name of the compact" + }, + "compactOperationsTeamEmails": { + "type": "array", + "description": "List of email addresses for operations team notifications", + "items": { + "type": "string", + "format": "email" + } } } }, - "SandboLicenpPZOnBEPSaJL": { + "SandboLicenqVKYQ6QCUUYV": { "required": [ - "compact", - "dob", - "familyName", - "givenName", - "jurisdiction", - "licenseType", - "partialSocial", - "password", - "recaptchaToken", - "username" + "compactAdverseActionsNotificationEmails", + "compactCommissionFee", + "compactOperationsTeamEmails", + "compactSummaryReportNotificationEmails", + "configuredStates", + "licenseeRegistrationEnabled" ], "type": "object", "properties": { - "licenseType": { - "type": "string", - "description": "Type of license", - "enum": [ - "audiologist", - "speech-language pathologist", - "occupational therapist", - "occupational therapy assistant", - "licensed professional counselor" - ] - }, - "password": { - "maxLength": 256, - "minLength": 12, - "type": "string", - "description": "Provider's current password" - }, - "compact": { - "type": "string", - "description": "Compact abbreviation", - "enum": [ - "aslp", - "octp", - "coun" - ] - }, - "dob": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "description": "Date of birth in YYYY-MM-DD format", - "format": "date" - }, - "jurisdiction": { - "type": "string", - "description": "Two-letter jurisdiction code", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "givenName": { - "maxLength": 200, - "minLength": 1, - "type": "string", - "description": "Provider's given name" - }, - "familyName": { - "maxLength": 200, - "minLength": 1, - "type": "string", - "description": "Provider's family name" - }, - "recaptchaToken": { - "minLength": 1, - "type": "string", - "description": "ReCAPTCHA token for verification" - }, - "partialSocial": { - "pattern": "^[0-9]{4}$", - "type": "string", - "description": "Last 4 digits of SSN" - }, - "username": { - "maxLength": 100, - "minLength": 5, - "type": "string", - "description": "Provider's email address (username)", - "format": "email" - } - }, - "additionalProperties": false - }, - "SandboLicenEAecRKtirVZk": { - "required": [ - "clinicalPrivilegeActionCategory", - "encumbranceEffectiveDate", - "encumbranceType" - ], - "type": "object", - "properties": { - "encumbranceEffectiveDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "description": "The effective date of the encumbrance", - "format": "date" - }, - "encumbranceType": { - "type": "string", - "description": "The type of encumbrance", - "enum": [ - "fine", - "reprimand", - "required supervision", - "completion of continuing education", - "public reprimand", - "probation", - "injunctive action", - "suspension", - "revocation", - "denial", - "surrender of license", - "modification of previous action-extension", - "modification of previous action-reduction", - "other monitoring", - "other adjudicated action not listed" - ] - }, - "clinicalPrivilegeActionCategory": { - "type": "string", - "description": "The category of clinical privilege action" - } - }, - "additionalProperties": false - }, - "SandboLicendF8CsBCXAU1x": { - "required": [ - "compact", - "dateOfUpdate", - "familyName", - "givenName", - "licenseJurisdiction", - "privilegeJurisdictions", - "providerId", - "type" - ], - "type": "object", - "properties": { - "privileges": { + "configuredStates": { "type": "array", + "description": "List of states that have submitted configurations and their live status", "items": { "required": [ - "administratorSetStatus", - "compact", - "dateOfExpiration", - "dateOfIssuance", - "dateOfRenewal", - "dateOfUpdate", - "jurisdiction", - "licenseJurisdiction", - "licenseType", - "privilegeId", - "providerId", - "status", - "type" + "isLive", + "postalAbbreviation" ], "type": "object", "properties": { - "licenseJurisdiction": { + "postalAbbreviation": { "type": "string", + "description": "The postal abbreviation of the jurisdiction", "enum": [ "al", "ak", @@ -3926,571 +3413,283 @@ "wy" ] }, - "compact": { - "type": "string", - "enum": [ - "aslp", - "octp", - "coun" - ] - }, - "jurisdiction": { - "type": "string", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] + "isLive": { + "type": "boolean", + "description": "Whether the state is live and available for registrations." + } + }, + "additionalProperties": false + } + }, + "compactCommissionFee": { + "required": [ + "feeAmount", + "feeType" + ], + "type": "object", + "properties": { + "feeAmount": { + "minimum": 0, + "type": "number" + }, + "feeType": { + "type": "string", + "enum": [ + "FLAT_RATE" + ] + } + }, + "additionalProperties": false + }, + "compactSummaryReportNotificationEmails": { + "maxItems": 10, + "minItems": 1, + "uniqueItems": true, + "type": "array", + "description": "List of email addresses for summary report notifications", + "items": { + "type": "string", + "format": "email" + } + }, + "compactAdverseActionsNotificationEmails": { + "maxItems": 10, + "minItems": 1, + "uniqueItems": true, + "type": "array", + "description": "List of email addresses for adverse actions notifications", + "items": { + "type": "string", + "format": "email" + } + }, + "licenseeRegistrationEnabled": { + "type": "boolean", + "description": "Denotes whether licensee registration is enabled" + }, + "transactionFeeConfiguration": { + "type": "object", + "properties": { + "licenseeCharges": { + "required": [ + "active", + "chargeAmount", + "chargeType" + ], + "type": "object", + "properties": { + "chargeType": { + "type": "string", + "description": "The type of transaction fee charge", + "enum": [ + "FLAT_FEE_PER_PRIVILEGE" + ] + }, + "active": { + "type": "boolean", + "description": "Whether the compact is charging licensees transaction fees" + }, + "chargeAmount": { + "minimum": 0, + "type": "number", + "description": "The amount to charge per privilege purchased" + } }, - "history": { - "type": "array", - "items": { - "required": [ - "compact", - "dateOfUpdate", - "jurisdiction", - "licenseType", - "previous", - "providerId", - "type", - "updateType", - "updatedValues" - ], + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "compactOperationsTeamEmails": { + "maxItems": 10, + "minItems": 1, + "uniqueItems": true, + "type": "array", + "description": "List of email addresses for operations team notifications", + "items": { + "type": "string", + "format": "email" + } + } + }, + "additionalProperties": false + }, + "SandboLiceno4zXe3APQ07E": { + "required": [ + "enabled" + ], + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Whether the feature flag is enabled" + } + } + }, + "SandboLicenwjDvDRZGRaqT": { + "required": [ + "effectiveLiftDate" + ], + "type": "object", + "properties": { + "effectiveLiftDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "description": "The effective date when the encumbrance will be lifted", + "format": "date" + } + }, + "additionalProperties": false + }, + "SandboLicenfM0YyXB9i4El": { + "type": "array", + "items": { + "required": [ + "compact", + "jurisdictionName", + "postalAbbreviation" + ], + "type": "object", + "properties": { + "postalAbbreviation": { + "type": "string", + "description": "The postal abbreviation of the jurisdiction" + }, + "compact": { + "type": "string" + }, + "jurisdictionName": { + "type": "string", + "description": "The name of the jurisdiction" + } + } + } + }, + "SandboLicenUTb3zNObrjW5": { + "required": [ + "deactivationNote" + ], + "type": "object", + "properties": { + "deactivationNote": { + "maxLength": 256, + "type": "string", + "description": "Note describing why the privilege is being deactivated" + } + }, + "additionalProperties": false + }, + "SandboLicenjksXkBC6cpMT": { + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "prevLastKey": { + "maxLength": 1024, + "minLength": 1, + "type": "object" + }, + "lastKey": { + "maxLength": 1024, + "minLength": 1, + "type": "object" + }, + "pageSize": { + "maximum": 100, + "minimum": 5, + "type": "integer" + } + } + }, + "users": { + "type": "array", + "items": { + "required": [ + "attributes", + "permissions", + "status", + "userId" + ], + "type": "object", + "properties": { + "permissions": { + "type": "object", + "additionalProperties": { "type": "object", "properties": { - "licenseType": { - "type": "string", - "enum": [ - "audiologist", - "speech-language pathologist", - "occupational therapist", - "occupational therapy assistant", - "licensed professional counselor" - ] - }, - "compact": { - "type": "string", - "enum": [ - "aslp", - "octp", - "coun" - ] - }, - "previous": { - "required": [ - "administratorSetStatus", - "dateOfExpiration", - "dateOfIssuance", - "dateOfRenewal", - "dateOfUpdate", - "licenseJurisdiction", - "privilegeId" - ], + "actions": { "type": "object", "properties": { - "administratorSetStatus": { - "type": "string", - "enum": [ - "active", - "inactive" - ] + "readPrivate": { + "type": "boolean" }, - "dateOfExpiration": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" + "admin": { + "type": "boolean" }, - "licenseJurisdiction": { - "type": "string", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "privilegeId": { - "type": "string" - }, - "dateOfRenewal": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "dateOfIssuance": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" + "readSSN": { + "type": "boolean" } } }, - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string" - }, - "jurisdiction": { - "type": "string", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "updatedValues": { + "jurisdictions": { "type": "object", - "properties": { - "administratorSetStatus": { - "type": "string", - "enum": [ - "active", - "inactive" - ] - }, - "dateOfExpiration": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "licenseJurisdiction": { - "type": "string", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "privilegeId": { - "type": "string" - }, - "dateOfRenewal": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "dateOfIssuance": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" + "additionalProperties": { + "type": "object", + "properties": { + "actions": { + "type": "object", + "properties": { + "readPrivate": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "write": { + "type": "boolean" + }, + "readSSN": { + "type": "boolean" + } + }, + "additionalProperties": false + } } } - }, - "type": { - "type": "string", - "enum": [ - "privilegeUpdate" - ] - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "updateType": { - "type": "string", - "enum": [ - "deactivation", - "expiration", - "issuance", - "other", - "renewal", - "encumbrance", - "homeJurisdictionChange", - "registration", - "lifting_encumbrance", - "licenseDeactivation", - "emailChange" - ] } - } + }, + "additionalProperties": false } }, - "type": { - "type": "string", - "enum": [ - "privilege" - ] - }, - "dateOfIssuance": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "licenseType": { - "type": "string", - "enum": [ - "audiologist", - "speech-language pathologist", - "occupational therapist", - "occupational therapy assistant", - "licensed professional counselor" - ] - }, - "administratorSetStatus": { - "type": "string", - "enum": [ - "active", - "inactive" - ] - }, - "dateOfExpiration": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "privilegeId": { - "type": "string" - }, - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string" - }, - "dateOfRenewal": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "adverseActions": { - "type": "array", - "items": { - "required": [ - "actionAgainst", - "adverseActionId", - "compact", - "creationDate", - "dateOfUpdate", - "effectiveStartDate", - "jurisdiction", - "licenseType", - "licenseTypeAbbreviation", - "providerId", - "type" - ], - "type": "object", - "properties": { - "licenseType": { - "type": "string" - }, - "compact": { - "type": "string", - "enum": [ - "aslp", - "octp", - "coun" - ] - }, - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string" - }, - "jurisdiction": { - "type": "string", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "effectiveStartDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "licenseTypeAbbreviation": { - "type": "string" - }, - "adverseActionId": { - "type": "string" - }, - "effectiveLiftDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "type": { - "type": "string", - "enum": [ - "adverseAction" - ] - }, - "creationDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "actionAgainst": { - "type": "string" - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - } + "attributes": { + "required": [ + "email", + "familyName", + "givenName" + ], + "type": "object", + "properties": { + "givenName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "familyName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "email": { + "maxLength": 100, + "minLength": 5, + "type": "string" } - } + }, + "additionalProperties": false }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" + "userId": { + "type": "string" }, "status": { "type": "string", @@ -4499,828 +3698,366 @@ "inactive" ] } - } + }, + "additionalProperties": false } - }, - "licenseJurisdiction": { - "type": "string", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "compact": { - "type": "string", - "enum": [ - "aslp", - "octp", - "coun" - ] - }, - "npi": { - "pattern": "^[0-9]{10}$", - "type": "string" - }, - "givenName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "privilegeJurisdictions": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - } - }, - "type": { - "type": "string", - "enum": [ - "provider" - ] - }, - "suffix": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "currentHomeJurisdiction": { - "type": "string", - "description": "The current jurisdiction postal abbreviation if known.", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy", - "other", - "unknown" - ] - }, - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string" - }, - "familyName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "middleName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" } - } + }, + "additionalProperties": false }, - "SandboLicenI2vqm7fRdSBi": { + "SandboLicenuLEzkOrUfJeb": { "required": [ - "items", - "pagination" + "attributes", + "permissions", + "status", + "userId" ], "type": "object", "properties": { - "pagination": { + "permissions": { "type": "object", - "properties": { - "prevLastKey": { - "maxLength": 1024, - "minLength": 1, - "type": "object" - }, - "lastKey": { - "maxLength": 1024, - "minLength": 1, - "type": "object" - }, - "pageSize": { - "maximum": 100, - "minimum": 5, - "type": "integer" - } - } - }, - "items": { - "maxLength": 100, - "type": "array", - "items": { + "additionalProperties": { "type": "object", - "oneOf": [ - { - "required": [ - "compactAbbr", - "compactCommissionFee", - "compactName", - "isSandbox", - "paymentProcessorPublicFields", - "transactionFeeConfiguration", - "type" - ], + "properties": { + "actions": { "type": "object", "properties": { - "compactCommissionFee": { - "required": [ - "feeAmount", - "feeType" - ], - "type": "object", - "properties": { - "feeAmount": { - "type": "number" - }, - "feeType": { - "type": "string", - "enum": [ - "FLAT_RATE" - ] - } - } - }, - "compactAbbr": { - "type": "string", - "description": "The abbreviation of the compact" - }, - "paymentProcessorPublicFields": { - "required": [ - "apiLoginId", - "publicClientKey" - ], - "type": "object", - "properties": { - "publicClientKey": { - "type": "string", - "description": "The public client key for the payment processor" - }, - "apiLoginId": { - "type": "string", - "description": "The API login ID for the payment processor" - } - } - }, - "type": { - "type": "string", - "enum": [ - "compact" - ] - }, - "transactionFeeConfiguration": { - "required": [ - "licenseeCharges" - ], - "type": "object", - "properties": { - "licenseeCharges": { - "required": [ - "active", - "chargeAmount", - "chargeType" - ], - "type": "object", - "properties": { - "chargeType": { - "type": "string", - "description": "The type of transaction fee charge", - "enum": [ - "FLAT_FEE_PER_PRIVILEGE" - ] - }, - "active": { - "type": "boolean", - "description": "Whether the compact is charging licensees transaction fees" - }, - "chargeAmount": { - "type": "number", - "description": "The amount to charge per privilege purchased" - } - } - } - } + "readPrivate": { + "type": "boolean" }, - "isSandbox": { - "type": "boolean", - "description": "Whether the compact is in sandbox mode" + "admin": { + "type": "boolean" }, - "compactName": { - "type": "string", - "description": "The full name of the compact" + "readSSN": { + "type": "boolean" } } }, - { - "required": [ - "jurisdictionName", - "jurisprudenceRequirements", - "postalAbbreviation", - "privilegeFees", - "type" - ], + "jurisdictions": { "type": "object", - "properties": { - "privilegeFees": { - "type": "array", - "description": "The fees for the privileges", - "items": { - "required": [ - "amount", - "licenseTypeAbbreviation" - ], + "additionalProperties": { + "type": "object", + "properties": { + "actions": { "type": "object", "properties": { - "amount": { - "type": "number" + "readPrivate": { + "type": "boolean" }, - "militaryRate": { - "description": "Optional military rate for the privilege fee.", - "oneOf": [ - { - "minimum": 0, - "type": "number" - }, - null - ] + "admin": { + "type": "boolean" }, - "licenseTypeAbbreviation": { - "type": "string" + "write": { + "type": "boolean" + }, + "readSSN": { + "type": "boolean" } - } - } - }, - "postalAbbreviation": { - "type": "string", - "description": "The postal abbreviation of the jurisdiction" - }, - "jurisprudenceRequirements": { - "required": [ - "required" - ], - "type": "object", - "properties": { - "linkToDocumentation": { - "description": "Optional link to jurisprudence documentation", - "oneOf": [ - { - "type": "string" - }, - null - ] }, - "required": { - "type": "boolean", - "description": "Whether jurisprudence requirements exist" - } + "additionalProperties": false } - }, - "jurisdictionName": { - "type": "string", - "description": "The name of the jurisdiction" - }, - "type": { - "type": "string", - "enum": [ - "jurisdiction" - ] } } } - ] + }, + "additionalProperties": false } + }, + "attributes": { + "required": [ + "email", + "familyName", + "givenName" + ], + "type": "object", + "properties": { + "givenName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "familyName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "email": { + "maxLength": 100, + "minLength": 5, + "type": "string" + } + }, + "additionalProperties": false + }, + "userId": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "active", + "inactive" + ] } - } + }, + "additionalProperties": false }, - "SandboLicenLPepHoMLi1aj": { + "SandboLicenOJHHzc75m2Dh": { "required": [ - "apiLoginId", - "processor", - "transactionKey" + "affiliationType", + "fileNames" ], "type": "object", "properties": { - "apiLoginId": { - "maxLength": 100, - "minLength": 1, - "type": "string", - "description": "The api login id for the payment processor" - }, - "transactionKey": { - "maxLength": 100, - "minLength": 1, - "type": "string", - "description": "The transaction key for the payment processor" - }, - "processor": { + "affiliationType": { "type": "string", - "description": "The type of payment processor", + "description": "The type of military affiliation", "enum": [ - "authorize.net" + "militaryMember", + "militaryMemberSpouse" ] + }, + "fileNames": { + "type": "array", + "description": "List of military affiliation file names", + "items": { + "maxLength": 150, + "type": "string", + "description": "The name of the file being uploaded" + } } }, "additionalProperties": false }, - "SandboLicenrzUhY3WW0Y7L": { + "SandboLicen14sjN2dXfQbr": { "required": [ - "compactAdverseActionsNotificationEmails", - "compactCommissionFee", - "compactOperationsTeamEmails", - "compactSummaryReportNotificationEmails", - "configuredStates", - "licenseeRegistrationEnabled" + "query" ], "type": "object", "properties": { - "configuredStates": { - "type": "array", - "description": "List of states that have submitted configurations and their live status", - "items": { - "required": [ - "isLive", - "postalAbbreviation" - ], - "type": "object", - "properties": { - "postalAbbreviation": { - "type": "string", - "description": "The postal abbreviation of the jurisdiction", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "isLive": { - "type": "boolean", - "description": "Whether the state is live and available for registrations." - } + "pagination": { + "type": "object", + "properties": { + "lastKey": { + "maxLength": 1024, + "minLength": 1, + "type": "string" }, - "additionalProperties": false - } + "pageSize": { + "maximum": 100, + "minimum": 5, + "type": "integer" + } + }, + "additionalProperties": false }, - "compactCommissionFee": { - "required": [ - "feeAmount", - "feeType" - ], + "query": { "type": "object", "properties": { - "feeAmount": { - "minimum": 0, - "type": "number" + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string", + "description": "Internal UUID for the provider" }, - "feeType": { + "jurisdiction": { "type": "string", + "description": "Filter for providers with privilege/license in a jurisdiction", "enum": [ - "FLAT_RATE" + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" ] + }, + "givenName": { + "maxLength": 100, + "type": "string", + "description": "Filter for providers with a given name (familyName is required if givenName is provided)" + }, + "familyName": { + "maxLength": 100, + "type": "string", + "description": "Filter for providers with a family name" } }, - "additionalProperties": false - }, - "compactSummaryReportNotificationEmails": { - "maxItems": 10, - "minItems": 1, - "uniqueItems": true, - "type": "array", - "description": "List of email addresses for summary report notifications", - "items": { - "type": "string", - "format": "email" - } - }, - "compactAdverseActionsNotificationEmails": { - "maxItems": 10, - "minItems": 1, - "uniqueItems": true, - "type": "array", - "description": "List of email addresses for adverse actions notifications", - "items": { - "type": "string", - "format": "email" - } - }, - "licenseeRegistrationEnabled": { - "type": "boolean", - "description": "Denotes whether licensee registration is enabled" + "additionalProperties": false, + "description": "The query parameters" }, - "transactionFeeConfiguration": { + "sorting": { + "required": [ + "key" + ], "type": "object", "properties": { - "licenseeCharges": { - "required": [ - "active", - "chargeAmount", - "chargeType" - ], - "type": "object", - "properties": { - "chargeType": { - "type": "string", - "description": "The type of transaction fee charge", - "enum": [ - "FLAT_FEE_PER_PRIVILEGE" - ] - }, - "active": { - "type": "boolean", - "description": "Whether the compact is charging licensees transaction fees" - }, - "chargeAmount": { - "minimum": 0, - "type": "number", - "description": "The amount to charge per privilege purchased" - } - }, - "additionalProperties": false + "key": { + "type": "string", + "description": "The key to sort results by", + "enum": [ + "dateOfUpdate", + "familyName" + ] + }, + "direction": { + "type": "string", + "description": "Direction to sort results by", + "enum": [ + "ascending", + "descending" + ] } }, - "additionalProperties": false - }, - "compactOperationsTeamEmails": { - "maxItems": 10, - "minItems": 1, - "uniqueItems": true, - "type": "array", - "description": "List of email addresses for operations team notifications", - "items": { - "type": "string", - "format": "email" - } + "description": "How to sort results" } }, "additionalProperties": false }, - "SandboLicenPAsEF1Ia4s7g": { + "SandboLicen34TBFk9LdAJJ": { "required": [ - "deactivationNote" + "verificationCode" ], "type": "object", "properties": { - "deactivationNote": { - "maxLength": 256, + "verificationCode": { + "pattern": "^[0-9]{4}$", "type": "string", - "description": "Note describing why the privilege is being deactivated" + "description": "4-digit verification code" } }, "additionalProperties": false }, - "SandboLicen9LUz5xMGHXhV": { + "SandboLicenrZuAY9tZ4fCA": { "required": [ - "enabled" + "transactionId" ], "type": "object", "properties": { - "enabled": { - "type": "boolean", - "description": "Whether the feature flag is enabled" + "message": { + "type": "string", + "description": "A message about the transaction" + }, + "transactionId": { + "type": "string", + "description": "The transaction id for the purchase" } } }, - "SandboLicenLLx7v2Sq2Nku": { + "SandboLicenFBKwuejTjcRR": { "type": "object", "properties": { - "pagination": { - "type": "object", - "properties": { - "prevLastKey": { - "maxLength": 1024, - "minLength": 1, - "type": "object" - }, - "lastKey": { - "maxLength": 1024, - "minLength": 1, - "type": "object" - }, - "pageSize": { - "maximum": 100, - "minimum": 5, - "type": "integer" - } - } + "dateCreated": { + "type": "string", + "format": "date-time" }, - "users": { - "type": "array", - "items": { - "required": [ - "attributes", - "permissions", - "status", - "userId" - ], - "type": "object", - "properties": { - "permissions": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "actions": { - "type": "object", - "properties": { - "readPrivate": { - "type": "boolean" - }, - "admin": { - "type": "boolean" - }, - "readSSN": { - "type": "boolean" - } - } - }, - "jurisdictions": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "actions": { - "type": "object", - "properties": { - "readPrivate": { - "type": "boolean" - }, - "admin": { - "type": "boolean" - }, - "write": { - "type": "boolean" - }, - "readSSN": { - "type": "boolean" - } - }, - "additionalProperties": false - } - } - } - } - }, - "additionalProperties": false - } - }, - "attributes": { - "required": [ - "email", - "familyName", - "givenName" - ], - "type": "object", - "properties": { - "givenName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "familyName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "email": { - "maxLength": 100, - "minLength": 5, - "type": "string" - } - }, - "additionalProperties": false - }, - "userId": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "active", - "inactive" - ] - } - }, - "additionalProperties": false - } + "attestationId": { + "type": "string" + }, + "compact": { + "type": "string", + "enum": [ + "aslp", + "octp", + "coun" + ] + }, + "text": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "attestation" + ] + }, + "locale": { + "type": "string" + }, + "version": { + "type": "string" + }, + "required": { + "type": "boolean" } - }, - "additionalProperties": false + } + }, + "SandboLicenT1eMkx5ptE5k": { + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A message about the request" + } + } }, - "SandboLicenobivPmYh5SvH": { + "SandboLicen2TYOnVghC533": { "required": [ "compact", - "events", + "dob", + "familyName", + "givenName", "jurisdiction", "licenseType", - "privilegeId", - "providerId" + "partialSocial", + "password", + "recaptchaToken", + "username" ], "type": "object", "properties": { "licenseType": { "type": "string", + "description": "Type of license", "enum": [ "audiologist", "speech-language pathologist", @@ -5329,23 +4066,30 @@ "licensed professional counselor" ] }, + "password": { + "maxLength": 256, + "minLength": 12, + "type": "string", + "description": "Provider's current password" + }, "compact": { "type": "string", + "description": "Compact abbreviation", "enum": [ "aslp", "octp", "coun" ] }, - "privilegeId": { - "type": "string" - }, - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string" + "dob": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "description": "Date of birth in YYYY-MM-DD format", + "format": "date" }, "jurisdiction": { "type": "string", + "description": "Two-letter jurisdiction code", "enum": [ "al", "ak", @@ -5402,433 +4146,707 @@ "wy" ] }, - "events": { + "givenName": { + "maxLength": 200, + "minLength": 1, + "type": "string", + "description": "Provider's given name" + }, + "familyName": { + "maxLength": 200, + "minLength": 1, + "type": "string", + "description": "Provider's family name" + }, + "recaptchaToken": { + "minLength": 1, + "type": "string", + "description": "ReCAPTCHA token for verification" + }, + "partialSocial": { + "pattern": "^[0-9]{4}$", + "type": "string", + "description": "Last 4 digits of SSN" + }, + "username": { + "maxLength": 100, + "minLength": 5, + "type": "string", + "description": "Provider's email address (username)", + "format": "email" + } + }, + "additionalProperties": false + }, + "SandboLicenkPqluVn6dJHe": { + "required": [ + "compact", + "dateOfUpdate", + "familyName", + "givenName", + "licenseJurisdiction", + "privilegeJurisdictions", + "providerId", + "type" + ], + "type": "object", + "properties": { + "privileges": { "type": "array", "items": { "required": [ - "createDate", + "administratorSetStatus", + "compact", + "dateOfExpiration", + "dateOfIssuance", + "dateOfRenewal", "dateOfUpdate", - "effectiveDate", - "type", - "updateType" - ], + "jurisdiction", + "licenseJurisdiction", + "licenseType", + "privilegeId", + "providerId", + "status", + "type" + ], "type": "object", "properties": { - "note": { - "type": "string" - }, - "type": { + "licenseJurisdiction": { "type": "string", "enum": [ - "privilegeUpdate" + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" ] }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "effectiveDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "updateType": { + "compact": { "type": "string", "enum": [ - "deactivation", - "expiration", - "issuance", - "other", - "renewal", - "encumbrance", - "homeJurisdictionChange", - "registration", - "lifting_encumbrance", - "licenseDeactivation", - "emailChange" + "aslp", + "octp", + "coun" ] }, - "createDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "jurisdiction": { "type": "string", - "format": "date" - } - } - } - } - } - }, - "SandboLicenI4CqYMff5SWl": { - "type": "object", - "properties": { - "attributes": { - "type": "object", - "properties": { - "givenName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "familyName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - "SandboLiceng72nqBB23bmL": { - "required": [ - "transactionId" - ], - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "A message about the transaction" - }, - "transactionId": { - "type": "string", - "description": "The transaction id for the purchase" - } - } - }, - "SandboLicenJZNKekBSUCl5": { - "required": [ - "affiliationType", - "fileNames" - ], - "type": "object", - "properties": { - "affiliationType": { - "type": "string", - "description": "The type of military affiliation", - "enum": [ - "militaryMember", - "militaryMemberSpouse" - ] - }, - "fileNames": { - "type": "array", - "description": "List of military affiliation file names", - "items": { - "maxLength": 150, - "type": "string", - "description": "The name of the file being uploaded" - } - } - }, - "additionalProperties": false - }, - "SandboLicenbGNGFVLD0EDE": { - "required": [ - "compact", - "jurisdictionAdverseActionsNotificationEmails", - "jurisdictionName", - "jurisdictionOperationsTeamEmails", - "jurisdictionSummaryReportNotificationEmails", - "jurisprudenceRequirements", - "licenseeRegistrationEnabled", - "postalAbbreviation", - "privilegeFees" - ], - "type": "object", - "properties": { - "privilegeFees": { - "type": "array", - "description": "The fees for the privileges by license type", - "items": { - "required": [ - "amount", - "licenseTypeAbbreviation" - ], - "type": "object", - "properties": { - "amount": { - "type": "number" - }, - "militaryRate": { - "description": "Optional military rate for the privilege fee.", - "oneOf": [ - { - "minimum": 0, - "type": "number" - }, - null + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" ] }, - "licenseTypeAbbreviation": { - "type": "string", - "enum": [ - "aud", - "slp", - "ot", - "ota", - "lpc" - ] - } - } - } - }, - "postalAbbreviation": { - "type": "string", - "description": "The postal abbreviation of the jurisdiction" - }, - "jurisdictionAdverseActionsNotificationEmails": { - "type": "array", - "description": "List of email addresses for adverse actions notifications", - "items": { - "type": "string", - "format": "email" - } - }, - "jurisdictionOperationsTeamEmails": { - "type": "array", - "description": "List of email addresses for operations team notifications", - "items": { - "type": "string", - "format": "email" - } - }, - "compact": { - "type": "string", - "description": "The compact this jurisdiction configuration belongs to", - "enum": [ - "aslp", - "octp", - "coun" - ] - }, - "jurisprudenceRequirements": { - "required": [ - "required" - ], - "type": "object", - "properties": { - "linkToDocumentation": { - "description": "Optional link to jurisprudence documentation", - "oneOf": [ - { - "type": "string" - }, - null - ] - }, - "required": { - "type": "boolean", - "description": "Whether jurisprudence requirements exist" - } - } - }, - "licenseeRegistrationEnabled": { - "type": "boolean", - "description": "Denotes whether licensee registration is enabled" - }, - "jurisdictionName": { - "type": "string", - "description": "The name of the jurisdiction" - }, - "jurisdictionSummaryReportNotificationEmails": { - "type": "array", - "description": "List of email addresses for summary report notifications", - "items": { - "type": "string", - "format": "email" - } - } - } - }, - "SandboLicenC1PiOZAh5Usx": { - "type": "object", - "properties": { - "permissions": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "actions": { - "type": "object", - "properties": { - "readPrivate": { - "type": "boolean" - }, - "admin": { - "type": "boolean" - }, - "readSSN": { - "type": "boolean" - } - } - }, - "jurisdictions": { - "type": "object", - "additionalProperties": { + "history": { + "type": "array", + "items": { + "required": [ + "compact", + "dateOfUpdate", + "jurisdiction", + "licenseType", + "previous", + "providerId", + "type", + "updateType", + "updatedValues" + ], "type": "object", "properties": { - "actions": { + "licenseType": { + "type": "string", + "enum": [ + "audiologist", + "speech-language pathologist", + "occupational therapist", + "occupational therapy assistant", + "licensed professional counselor" + ] + }, + "compact": { + "type": "string", + "enum": [ + "aslp", + "octp", + "coun" + ] + }, + "previous": { + "required": [ + "administratorSetStatus", + "dateOfExpiration", + "dateOfIssuance", + "dateOfRenewal", + "dateOfUpdate", + "licenseJurisdiction", + "privilegeId" + ], "type": "object", "properties": { - "readPrivate": { - "type": "boolean" + "administratorSetStatus": { + "type": "string", + "enum": [ + "active", + "inactive" + ] }, - "admin": { - "type": "boolean" + "dateOfExpiration": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" }, - "write": { - "type": "boolean" + "licenseJurisdiction": { + "type": "string", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] }, - "readSSN": { - "type": "boolean" + "privilegeId": { + "type": "string" + }, + "dateOfRenewal": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "dateOfIssuance": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" } - }, - "additionalProperties": false - } - } - } - } - }, - "additionalProperties": false - } - } - }, - "additionalProperties": false - }, - "SandboLicenHcuQxywUvhOh": { - "type": "object", - "properties": { - "dateCreated": { - "type": "string", - "format": "date-time" - }, - "attestationId": { - "type": "string" - }, - "compact": { - "type": "string", - "enum": [ - "aslp", - "octp", - "coun" - ] - }, - "text": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "attestation" - ] - }, - "locale": { - "type": "string" - }, - "version": { - "type": "string" - }, - "required": { - "type": "boolean" - } - } - }, - "SandboLicenDb8Dl04rAoPD": { - "required": [ - "attributes", - "permissions" - ], - "type": "object", - "properties": { - "permissions": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "actions": { - "type": "object", - "properties": { - "readPrivate": { - "type": "boolean" - }, - "admin": { - "type": "boolean" - }, - "readSSN": { - "type": "boolean" - } - } - }, - "jurisdictions": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "actions": { + } + }, + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string" + }, + "jurisdiction": { + "type": "string", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] + }, + "updatedValues": { "type": "object", "properties": { - "readPrivate": { - "type": "boolean" + "administratorSetStatus": { + "type": "string", + "enum": [ + "active", + "inactive" + ] }, - "admin": { - "type": "boolean" + "dateOfExpiration": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" }, - "write": { - "type": "boolean" + "licenseJurisdiction": { + "type": "string", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] }, - "readSSN": { - "type": "boolean" + "privilegeId": { + "type": "string" + }, + "dateOfRenewal": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "dateOfIssuance": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" } - }, - "additionalProperties": false + } + }, + "type": { + "type": "string", + "enum": [ + "privilegeUpdate" + ] + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "updateType": { + "type": "string", + "enum": [ + "deactivation", + "expiration", + "issuance", + "other", + "renewal", + "encumbrance", + "homeJurisdictionChange", + "registration", + "lifting_encumbrance", + "licenseDeactivation", + "emailChange" + ] } } } - } - }, - "additionalProperties": false - } - }, - "attributes": { - "required": [ - "email", - "familyName", - "givenName" - ], - "type": "object", - "properties": { - "givenName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "familyName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "email": { - "maxLength": 100, - "minLength": 5, - "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "privilege" + ] + }, + "dateOfIssuance": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "licenseType": { + "type": "string", + "enum": [ + "audiologist", + "speech-language pathologist", + "occupational therapist", + "occupational therapy assistant", + "licensed professional counselor" + ] + }, + "administratorSetStatus": { + "type": "string", + "enum": [ + "active", + "inactive" + ] + }, + "dateOfExpiration": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "privilegeId": { + "type": "string" + }, + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string" + }, + "dateOfRenewal": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "adverseActions": { + "type": "array", + "items": { + "required": [ + "actionAgainst", + "adverseActionId", + "compact", + "creationDate", + "dateOfUpdate", + "effectiveStartDate", + "jurisdiction", + "licenseType", + "licenseTypeAbbreviation", + "providerId", + "type" + ], + "type": "object", + "properties": { + "licenseType": { + "type": "string" + }, + "compact": { + "type": "string", + "enum": [ + "aslp", + "octp", + "coun" + ] + }, + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string" + }, + "jurisdiction": { + "type": "string", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] + }, + "effectiveStartDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "licenseTypeAbbreviation": { + "type": "string" + }, + "adverseActionId": { + "type": "string" + }, + "effectiveLiftDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "type": { + "type": "string", + "enum": [ + "adverseAction" + ] + }, + "creationDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "actionAgainst": { + "type": "string" + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + } + } + } + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "status": { + "type": "string", + "enum": [ + "active", + "inactive" + ] + } } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - "SandboLicen8QcYRI7AzDyX": { - "required": [ - "jurisdiction" - ], - "type": "object", - "properties": { - "jurisdiction": { + } + }, + "licenseJurisdiction": { "type": "string", - "description": "The jurisdiction postal abbreviation to set as home jurisdiction", "enum": [ "al", "ak", @@ -5882,90 +4900,30 @@ "wa", "wv", "wi", - "wy", - "other" + "wy" ] - } - }, - "additionalProperties": false - }, - "SandboLicenBWZgN83iyevY": { - "required": [ - "attestations", - "licenseType", - "orderInformation", - "selectedJurisdictions" - ], - "type": "object", - "properties": { - "licenseType": { + }, + "compact": { "type": "string", - "description": "The type of license the provider is purchasing a privilege for.", "enum": [ - "audiologist", - "speech-language pathologist", - "occupational therapist", - "occupational therapy assistant", - "licensed professional counselor" + "aslp", + "octp", + "coun" ] }, - "attestations": { - "type": "array", - "description": "List of attestations that the user has agreed to", - "items": { - "required": [ - "attestationId", - "version" - ], - "type": "object", - "properties": { - "attestationId": { - "maxLength": 100, - "type": "string", - "description": "The ID of the attestation" - }, - "version": { - "maxLength": 10, - "pattern": "^\\d+$", - "type": "string", - "description": "The version of the attestation" - } - } - } + "npi": { + "pattern": "^[0-9]{10}$", + "type": "string" }, - "orderInformation": { - "required": [ - "opaqueData" - ], - "type": "object", - "properties": { - "opaqueData": { - "required": [ - "dataDescriptor", - "dataValue" - ], - "type": "object", - "properties": { - "dataValue": { - "maxLength": 1000, - "type": "string", - "description": "The opaque data value token returned by Authorize.Net Accept UI" - }, - "dataDescriptor": { - "maxLength": 100, - "type": "string", - "description": "The opaque data descriptor returned by Authorize.Net Accept UI" - } - } - } - } + "givenName": { + "maxLength": 100, + "minLength": 1, + "type": "string" }, - "selectedJurisdictions": { - "maxLength": 20, + "privilegeJurisdictions": { "type": "array", "items": { "type": "string", - "description": "Jurisdictions a provider has selected to purchase privileges in.", "enum": [ "al", "ak", @@ -6022,577 +4980,471 @@ "wy" ] } + }, + "type": { + "type": "string", + "enum": [ + "provider" + ] + }, + "suffix": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "currentHomeJurisdiction": { + "type": "string", + "description": "The current jurisdiction postal abbreviation if known.", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy", + "other", + "unknown" + ] + }, + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string" + }, + "familyName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "middleName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" } } }, - "SandboLicenBxfAXNgCl0f1": { + "SandboLicenaLbwv28ZqyH6": { "required": [ - "compactAbbr", - "compactAdverseActionsNotificationEmails", - "compactCommissionFee", - "compactName", - "compactOperationsTeamEmails", - "compactSummaryReportNotificationEmails", - "configuredStates", - "licenseeRegistrationEnabled" + "message" ], "type": "object", "properties": { - "configuredStates": { - "type": "array", - "description": "List of states that have submitted configurations and their live status", - "items": { - "required": [ - "isLive", - "postalAbbreviation" - ], - "type": "object", - "properties": { - "postalAbbreviation": { - "type": "string", - "description": "The postal abbreviation of the jurisdiction", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "isLive": { - "type": "boolean", - "description": "Whether the state is live and available for registrations." - } - } - } + "message": { + "type": "string", + "description": "A message about the request" + } + } + }, + "SandboLicen74bwm5yy6E5W": { + "required": [ + "apiLoginId", + "processor", + "transactionKey" + ], + "type": "object", + "properties": { + "apiLoginId": { + "maxLength": 100, + "minLength": 1, + "type": "string", + "description": "The api login id for the payment processor" }, - "compactCommissionFee": { - "required": [ - "feeAmount", - "feeType" - ], - "type": "object", - "properties": { - "feeAmount": { - "type": "number" - }, - "feeType": { - "type": "string", - "enum": [ - "FLAT_RATE" - ] - } - } - }, - "compactSummaryReportNotificationEmails": { - "type": "array", - "description": "List of email addresses for summary report notifications", - "items": { - "type": "string", - "format": "email" - } - }, - "compactAdverseActionsNotificationEmails": { - "type": "array", - "description": "List of email addresses for adverse actions notifications", - "items": { - "type": "string", - "format": "email" - } - }, - "licenseeRegistrationEnabled": { - "type": "boolean", - "description": "Denotes whether licensee registration is enabled" - }, - "compactAbbr": { + "transactionKey": { + "maxLength": 100, + "minLength": 1, "type": "string", - "description": "The abbreviation of the compact" - }, - "transactionFeeConfiguration": { - "type": "object", - "properties": { - "licenseeCharges": { - "required": [ - "active", - "chargeAmount", - "chargeType" - ], - "type": "object", - "properties": { - "chargeType": { - "type": "string", - "description": "The type of transaction fee charge", - "enum": [ - "FLAT_FEE_PER_PRIVILEGE" - ] - }, - "active": { - "type": "boolean", - "description": "Whether the compact is charging licensees transaction fees" - }, - "chargeAmount": { - "type": "number", - "description": "The amount to charge per privilege purchased" - } - } - } - } + "description": "The transaction key for the payment processor" }, - "compactName": { + "processor": { "type": "string", - "description": "The full name of the compact" - }, - "compactOperationsTeamEmails": { - "type": "array", - "description": "List of email addresses for operations team notifications", - "items": { - "type": "string", - "format": "email" - } + "description": "The type of payment processor", + "enum": [ + "authorize.net" + ] } - } + }, + "additionalProperties": false }, - "SandboLiceno12FSfDWBzow": { + "SandboLicenZVm9nad5vQW4": { "required": [ - "pagination", - "providers" + "compact", + "events", + "jurisdiction", + "licenseType", + "privilegeId", + "providerId" ], "type": "object", "properties": { - "pagination": { - "type": "object", - "properties": { - "prevLastKey": { - "maxLength": 1024, - "minLength": 1, - "type": "object" - }, - "lastKey": { - "maxLength": 1024, - "minLength": 1, - "type": "object" - }, - "pageSize": { - "maximum": 100, - "minimum": 5, - "type": "integer" - } - } + "licenseType": { + "type": "string", + "enum": [ + "audiologist", + "speech-language pathologist", + "occupational therapist", + "occupational therapy assistant", + "licensed professional counselor" + ] }, - "sorting": { - "required": [ - "key" - ], - "type": "object", - "properties": { - "key": { - "type": "string", - "description": "The key to sort results by", - "enum": [ - "dateOfUpdate", - "familyName" - ] - }, - "direction": { - "type": "string", - "description": "Direction to sort results by", - "enum": [ - "ascending", - "descending" - ] - } - }, - "description": "How to sort results" + "compact": { + "type": "string", + "enum": [ + "aslp", + "octp", + "coun" + ] }, - "providers": { - "maxLength": 100, + "privilegeId": { + "type": "string" + }, + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string" + }, + "jurisdiction": { + "type": "string", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] + }, + "events": { "type": "array", "items": { "required": [ - "birthMonthDay", - "compact", - "compactEligibility", - "dateOfExpiration", + "createDate", "dateOfUpdate", - "familyName", - "givenName", - "jurisdictionUploadedCompactEligibility", - "jurisdictionUploadedLicenseStatus", - "licenseJurisdiction", - "licenseStatus", - "privilegeJurisdictions", - "providerId", - "type" + "effectiveDate", + "type", + "updateType" ], "type": "object", "properties": { - "licenseJurisdiction": { + "note": { + "type": "string" + }, + "type": { "type": "string", "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" + "privilegeUpdate" ] }, - "compact": { + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", "type": "string", - "enum": [ - "aslp", - "octp", - "coun" - ] - }, - "npi": { - "pattern": "^[0-9]{10}$", - "type": "string" - }, - "givenName": { - "maxLength": 100, - "minLength": 1, - "type": "string" + "format": "date" }, - "compactEligibility": { + "effectiveDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", "type": "string", - "enum": [ - "eligible", - "ineligible" - ] + "format": "date" }, - "jurisdictionUploadedCompactEligibility": { + "updateType": { "type": "string", "enum": [ - "eligible", - "ineligible" + "deactivation", + "expiration", + "issuance", + "other", + "renewal", + "encumbrance", + "homeJurisdictionChange", + "registration", + "lifting_encumbrance", + "licenseDeactivation", + "emailChange" ] }, - "dateOfBirth": { + "createDate": { "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", "type": "string", "format": "date" + } + } + } + } + } + }, + "SandboLicen3QxrBb8JFDnT": { + "required": [ + "encumbranceEffectiveDate", + "encumbranceType" + ], + "type": "object", + "properties": { + "encumbranceEffectiveDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "description": "The effective date of the encumbrance", + "format": "date" + }, + "clinicalPrivilegeActionCategories": { + "type": "array", + "description": "The categories of clinical privilege action", + "items": { + "type": "string" + } + }, + "encumbranceType": { + "type": "string", + "description": "The type of encumbrance", + "enum": [ + "fine", + "reprimand", + "required supervision", + "completion of continuing education", + "public reprimand", + "probation", + "injunctive action", + "suspension", + "revocation", + "denial", + "surrender of license", + "modification of previous action-extension", + "modification of previous action-reduction", + "other monitoring", + "other adjudicated action not listed" + ] + }, + "clinicalPrivilegeActionCategory": { + "type": "string", + "description": "(Deprecated) The category of clinical privilege action. Use clinicalPrivilegeActionCategories instead." + } + }, + "additionalProperties": false + }, + "SandboLicene2a50HkoiVOX": { + "required": [ + "compact", + "jurisdictionAdverseActionsNotificationEmails", + "jurisdictionName", + "jurisdictionOperationsTeamEmails", + "jurisdictionSummaryReportNotificationEmails", + "jurisprudenceRequirements", + "licenseeRegistrationEnabled", + "postalAbbreviation", + "privilegeFees" + ], + "type": "object", + "properties": { + "privilegeFees": { + "type": "array", + "description": "The fees for the privileges by license type", + "items": { + "required": [ + "amount", + "licenseTypeAbbreviation" + ], + "type": "object", + "properties": { + "amount": { + "type": "number" }, - "jurisdictionUploadedLicenseStatus": { - "type": "string", - "enum": [ - "active", - "inactive" + "militaryRate": { + "description": "Optional military rate for the privilege fee.", + "oneOf": [ + { + "minimum": 0, + "type": "number" + }, + null ] }, - "privilegeJurisdictions": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - } - }, - "type": { + "licenseTypeAbbreviation": { "type": "string", "enum": [ - "provider" + "aud", + "slp", + "ot", + "ota", + "lpc" ] - }, - "suffix": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "currentHomeJurisdiction": { - "type": "string", - "description": "The current jurisdiction postal abbreviation if known.", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy", - "other", - "unknown" - ] - }, - "ssnLastFour": { - "pattern": "^[0-9]{4}$", - "type": "string" - }, - "dateOfExpiration": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string" - }, - "licenseStatus": { - "type": "string", - "enum": [ - "active", - "inactive" - ] - }, - "familyName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "middleName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "birthMonthDay": { - "pattern": "^[01]{1}[0-9]{1}-[0-3]{1}[0-9]{1}$", - "type": "string", - "format": "date" - }, - "compactConnectRegisteredEmailAddress": { - "maxLength": 100, - "minLength": 5, - "type": "string", - "format": "email" - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" } } } - } - } - }, - "SandboLicendERazg9NeEsA": { - "required": [ - "status" - ], - "type": "object", - "properties": { - "status": { + }, + "postalAbbreviation": { "type": "string", - "description": "The status to set the military affiliation to.", + "description": "The postal abbreviation of the jurisdiction" + }, + "jurisdictionAdverseActionsNotificationEmails": { + "type": "array", + "description": "List of email addresses for adverse actions notifications", + "items": { + "type": "string", + "format": "email" + } + }, + "jurisdictionOperationsTeamEmails": { + "type": "array", + "description": "List of email addresses for operations team notifications", + "items": { + "type": "string", + "format": "email" + } + }, + "compact": { + "type": "string", + "description": "The compact this jurisdiction configuration belongs to", "enum": [ - "inactive" + "aslp", + "octp", + "coun" ] + }, + "jurisprudenceRequirements": { + "required": [ + "required" + ], + "type": "object", + "properties": { + "linkToDocumentation": { + "description": "Optional link to jurisprudence documentation", + "oneOf": [ + { + "type": "string" + }, + null + ] + }, + "required": { + "type": "boolean", + "description": "Whether jurisprudence requirements exist" + } + } + }, + "licenseeRegistrationEnabled": { + "type": "boolean", + "description": "Denotes whether licensee registration is enabled" + }, + "jurisdictionName": { + "type": "string", + "description": "The name of the jurisdiction" + }, + "jurisdictionSummaryReportNotificationEmails": { + "type": "array", + "description": "List of email addresses for summary report notifications", + "items": { + "type": "string", + "format": "email" + } } - }, - "additionalProperties": false + } }, - "SandboLicenwoqrSnm0rsGM": { + "SandboLicenLhkhDxX4fiIg": { "required": [ - "compact", - "dob", - "email", - "familyName", - "givenName", - "jurisdiction", + "attestations", "licenseType", - "partialSocial", - "token" + "orderInformation", + "selectedJurisdictions" ], "type": "object", "properties": { "licenseType": { - "maxLength": 500, "type": "string", - "description": "Type of license", + "description": "The type of license the provider is purchasing a privilege for.", "enum": [ "audiologist", "speech-language pathologist", @@ -6601,123 +5453,139 @@ "licensed professional counselor" ] }, - "compact": { - "maxLength": 100, - "type": "string", - "description": "Compact name" - }, - "dob": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "description": "Date of birth in YYYY-MM-DD format" - }, - "givenName": { - "maxLength": 200, - "type": "string", - "description": "Provider's given name" + "attestations": { + "type": "array", + "description": "List of attestations that the user has agreed to", + "items": { + "required": [ + "attestationId", + "version" + ], + "type": "object", + "properties": { + "attestationId": { + "maxLength": 100, + "type": "string", + "description": "The ID of the attestation" + }, + "version": { + "maxLength": 10, + "pattern": "^\\d+$", + "type": "string", + "description": "The version of the attestation" + } + } + } }, - "familyName": { - "maxLength": 200, - "type": "string", - "description": "Provider's family name" + "orderInformation": { + "required": [ + "opaqueData" + ], + "type": "object", + "properties": { + "opaqueData": { + "required": [ + "dataDescriptor", + "dataValue" + ], + "type": "object", + "properties": { + "dataValue": { + "maxLength": 1000, + "type": "string", + "description": "The opaque data value token returned by Authorize.Net Accept UI" + }, + "dataDescriptor": { + "maxLength": 100, + "type": "string", + "description": "The opaque data descriptor returned by Authorize.Net Accept UI" + } + } + } + } }, - "jurisdiction": { - "maxLength": 2, - "minLength": 2, - "type": "string", - "description": "Two-letter jurisdiction code", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "partialSocial": { - "maxLength": 4, - "minLength": 4, - "type": "string", - "description": "Last 4 digits of SSN" - }, - "email": { - "maxLength": 100, - "minLength": 5, - "type": "string", - "description": "Provider's email address", - "format": "email" - }, - "token": { - "type": "string", - "description": "ReCAPTCHA token" + "selectedJurisdictions": { + "maxLength": 20, + "type": "array", + "items": { + "type": "string", + "description": "Jurisdictions a provider has selected to purchase privileges in.", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] + } } } }, - "SandboLicenaSmGZue6afyn": { + "SandboLicenDDeRKnGCOQFv": { "required": [ - "newEmailAddress" + "status" ], "type": "object", "properties": { - "newEmailAddress": { - "maxLength": 100, - "minLength": 5, + "status": { "type": "string", - "description": "The new email address to set for the provider", - "format": "email" + "description": "The status to set the military affiliation to.", + "enum": [ + "inactive" + ] } }, "additionalProperties": false }, - "SandboLicenr5TVmpxKfPGq": { + "SandboLicen6yHAPPYOdJ3t": { "required": [ "birthMonthDay", "compact", @@ -7491,7 +6359,6 @@ "required": [ "actionAgainst", "adverseActionId", - "clinicalPrivilegeActionCategory", "compact", "creationDate", "dateOfUpdate", @@ -7505,6 +6372,13 @@ ], "type": "object", "properties": { + "clinicalPrivilegeActionCategories": { + "type": "array", + "description": "The categories of clinical privilege action", + "items": { + "type": "string" + } + }, "compact": { "type": "string", "enum": [ @@ -8404,271 +7278,1236 @@ "type": "string", "format": "date" }, - "licenseStatus": { - "type": "string", - "enum": [ - "active", - "inactive" + "licenseStatus": { + "type": "string", + "enum": [ + "active", + "inactive" + ] + }, + "familyName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "homeAddressCity": { + "maxLength": 100, + "minLength": 2, + "type": "string" + }, + "licenseNumber": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "middleName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "licenseStatusName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + } + } + }, + "type": { + "type": "string", + "enum": [ + "licenseUpdate" + ] + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "updateType": { + "type": "string", + "enum": [ + "deactivation", + "expiration", + "issuance", + "other", + "renewal", + "encumbrance", + "homeJurisdictionChange", + "registration", + "lifting_encumbrance", + "licenseDeactivation", + "emailChange" + ] + } + } + } + }, + "ssnLastFour": { + "pattern": "^[0-9]{4}$", + "type": "string" + }, + "phoneNumber": { + "pattern": "^\\+[0-9]{8,15}$", + "type": "string" + }, + "licenseStatus": { + "type": "string", + "enum": [ + "active", + "inactive" + ] + }, + "middleName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "licenseStatusName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "adverseActions": { + "type": "array", + "items": { + "required": [ + "actionAgainst", + "adverseActionId", + "compact", + "creationDate", + "dateOfUpdate", + "effectiveStartDate", + "encumbranceType", + "jurisdiction", + "licenseType", + "licenseTypeAbbreviation", + "providerId", + "type" + ], + "type": "object", + "properties": { + "clinicalPrivilegeActionCategories": { + "type": "array", + "description": "The categories of clinical privilege action", + "items": { + "type": "string" + } + }, + "compact": { + "type": "string", + "enum": [ + "aslp", + "octp", + "coun" + ] + }, + "jurisdiction": { + "type": "string", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] + }, + "licenseTypeAbbreviation": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "adverseAction" + ] + }, + "creationDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "actionAgainst": { + "type": "string" + }, + "licenseType": { + "type": "string" + }, + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string" + }, + "effectiveStartDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "adverseActionId": { + "type": "string" + }, + "effectiveLiftDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "encumbranceType": { + "type": "string" + }, + "clinicalPrivilegeActionCategory": { + "type": "string" + }, + "liftingUser": { + "type": "string" + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + } + } + } + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + } + } + } + }, + "ssnLastFour": { + "pattern": "^[0-9]{4}$", + "type": "string" + }, + "dateOfExpiration": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "militaryAffiliations": { + "type": "array", + "items": { + "required": [ + "affiliationType", + "compact", + "dateOfUpdate", + "dateOfUpload", + "fileNames", + "providerId", + "status", + "type" + ], + "type": "object", + "properties": { + "dateOfUpload": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "compact": { + "type": "string", + "enum": [ + "aslp", + "octp", + "coun" + ] + }, + "downloadLinks": { + "type": "array", + "items": { + "required": [ + "fileName", + "url" + ], + "type": "object", + "properties": { + "fileName": { + "type": "string" + }, + "url": { + "type": "string" + } + } + } + }, + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string" + }, + "affiliationType": { + "type": "string", + "enum": [ + "militaryMember", + "militaryMemberSpouse" + ] + }, + "type": { + "type": "string", + "enum": [ + "militaryAffiliation" + ] + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + }, + "fileNames": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "string", + "enum": [ + "active", + "inactive" + ] + } + } + } + }, + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string" + }, + "licenseStatus": { + "type": "string", + "enum": [ + "active", + "inactive" + ] + }, + "familyName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "middleName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "birthMonthDay": { + "pattern": "^[01]{1}[0-9]{1}-[0-3]{1}[0-9]{1}$", + "type": "string", + "format": "date" + }, + "compactConnectRegisteredEmailAddress": { + "maxLength": 100, + "minLength": 5, + "type": "string", + "format": "email" + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "format": "date" + } + } + }, + "SandboLicenbmJo5pJTGNyk": { + "required": [ + "affiliationType", + "dateOfUpdate", + "dateOfUpload", + "documentUploadFields", + "status" + ], + "type": "object", + "properties": { + "dateOfUpload": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "description": "The date the document was uploaded", + "format": "date" + }, + "affiliationType": { + "type": "string", + "description": "The type of military affiliation", + "enum": [ + "militaryMember", + "militaryMemberSpouse" + ] + }, + "fileNames": { + "type": "array", + "description": "List of military affiliation file names", + "items": { + "type": "string", + "description": "The name of the file being uploaded" + } + }, + "dateOfUpdate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "description": "The date the document was last updated", + "format": "date" + }, + "status": { + "type": "string", + "description": "The status of the military affiliation" + }, + "documentUploadFields": { + "type": "array", + "description": "The fields used to upload documents", + "items": { + "type": "object", + "properties": { + "fields": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "The form fields used to upload the document" + }, + "url": { + "type": "string", + "description": "The url to upload the document to" + } + }, + "description": "The fields used to upload a specific document" + } + } + } + }, + "SandboLicenbvbpTeGqjAcZ": { + "required": [ + "compact", + "providerId", + "recaptchaToken", + "recoveryToken" + ], + "type": "object", + "properties": { + "compact": { + "type": "string", + "description": "Compact abbreviation", + "enum": [ + "aslp", + "octp", + "coun" + ] + }, + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string", + "description": "Provider UUID" + }, + "recaptchaToken": { + "minLength": 1, + "type": "string", + "description": "ReCAPTCHA token for verification" + }, + "recoveryToken": { + "maxLength": 256, + "minLength": 1, + "type": "string", + "description": "Recovery token from the email link" + } + }, + "additionalProperties": false + }, + "SandboLicenBqFE7Lkpte9Z": { + "required": [ + "items", + "pagination" + ], + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "prevLastKey": { + "maxLength": 1024, + "minLength": 1, + "type": "object" + }, + "lastKey": { + "maxLength": 1024, + "minLength": 1, + "type": "object" + }, + "pageSize": { + "maximum": 100, + "minimum": 5, + "type": "integer" + } + } + }, + "items": { + "maxLength": 100, + "type": "array", + "items": { + "type": "object", + "oneOf": [ + { + "required": [ + "compactAbbr", + "compactCommissionFee", + "compactName", + "isSandbox", + "paymentProcessorPublicFields", + "transactionFeeConfiguration", + "type" + ], + "type": "object", + "properties": { + "compactCommissionFee": { + "required": [ + "feeAmount", + "feeType" + ], + "type": "object", + "properties": { + "feeAmount": { + "type": "number" + }, + "feeType": { + "type": "string", + "enum": [ + "FLAT_RATE" + ] + } + } + }, + "compactAbbr": { + "type": "string", + "description": "The abbreviation of the compact" + }, + "paymentProcessorPublicFields": { + "required": [ + "apiLoginId", + "publicClientKey" + ], + "type": "object", + "properties": { + "publicClientKey": { + "type": "string", + "description": "The public client key for the payment processor" + }, + "apiLoginId": { + "type": "string", + "description": "The API login ID for the payment processor" + } + } + }, + "type": { + "type": "string", + "enum": [ + "compact" + ] + }, + "transactionFeeConfiguration": { + "required": [ + "licenseeCharges" + ], + "type": "object", + "properties": { + "licenseeCharges": { + "required": [ + "active", + "chargeAmount", + "chargeType" + ], + "type": "object", + "properties": { + "chargeType": { + "type": "string", + "description": "The type of transaction fee charge", + "enum": [ + "FLAT_FEE_PER_PRIVILEGE" + ] + }, + "active": { + "type": "boolean", + "description": "Whether the compact is charging licensees transaction fees" + }, + "chargeAmount": { + "type": "number", + "description": "The amount to charge per privilege purchased" + } + } + } + } + }, + "isSandbox": { + "type": "boolean", + "description": "Whether the compact is in sandbox mode" + }, + "compactName": { + "type": "string", + "description": "The full name of the compact" + } + } + }, + { + "required": [ + "jurisdictionName", + "jurisprudenceRequirements", + "postalAbbreviation", + "privilegeFees", + "type" + ], + "type": "object", + "properties": { + "privilegeFees": { + "type": "array", + "description": "The fees for the privileges", + "items": { + "required": [ + "amount", + "licenseTypeAbbreviation" + ], + "type": "object", + "properties": { + "amount": { + "type": "number" + }, + "militaryRate": { + "description": "Optional military rate for the privilege fee.", + "oneOf": [ + { + "minimum": 0, + "type": "number" + }, + null ] }, - "familyName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "homeAddressCity": { - "maxLength": 100, - "minLength": 2, + "licenseTypeAbbreviation": { "type": "string" + } + } + } + }, + "postalAbbreviation": { + "type": "string", + "description": "The postal abbreviation of the jurisdiction" + }, + "jurisprudenceRequirements": { + "required": [ + "required" + ], + "type": "object", + "properties": { + "linkToDocumentation": { + "description": "Optional link to jurisprudence documentation", + "oneOf": [ + { + "type": "string" + }, + null + ] + }, + "required": { + "type": "boolean", + "description": "Whether jurisprudence requirements exist" + } + } + }, + "jurisdictionName": { + "type": "string", + "description": "The name of the jurisdiction" + }, + "type": { + "type": "string", + "enum": [ + "jurisdiction" + ] + } + } + } + ] + } + } + } + }, + "SandboLicens8zWlw8e3VjA": { + "type": "object", + "properties": { + "permissions": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "actions": { + "type": "object", + "properties": { + "readPrivate": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "readSSN": { + "type": "boolean" + } + } + }, + "jurisdictions": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "actions": { + "type": "object", + "properties": { + "readPrivate": { + "type": "boolean" }, - "licenseNumber": { - "maxLength": 100, - "minLength": 1, - "type": "string" + "admin": { + "type": "boolean" }, - "middleName": { - "maxLength": 100, - "minLength": 1, - "type": "string" + "write": { + "type": "boolean" }, - "licenseStatusName": { - "maxLength": 100, - "minLength": 1, - "type": "string" + "readSSN": { + "type": "boolean" } - } - }, - "type": { - "type": "string", - "enum": [ - "licenseUpdate" - ] - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "updateType": { - "type": "string", - "enum": [ - "deactivation", - "expiration", - "issuance", - "other", - "renewal", - "encumbrance", - "homeJurisdictionChange", - "registration", - "lifting_encumbrance", - "licenseDeactivation", - "emailChange" - ] + }, + "additionalProperties": false } } } + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + }, + "SandboLicenGkLIz61xmgWo": { + "required": [ + "effectiveLiftDate" + ], + "type": "object", + "properties": { + "effectiveLiftDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "description": "The effective date when the encumbrance will be lifted", + "format": "date" + } + }, + "additionalProperties": false + }, + "SandboLicenQrINPgMnQioZ": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "properties": { + "givenName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "familyName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "SandboLicenS3OpuzvlfqIR": { + "type": "object", + "properties": { + "context": { + "type": "object", + "properties": { + "userId": { + "maxLength": 100, + "minLength": 1, + "type": "string", + "description": "Optional user ID for feature flag evaluation" + }, + "customAttributes": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Optional custom attributes for feature flag evaluation" + } + }, + "additionalProperties": false, + "description": "Optional context for feature flag evaluation" + } + }, + "additionalProperties": false + }, + "SandboLiceno1FF4B6IPNWg": { + "required": [ + "newEmailAddress" + ], + "type": "object", + "properties": { + "newEmailAddress": { + "maxLength": 100, + "minLength": 5, + "type": "string", + "description": "The new email address to set for the provider", + "format": "email" + } + }, + "additionalProperties": false + }, + "SandboLicen15BtNCg0ttcx": { + "required": [ + "attributes", + "permissions" + ], + "type": "object", + "properties": { + "permissions": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "actions": { + "type": "object", + "properties": { + "readPrivate": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "readSSN": { + "type": "boolean" + } + } }, - "ssnLastFour": { - "pattern": "^[0-9]{4}$", - "type": "string" - }, - "phoneNumber": { - "pattern": "^\\+[0-9]{8,15}$", - "type": "string" - }, - "licenseStatus": { - "type": "string", - "enum": [ - "active", - "inactive" - ] - }, - "middleName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "licenseStatusName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "adverseActions": { - "type": "array", - "items": { - "required": [ - "actionAgainst", - "adverseActionId", - "clinicalPrivilegeActionCategory", - "compact", - "creationDate", - "dateOfUpdate", - "effectiveStartDate", - "encumbranceType", - "jurisdiction", - "licenseType", - "licenseTypeAbbreviation", - "providerId", - "type" - ], + "jurisdictions": { + "type": "object", + "additionalProperties": { "type": "object", "properties": { - "compact": { - "type": "string", - "enum": [ - "aslp", - "octp", - "coun" - ] - }, - "jurisdiction": { - "type": "string", - "enum": [ - "al", - "ak", - "az", - "ar", - "ca", - "co", - "ct", - "de", - "dc", - "fl", - "ga", - "hi", - "id", - "il", - "in", - "ia", - "ks", - "ky", - "la", - "me", - "md", - "ma", - "mi", - "mn", - "ms", - "mo", - "mt", - "ne", - "nv", - "nh", - "nj", - "nm", - "ny", - "nc", - "nd", - "oh", - "ok", - "or", - "pa", - "pr", - "ri", - "sc", - "sd", - "tn", - "tx", - "ut", - "vt", - "va", - "vi", - "wa", - "wv", - "wi", - "wy" - ] - }, - "licenseTypeAbbreviation": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "adverseAction" - ] - }, - "creationDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "actionAgainst": { - "type": "string" - }, - "licenseType": { - "type": "string" - }, - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string" - }, - "effectiveStartDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "adverseActionId": { - "type": "string" - }, - "effectiveLiftDate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" - }, - "encumbranceType": { - "type": "string" - }, - "clinicalPrivilegeActionCategory": { - "type": "string" - }, - "liftingUser": { - "type": "string" - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" + "actions": { + "type": "object", + "properties": { + "readPrivate": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "write": { + "type": "boolean" + }, + "readSSN": { + "type": "boolean" + } + }, + "additionalProperties": false } } } - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" } + }, + "additionalProperties": false + } + }, + "attributes": { + "required": [ + "email", + "familyName", + "givenName" + ], + "type": "object", + "properties": { + "givenName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "familyName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "email": { + "maxLength": 100, + "minLength": 5, + "type": "string" } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "SandboLicenaFsmBhKzUkNI": { + "required": [ + "jurisdiction" + ], + "type": "object", + "properties": { + "jurisdiction": { + "type": "string", + "description": "The jurisdiction postal abbreviation to set as home jurisdiction", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy", + "other" + ] + } + }, + "additionalProperties": false + }, + "SandboLicenk1ql1I81jsMY": { + "required": [ + "encumbranceEffectiveDate", + "encumbranceType" + ], + "type": "object", + "properties": { + "encumbranceEffectiveDate": { + "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "type": "string", + "description": "The effective date of the encumbrance", + "format": "date" + }, + "clinicalPrivilegeActionCategories": { + "type": "array", + "description": "The categories of clinical privilege action", + "items": { + "type": "string" } }, - "ssnLastFour": { - "pattern": "^[0-9]{4}$", - "type": "string" + "encumbranceType": { + "type": "string", + "description": "The type of encumbrance", + "enum": [ + "fine", + "reprimand", + "required supervision", + "completion of continuing education", + "public reprimand", + "probation", + "injunctive action", + "suspension", + "revocation", + "denial", + "surrender of license", + "modification of previous action-extension", + "modification of previous action-reduction", + "other monitoring", + "other adjudicated action not listed" + ] }, - "dateOfExpiration": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "clinicalPrivilegeActionCategory": { "type": "string", - "format": "date" + "description": "(Deprecated) The category of clinical privilege action. Use clinicalPrivilegeActionCategories instead." + } + }, + "additionalProperties": false + }, + "SandboLicenxSf6anmMiZUl": { + "required": [ + "pagination", + "providers" + ], + "type": "object", + "properties": { + "pagination": { + "type": "object", + "properties": { + "prevLastKey": { + "maxLength": 1024, + "minLength": 1, + "type": "object" + }, + "lastKey": { + "maxLength": 1024, + "minLength": 1, + "type": "object" + }, + "pageSize": { + "maximum": 100, + "minimum": 5, + "type": "integer" + } + } }, - "militaryAffiliations": { + "query": { + "type": "object", + "properties": { + "providerId": { + "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", + "type": "string", + "description": "Internal UUID for the provider" + }, + "jurisdiction": { + "type": "string", + "description": "Filter for providers with privilege/license in a jurisdiction", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] + }, + "givenName": { + "maxLength": 100, + "type": "string", + "description": "Filter for providers with a given name" + }, + "familyName": { + "maxLength": 100, + "type": "string", + "description": "Filter for providers with a family name" + } + } + }, + "sorting": { + "required": [ + "key" + ], + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "The key to sort results by", + "enum": [ + "dateOfUpdate", + "familyName" + ] + }, + "direction": { + "type": "string", + "description": "Direction to sort results by", + "enum": [ + "ascending", + "descending" + ] + } + }, + "description": "How to sort results" + }, + "providers": { + "maxLength": 100, "type": "array", "items": { "required": [ - "affiliationType", "compact", - "dateOfUpdate", - "dateOfUpload", - "fileNames", + "familyName", + "givenName", + "licenseJurisdiction", + "privilegeJurisdictions", "providerId", - "status", "type" ], "type": "object", "properties": { - "dateOfUpload": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", + "licenseJurisdiction": { "type": "string", - "format": "date" + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] }, "compact": { "type": "string", @@ -8678,98 +8517,169 @@ "coun" ] }, - "downloadLinks": { - "type": "array", - "items": { - "required": [ - "fileName", - "url" - ], - "type": "object", - "properties": { - "fileName": { - "type": "string" - }, - "url": { - "type": "string" - } - } - } - }, "providerId": { "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", "type": "string" }, - "affiliationType": { + "npi": { + "pattern": "^[0-9]{10}$", + "type": "string" + }, + "givenName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "familyName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "middleName": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "privilegeJurisdictions": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy" + ] + } + }, + "type": { "type": "string", "enum": [ - "militaryMember", - "militaryMemberSpouse" + "provider" ] }, - "type": { + "suffix": { + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "currentHomeJurisdiction": { "type": "string", + "description": "The current jurisdiction postal abbreviation if known.", "enum": [ - "militaryAffiliation" + "al", + "ak", + "az", + "ar", + "ca", + "co", + "ct", + "de", + "dc", + "fl", + "ga", + "hi", + "id", + "il", + "in", + "ia", + "ks", + "ky", + "la", + "me", + "md", + "ma", + "mi", + "mn", + "ms", + "mo", + "mt", + "ne", + "nv", + "nh", + "nj", + "nm", + "ny", + "nc", + "nd", + "oh", + "ok", + "or", + "pa", + "pr", + "ri", + "sc", + "sd", + "tn", + "tx", + "ut", + "vt", + "va", + "vi", + "wa", + "wv", + "wi", + "wy", + "other", + "unknown" ] }, "dateOfUpdate": { "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", "type": "string", "format": "date" - }, - "fileNames": { - "type": "array", - "items": { - "type": "string" - } - }, - "status": { - "type": "string", - "enum": [ - "active", - "inactive" - ] } } } - }, - "providerId": { - "pattern": "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab]{1}[0-9a-f]{3}-[0-9a-f]{12}", - "type": "string" - }, - "licenseStatus": { - "type": "string", - "enum": [ - "active", - "inactive" - ] - }, - "familyName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "middleName": { - "maxLength": 100, - "minLength": 1, - "type": "string" - }, - "birthMonthDay": { - "pattern": "^[01]{1}[0-9]{1}-[0-3]{1}[0-9]{1}$", - "type": "string", - "format": "date" - }, - "compactConnectRegisteredEmailAddress": { - "maxLength": 100, - "minLength": 5, - "type": "string", - "format": "email" - }, - "dateOfUpdate": { - "pattern": "^[12]{1}[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$", - "type": "string", - "format": "date" } } } diff --git a/backend/compact-connect/docs/internal/postman/postman-collection.json b/backend/compact-connect/docs/internal/postman/postman-collection.json index 0b8e7222f..18f4c2200 100644 --- a/backend/compact-connect/docs/internal/postman/postman-collection.json +++ b/backend/compact-connect/docs/internal/postman/postman-collection.json @@ -10,7 +10,7 @@ "type": "bearer" }, "info": { - "_postman_id": "5f492f68-5627-4a3f-8743-e7c1799807b3", + "_postman_id": "5e637b8e-9328-4620-a612-6b617605b439", "description": { "content": "", "type": "text/plain" @@ -401,7 +401,7 @@ "item": [ { "event": [], - "id": "68f0420e-8442-4ef0-8571-93fc93520599", + "id": "23793feb-0c0d-41c1-803d-946d805d4574", "name": "/v1/compacts/:compact", "protocolProfileBehavior": { "disableBodyPruning": true @@ -444,7 +444,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"compactAbbr\": \"\",\n \"compactAdverseActionsNotificationEmails\": [\n \"\",\n \"\"\n ],\n \"compactCommissionFee\": {\n \"feeAmount\": \"\",\n \"feeType\": \"FLAT_RATE\"\n },\n \"compactName\": \"\",\n \"compactOperationsTeamEmails\": [\n \"\",\n \"\"\n ],\n \"compactSummaryReportNotificationEmails\": [\n \"\",\n \"\"\n ],\n \"configuredStates\": [\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"ne\"\n },\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"sc\"\n }\n ],\n \"licenseeRegistrationEnabled\": \"\",\n \"transactionFeeConfiguration\": {\n \"licenseeCharges\": {\n \"active\": \"\",\n \"chargeAmount\": \"\",\n \"chargeType\": \"FLAT_FEE_PER_PRIVILEGE\"\n }\n }\n}", + "body": "{\n \"compactAbbr\": \"\",\n \"compactAdverseActionsNotificationEmails\": [\n \"\",\n \"\"\n ],\n \"compactCommissionFee\": {\n \"feeAmount\": \"\",\n \"feeType\": \"FLAT_RATE\"\n },\n \"compactName\": \"\",\n \"compactOperationsTeamEmails\": [\n \"\",\n \"\"\n ],\n \"compactSummaryReportNotificationEmails\": [\n \"\",\n \"\"\n ],\n \"configuredStates\": [\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"ky\"\n },\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"sd\"\n }\n ],\n \"licenseeRegistrationEnabled\": \"\",\n \"transactionFeeConfiguration\": {\n \"licenseeCharges\": {\n \"active\": \"\",\n \"chargeAmount\": \"\",\n \"chargeType\": \"FLAT_FEE_PER_PRIVILEGE\"\n }\n }\n}", "code": 200, "cookie": [], "header": [ @@ -453,7 +453,7 @@ "value": "application/json" } ], - "id": "1fe7020a-cc42-497c-893a-18136710f2b3", + "id": "6095477c-0639-4313-b1f6-560ee5efc01d", "name": "200 response", "originalRequest": { "body": {}, @@ -491,7 +491,7 @@ }, { "event": [], - "id": "a4321217-8afc-4bfc-818e-4cbfe1134311", + "id": "78d24e49-cd10-4fcd-b463-37c5bec5f831", "name": "/v1/compacts/:compact", "protocolProfileBehavior": { "disableBodyPruning": true @@ -505,7 +505,7 @@ "language": "json" } }, - "raw": "{\n \"compactAdverseActionsNotificationEmails\": [\n \"\"\n ],\n \"compactCommissionFee\": {\n \"feeAmount\": \"\",\n \"feeType\": \"FLAT_RATE\"\n },\n \"compactOperationsTeamEmails\": [\n \"\"\n ],\n \"compactSummaryReportNotificationEmails\": [\n \"\"\n ],\n \"configuredStates\": [\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"mi\"\n },\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"ok\"\n }\n ],\n \"licenseeRegistrationEnabled\": \"\",\n \"transactionFeeConfiguration\": {\n \"licenseeCharges\": {\n \"active\": \"\",\n \"chargeAmount\": \"\",\n \"chargeType\": \"FLAT_FEE_PER_PRIVILEGE\"\n }\n }\n}" + "raw": "{\n \"compactAdverseActionsNotificationEmails\": [\n \"\"\n ],\n \"compactCommissionFee\": {\n \"feeAmount\": \"\",\n \"feeType\": \"FLAT_RATE\"\n },\n \"compactOperationsTeamEmails\": [\n \"\"\n ],\n \"compactSummaryReportNotificationEmails\": [\n \"\"\n ],\n \"configuredStates\": [\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"il\"\n },\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"nh\"\n }\n ],\n \"licenseeRegistrationEnabled\": \"\",\n \"transactionFeeConfiguration\": {\n \"licenseeCharges\": {\n \"active\": \"\",\n \"chargeAmount\": \"\",\n \"chargeType\": \"FLAT_FEE_PER_PRIVILEGE\"\n }\n }\n}" }, "description": {}, "header": [ @@ -556,7 +556,7 @@ "value": "application/json" } ], - "id": "f9cd8109-469c-4a24-842f-204c73511e7f", + "id": "b3b7d273-4ba7-4787-a25d-9a50858b034e", "name": "200 response", "originalRequest": { "body": { @@ -567,7 +567,7 @@ "language": "json" } }, - "raw": "{\n \"compactAdverseActionsNotificationEmails\": [\n \"\"\n ],\n \"compactCommissionFee\": {\n \"feeAmount\": \"\",\n \"feeType\": \"FLAT_RATE\"\n },\n \"compactOperationsTeamEmails\": [\n \"\"\n ],\n \"compactSummaryReportNotificationEmails\": [\n \"\"\n ],\n \"configuredStates\": [\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"mi\"\n },\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"ok\"\n }\n ],\n \"licenseeRegistrationEnabled\": \"\",\n \"transactionFeeConfiguration\": {\n \"licenseeCharges\": {\n \"active\": \"\",\n \"chargeAmount\": \"\",\n \"chargeType\": \"FLAT_FEE_PER_PRIVILEGE\"\n }\n }\n}" + "raw": "{\n \"compactAdverseActionsNotificationEmails\": [\n \"\"\n ],\n \"compactCommissionFee\": {\n \"feeAmount\": \"\",\n \"feeType\": \"FLAT_RATE\"\n },\n \"compactOperationsTeamEmails\": [\n \"\"\n ],\n \"compactSummaryReportNotificationEmails\": [\n \"\"\n ],\n \"configuredStates\": [\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"il\"\n },\n {\n \"isLive\": \"\",\n \"postalAbbreviation\": \"nh\"\n }\n ],\n \"licenseeRegistrationEnabled\": \"\",\n \"transactionFeeConfiguration\": {\n \"licenseeCharges\": {\n \"active\": \"\",\n \"chargeAmount\": \"\",\n \"chargeType\": \"FLAT_FEE_PER_PRIVILEGE\"\n }\n }\n}" }, "header": [ { @@ -613,7 +613,7 @@ "item": [ { "event": [], - "id": "08a5e2f3-040d-4409-8126-5d38e5173168", + "id": "ce36eb0f-c26e-452e-88b9-26a80cefe710", "name": "/v1/compacts/:compact/attestations/:attestationId", "protocolProfileBehavior": { "disableBodyPruning": true @@ -668,7 +668,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"dateCreated\": \"\",\n \"attestationId\": \"\",\n \"compact\": \"octp\",\n \"text\": \"\",\n \"type\": \"attestation\",\n \"locale\": \"\",\n \"version\": \"\",\n \"required\": \"\"\n}", + "body": "{\n \"dateCreated\": \"\",\n \"attestationId\": \"\",\n \"compact\": \"aslp\",\n \"text\": \"\",\n \"type\": \"attestation\",\n \"locale\": \"\",\n \"version\": \"\",\n \"required\": \"\"\n}", "code": 200, "cookie": [], "header": [ @@ -677,7 +677,7 @@ "value": "application/json" } ], - "id": "d02dbde3-3803-40d0-a05d-766c0c55a6cd", + "id": "6d805ffc-3f03-429a-a2ec-7cc414c9b09b", "name": "200 response", "originalRequest": { "body": {}, @@ -729,7 +729,7 @@ "item": [ { "event": [], - "id": "8983d39d-ff32-408b-86ac-8c2c898a7342", + "id": "2cb2a4bc-7ee8-43ad-8bf1-50b569eab181", "name": "/v1/compacts/:compact/credentials/payment-processor", "protocolProfileBehavior": { "disableBodyPruning": true @@ -796,7 +796,7 @@ "value": "application/json" } ], - "id": "9d6a6149-0100-4ac9-a844-da7b7da31eac", + "id": "02e53863-4227-4884-a561-1a201b75a1f2", "name": "200 response", "originalRequest": { "body": { @@ -858,7 +858,7 @@ "item": [ { "event": [], - "id": "efd220bd-7b7c-4d3a-b049-93c42cecb6bc", + "id": "4e7c5159-3dfe-4d3e-a962-8eb9036e45c3", "name": "/v1/compacts/:compact/jurisdictions", "protocolProfileBehavior": { "disableBodyPruning": true @@ -911,7 +911,7 @@ "value": "application/json" } ], - "id": "db231ae7-5140-42ca-aa4e-885ba7d7ca91", + "id": "a788b8aa-efa2-45b9-ae00-22a5606fa311", "name": "200 response", "originalRequest": { "body": {}, @@ -954,160 +954,6 @@ { "description": "", "item": [ - { - "event": [], - "id": "70f9e08d-63d0-4e89-96cb-5c51cac0561d", - "name": "/v1/compacts/:compact/jurisdictions/:jurisdiction/licenses", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "body": {}, - "description": {}, - "header": [ - { - "key": "Accept", - "value": "application/json" - } - ], - "method": "POST", - "name": "/v1/compacts/:compact/jurisdictions/:jurisdiction/licenses", - "url": { - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1", - "compacts", - ":compact", - "jurisdictions", - ":jurisdiction", - "licenses" - ], - "query": [], - "variable": [ - { - "description": { - "content": "(Required) ", - "type": "text/plain" - }, - "disabled": false, - "key": "compact", - "type": "any", - "value": "" - }, - { - "description": { - "content": "(Required) ", - "type": "text/plain" - }, - "disabled": false, - "key": "jurisdiction", - "type": "any", - "value": "" - } - ] - } - }, - "response": [ - { - "_postman_previewlanguage": "json", - "body": "{\n \"message\": \"\"\n}", - "code": 200, - "cookie": [], - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "id": "42787a86-c0f1-4805-b19f-825d2c8d28f9", - "name": "200 response", - "originalRequest": { - "body": {}, - "header": [ - { - "key": "Accept", - "value": "application/json" - }, - { - "description": { - "content": "Added as a part of security scheme: apikey", - "type": "text/plain" - }, - "key": "Authorization", - "value": "" - } - ], - "method": "POST", - "url": { - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1", - "compacts", - ":compact", - "jurisdictions", - ":jurisdiction", - "licenses" - ], - "query": [], - "variable": [] - } - }, - "status": "OK" - }, - { - "_postman_previewlanguage": "json", - "body": "{\n \"message\": \"\",\n \"errors\": {\n \"key_0\": {\n \"key_0\": [\n \"\",\n \"\"\n ],\n \"key_1\": [\n \"\",\n \"\"\n ],\n \"key_2\": [\n \"\",\n \"\"\n ],\n \"key_3\": [\n \"\",\n \"\"\n ]\n },\n \"key_1\": {\n \"key_0\": [\n \"\",\n \"\"\n ],\n \"key_1\": [\n \"\",\n \"\"\n ]\n },\n \"key_2\": {\n \"key_0\": [\n \"\",\n \"\"\n ],\n \"key_1\": [\n \"\",\n \"\"\n ],\n \"key_2\": [\n \"\",\n \"\"\n ]\n },\n \"key_3\": {\n \"key_0\": [\n \"\",\n \"\"\n ],\n \"key_1\": [\n \"\",\n \"\"\n ],\n \"key_2\": [\n \"\",\n \"\"\n ]\n }\n }\n}", - "code": 400, - "cookie": [], - "header": [ - { - "key": "Content-Type", - "value": "application/json" - } - ], - "id": "7c4b8847-e4c1-4931-a4c8-8d6ea23d6ff5", - "name": "400 response", - "originalRequest": { - "body": {}, - "header": [ - { - "key": "Accept", - "value": "application/json" - }, - { - "description": { - "content": "Added as a part of security scheme: apikey", - "type": "text/plain" - }, - "key": "Authorization", - "value": "" - } - ], - "method": "POST", - "url": { - "host": [ - "{{baseUrl}}" - ], - "path": [ - "v1", - "compacts", - ":compact", - "jurisdictions", - ":jurisdiction", - "licenses" - ], - "query": [], - "variable": [] - } - }, - "status": "Bad Request" - } - ] - }, { "description": "", "item": [ @@ -1138,7 +984,7 @@ } } ], - "id": "8c27923f-5065-4a16-be71-86793a152c3d", + "id": "e8ae53d0-e6bd-4137-aedc-8b9cf4e410a1", "name": "/v1/compacts/:compact/jurisdictions/:jurisdiction/licenses/bulk-upload", "protocolProfileBehavior": { "disableBodyPruning": true @@ -1195,7 +1041,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"upload\": {\n \"fields\": {\n \"key_0\": \"\",\n \"key_1\": \"\"\n },\n \"url\": \"\"\n }\n}", + "body": "{\n \"upload\": {\n \"fields\": {\n \"officia_f\": \"\"\n },\n \"url\": \"\"\n }\n}", "code": 200, "cookie": [], "header": [ @@ -1204,7 +1050,7 @@ "value": "application/json" } ], - "id": "dc0db506-543a-4483-9e56-b84c4e8b47c5", + "id": "82717e1a-3dad-4509-87f4-bf58add92bbd", "name": "200 response", "originalRequest": { "body": {}, @@ -1264,7 +1110,7 @@ "item": [ { "event": [], - "id": "68d2329c-f0b9-476b-8052-a7226f5556ae", + "id": "6853ddc2-310c-480a-88c2-3c60e1ad2fbf", "name": "/v1/compacts/:compact/providers/query", "protocolProfileBehavior": { "disableBodyPruning": true @@ -1278,7 +1124,7 @@ "language": "json" } }, - "raw": "{\n \"query\": {\n \"providerId\": \"7e651bfc-493a-488f-86bc-5751905747cf\",\n \"jurisdiction\": \"nm\",\n \"givenName\": \"\",\n \"familyName\": \"\"\n },\n \"pagination\": {\n \"lastKey\": \"\",\n \"pageSize\": \"\"\n },\n \"sorting\": {\n \"key\": \"dateOfUpdate\",\n \"direction\": \"descending\"\n }\n}" + "raw": "{\n \"query\": {\n \"providerId\": \"3f3c1b6f-4d02-4048-adef-7a8ec269307b\",\n \"jurisdiction\": \"co\",\n \"givenName\": \"\",\n \"familyName\": \"\"\n },\n \"pagination\": {\n \"lastKey\": \"\",\n \"pageSize\": \"\"\n },\n \"sorting\": {\n \"key\": \"dateOfUpdate\",\n \"direction\": \"descending\"\n }\n}" }, "description": {}, "header": [ @@ -1322,7 +1168,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"pagination\": {\n \"prevLastKey\": {},\n \"lastKey\": {},\n \"pageSize\": \"\"\n },\n \"providers\": [\n {\n \"birthMonthDay\": \"16-00\",\n \"compact\": \"coun\",\n \"compactEligibility\": \"eligible\",\n \"dateOfExpiration\": \"2014-10-22\",\n \"dateOfUpdate\": \"1135-02-05\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"licenseJurisdiction\": \"me\",\n \"licenseStatus\": \"active\",\n \"privilegeJurisdictions\": [\n \"mn\",\n \"ct\"\n ],\n \"providerId\": \"60f95f47-c65d-4f35-9aa1-d144a4afef3b\",\n \"type\": \"provider\",\n \"npi\": \"3758648602\",\n \"dateOfBirth\": \"1799-02-29\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"mo\",\n \"ssnLastFour\": \"9067\",\n \"middleName\": \"\",\n \"compactConnectRegisteredEmailAddress\": \"\"\n },\n {\n \"birthMonthDay\": \"04-22\",\n \"compact\": \"octp\",\n \"compactEligibility\": \"eligible\",\n \"dateOfExpiration\": \"1039-05-30\",\n \"dateOfUpdate\": \"2740-05-06\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"licenseJurisdiction\": \"ks\",\n \"licenseStatus\": \"inactive\",\n \"privilegeJurisdictions\": [\n \"ia\",\n \"nh\"\n ],\n \"providerId\": \"6b620401-6c57-4681-a9fc-d9070b1f8d09\",\n \"type\": \"provider\",\n \"npi\": \"3106798211\",\n \"dateOfBirth\": \"2308-12-04\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"ms\",\n \"ssnLastFour\": \"7206\",\n \"middleName\": \"\",\n \"compactConnectRegisteredEmailAddress\": \"\"\n }\n ],\n \"sorting\": {\n \"key\": \"familyName\",\n \"direction\": \"descending\"\n }\n}", + "body": "{\n \"pagination\": {\n \"prevLastKey\": {},\n \"lastKey\": {},\n \"pageSize\": \"\"\n },\n \"providers\": [\n {\n \"birthMonthDay\": \"06-15\",\n \"compact\": \"octp\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfExpiration\": \"2019-12-29\",\n \"dateOfUpdate\": \"1509-09-03\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"licenseJurisdiction\": \"ms\",\n \"licenseStatus\": \"active\",\n \"privilegeJurisdictions\": [\n \"tn\",\n \"nd\"\n ],\n \"providerId\": \"63ce33be-9b01-4615-a8e5-be23ae32ac24\",\n \"type\": \"provider\",\n \"npi\": \"6210275723\",\n \"dateOfBirth\": \"1208-10-14\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"unknown\",\n \"ssnLastFour\": \"3597\",\n \"middleName\": \"\",\n \"compactConnectRegisteredEmailAddress\": \"\"\n },\n {\n \"birthMonthDay\": \"10-05\",\n \"compact\": \"aslp\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfExpiration\": \"2818-12-29\",\n \"dateOfUpdate\": \"2767-05-31\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"licenseJurisdiction\": \"nm\",\n \"licenseStatus\": \"active\",\n \"privilegeJurisdictions\": [\n \"wa\",\n \"pr\"\n ],\n \"providerId\": \"7a2f41b7-d0fe-4c58-9669-6808e0eee745\",\n \"type\": \"provider\",\n \"npi\": \"1896325843\",\n \"dateOfBirth\": \"2934-11-31\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"nj\",\n \"ssnLastFour\": \"9104\",\n \"middleName\": \"\",\n \"compactConnectRegisteredEmailAddress\": \"\"\n }\n ],\n \"sorting\": {\n \"key\": \"dateOfUpdate\",\n \"direction\": \"ascending\"\n }\n}", "code": 200, "cookie": [], "header": [ @@ -1331,7 +1177,7 @@ "value": "application/json" } ], - "id": "38d665a0-9c29-4753-81d4-98478c78b7ae", + "id": "e53980a8-1143-4024-bb86-7f157fc3c354", "name": "200 response", "originalRequest": { "body": { @@ -1342,7 +1188,7 @@ "language": "json" } }, - "raw": "{\n \"query\": {\n \"providerId\": \"7e651bfc-493a-488f-86bc-5751905747cf\",\n \"jurisdiction\": \"nm\",\n \"givenName\": \"\",\n \"familyName\": \"\"\n },\n \"pagination\": {\n \"lastKey\": \"\",\n \"pageSize\": \"\"\n },\n \"sorting\": {\n \"key\": \"dateOfUpdate\",\n \"direction\": \"descending\"\n }\n}" + "raw": "{\n \"query\": {\n \"providerId\": \"3f3c1b6f-4d02-4048-adef-7a8ec269307b\",\n \"jurisdiction\": \"co\",\n \"givenName\": \"\",\n \"familyName\": \"\"\n },\n \"pagination\": {\n \"lastKey\": \"\",\n \"pageSize\": \"\"\n },\n \"sorting\": {\n \"key\": \"dateOfUpdate\",\n \"direction\": \"descending\"\n }\n}" }, "header": [ { @@ -1390,7 +1236,7 @@ "item": [ { "event": [], - "id": "6f1f983b-9a60-4a3c-8a16-977540b8dc2b", + "id": "14737019-8659-4b74-930e-ce7a28ffcacc", "name": "/v1/compacts/:compact/providers/:providerId", "protocolProfileBehavior": { "disableBodyPruning": true @@ -1445,7 +1291,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"birthMonthDay\": \"18-05\",\n \"compact\": \"aslp\",\n \"dateOfExpiration\": \"1114-09-12\",\n \"dateOfUpdate\": \"1433-03-23\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"licenseJurisdiction\": \"ar\",\n \"licenses\": [\n {\n \"compact\": \"aslp\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfExpiration\": \"1306-03-08\",\n \"dateOfIssuance\": \"1030-12-30\",\n \"dateOfRenewal\": \"2474-02-05\",\n \"dateOfUpdate\": \"2475-10-30\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"history\": [\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"1010-10-30\",\n \"jurisdiction\": \"nm\",\n \"previous\": {\n \"dateOfExpiration\": \"2000-10-31\",\n \"dateOfIssuance\": \"1844-02-31\",\n \"dateOfRenewal\": \"1608-11-02\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"1753423147\",\n \"compactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1452-01-06\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+1309397612826\",\n \"licenseStatus\": \"active\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"encumbrance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"occupational therapy assistant\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"3671735098\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"2873-07-02\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"1031-11-02\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"1975-11-12\",\n \"phoneNumber\": \"+17851605\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"1695-07-10\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n },\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"1541-11-31\",\n \"jurisdiction\": \"ma\",\n \"previous\": {\n \"dateOfExpiration\": \"1936-10-30\",\n \"dateOfIssuance\": \"2331-04-30\",\n \"dateOfRenewal\": \"2842-11-30\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"9804384619\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"2010-11-16\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+71413357\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"other\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"8250482424\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"eligible\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1069-04-05\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"2613-04-31\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"2711-11-03\",\n \"phoneNumber\": \"+2050697721898\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"1517-05-02\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n }\n ],\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdiction\": \"az\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"licenseStatus\": \"inactive\",\n \"licenseType\": \"licensed professional counselor\",\n \"middleName\": \"\",\n \"providerId\": \"b0496763-ec92-4a47-ab2f-4536b681bd38\",\n \"type\": \"license-home\",\n \"homeAddressStreet2\": \"\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"licenseNumber\": \"\",\n \"npi\": \"6095695256\",\n \"dateOfBirth\": \"1320-04-03\",\n \"ssnLastFour\": \"1076\",\n \"phoneNumber\": \"+382839208006\",\n \"licenseStatusName\": \"\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"aslp\",\n \"creationDate\": \"1214-10-30\",\n \"dateOfUpdate\": \"2390-11-06\",\n \"effectiveStartDate\": \"2953-01-18\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"hi\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"0b8fe736-c033-4136-91f5-eda7f2b8ba7f\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2194-04-08\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"1503-05-25\",\n \"dateOfUpdate\": \"1262-01-13\",\n \"effectiveStartDate\": \"2162-09-31\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"id\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"3d8e7a68-4df4-47c3-adb9-d5e575911bc0\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2812-01-31\",\n \"liftingUser\": \"\"\n }\n ]\n },\n {\n \"compact\": \"octp\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfExpiration\": \"2646-12-18\",\n \"dateOfIssuance\": \"1304-11-30\",\n \"dateOfRenewal\": \"1212-10-06\",\n \"dateOfUpdate\": \"2731-02-08\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"history\": [\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"2968-11-05\",\n \"jurisdiction\": \"oh\",\n \"previous\": {\n \"dateOfExpiration\": \"1495-02-09\",\n \"dateOfIssuance\": \"2074-08-09\",\n \"dateOfRenewal\": \"2897-05-18\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"3591668223\",\n \"compactEligibility\": \"eligible\",\n \"dateOfBirth\": \"2528-12-16\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+925332212023\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"renewal\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"licensed professional counselor\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"3128128708\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1615-03-27\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"1858-12-12\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"2093-05-06\",\n \"phoneNumber\": \"+88862351397\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"2188-02-03\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n },\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"1014-09-30\",\n \"jurisdiction\": \"nc\",\n \"previous\": {\n \"dateOfExpiration\": \"2200-12-17\",\n \"dateOfIssuance\": \"1483-08-09\",\n \"dateOfRenewal\": \"1580-11-04\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"7107653147\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"1684-12-09\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+982749013585799\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"licenseDeactivation\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"speech-language pathologist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"1201882644\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1252-11-27\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"1019-08-30\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"1397-11-30\",\n \"phoneNumber\": \"+52496923166065\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"2633-03-17\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n }\n ],\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdiction\": \"md\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"licenseStatus\": \"active\",\n \"licenseType\": \"occupational therapist\",\n \"middleName\": \"\",\n \"providerId\": \"e3b45a75-ebd9-4b90-aa3e-93a1ccef8db3\",\n \"type\": \"license-home\",\n \"homeAddressStreet2\": \"\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"licenseNumber\": \"\",\n \"npi\": \"1310126629\",\n \"dateOfBirth\": \"2033-10-30\",\n \"ssnLastFour\": \"4546\",\n \"phoneNumber\": \"+2458662829273\",\n \"licenseStatusName\": \"\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"1494-09-09\",\n \"dateOfUpdate\": \"1137-01-30\",\n \"effectiveStartDate\": \"1605-10-27\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"de\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"77f72e9e-b1c0-4550-8378-2ef810a520b5\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2220-10-30\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"1487-10-03\",\n \"dateOfUpdate\": \"2605-12-30\",\n \"effectiveStartDate\": \"1965-06-14\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"il\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"a4311387-4e26-4f26-ba5a-1deafc45e728\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1069-05-25\",\n \"liftingUser\": \"\"\n }\n ]\n }\n ],\n \"militaryAffiliations\": [\n {\n \"affiliationType\": \"militaryMember\",\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1725-12-30\",\n \"dateOfUpload\": \"2049-12-25\",\n \"fileNames\": [\n \"\",\n \"\"\n ],\n \"providerId\": \"e0e86c9f-b5eb-426a-90ac-36829f8388bd\",\n \"status\": \"active\",\n \"type\": \"militaryAffiliation\",\n \"downloadLinks\": [\n {\n \"fileName\": \"\",\n \"url\": \"\"\n },\n {\n \"fileName\": \"\",\n \"url\": \"\"\n }\n ]\n },\n {\n \"affiliationType\": \"militaryMember\",\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1892-12-11\",\n \"dateOfUpload\": \"1877-11-07\",\n \"fileNames\": [\n \"\",\n \"\"\n ],\n \"providerId\": \"8385072b-15c4-4e87-b06b-97a1eb9e68a7\",\n \"status\": \"active\",\n \"type\": \"militaryAffiliation\",\n \"downloadLinks\": [\n {\n \"fileName\": \"\",\n \"url\": \"\"\n },\n {\n \"fileName\": \"\",\n \"url\": \"\"\n }\n ]\n }\n ],\n \"privilegeJurisdictions\": [\n \"mn\",\n \"tn\"\n ],\n \"privileges\": [\n {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compact\": \"octp\",\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1446-11-31\",\n \"dateOfIssuance\": \"1724-04-07\",\n \"dateOfRenewal\": \"2644-08-21\",\n \"dateOfUpdate\": \"2229-06-07\",\n \"history\": [\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"2991-04-08\",\n \"jurisdiction\": \"il\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1660-12-30\",\n \"dateOfIssuance\": \"1313-03-24\",\n \"dateOfRenewal\": \"2145-12-31\",\n \"dateOfUpdate\": \"2403-05-30\",\n \"licenseJurisdiction\": \"vi\",\n \"privilegeId\": \"\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"il\",\n \"type\": \"privilege\",\n \"providerId\": \"d4ad584f-9f2b-4b92-ba60-7fe995bbf582\",\n \"status\": \"active\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"issuance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"va\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"al\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"1534-03-30\",\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"2504-03-30\",\n \"privilegeId\": \"\",\n \"providerId\": \"e3713f86-cda1-48f5-8683-caf9abb02462\",\n \"dateOfRenewal\": \"2667-12-07\",\n \"dateOfUpdate\": \"2148-10-04\",\n \"status\": \"inactive\"\n }\n },\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"2016-07-31\",\n \"jurisdiction\": \"ks\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"2781-11-17\",\n \"dateOfIssuance\": \"2079-03-20\",\n \"dateOfRenewal\": \"2623-10-31\",\n \"dateOfUpdate\": \"2572-07-31\",\n \"licenseJurisdiction\": \"la\",\n \"privilegeId\": \"\",\n \"compact\": \"aslp\",\n \"jurisdiction\": \"ne\",\n \"type\": \"privilege\",\n \"providerId\": \"eb1f0881-30a4-40ff-b2b1-fac2a1af50d3\",\n \"status\": \"active\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"licenseDeactivation\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"ar\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"tn\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"2044-12-09\",\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"1521-08-30\",\n \"privilegeId\": \"\",\n \"providerId\": \"09e6288d-de40-4fc0-b519-d19cf7e84a25\",\n \"dateOfRenewal\": \"2128-07-18\",\n \"dateOfUpdate\": \"1744-04-06\",\n \"status\": \"inactive\"\n }\n }\n ],\n \"jurisdiction\": \"ga\",\n \"licenseJurisdiction\": \"md\",\n \"licenseType\": \"occupational therapy assistant\",\n \"privilegeId\": \"\",\n \"providerId\": \"e5e4b3ff-d893-4958-a1d3-50e1fddb2521\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"aslp\",\n \"creationDate\": \"2273-02-08\",\n \"dateOfUpdate\": \"1801-06-24\",\n \"effectiveStartDate\": \"2299-08-30\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"ms\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"7540c90b-f2ce-4e8d-aff7-00ed6bf8a3b8\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2819-12-30\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"2967-12-30\",\n \"dateOfUpdate\": \"2051-03-19\",\n \"effectiveStartDate\": \"2562-10-31\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"wi\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"9a1790c1-066a-493c-af95-06983d3362be\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1103-10-12\",\n \"liftingUser\": \"\"\n }\n ]\n },\n {\n \"administratorSetStatus\": \"inactive\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compact\": \"aslp\",\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1800-11-05\",\n \"dateOfIssuance\": \"2485-03-30\",\n \"dateOfRenewal\": \"1669-04-31\",\n \"dateOfUpdate\": \"1350-10-05\",\n \"history\": [\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2614-10-01\",\n \"jurisdiction\": \"ne\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1548-10-30\",\n \"dateOfIssuance\": \"2661-11-09\",\n \"dateOfRenewal\": \"2248-01-29\",\n \"dateOfUpdate\": \"2755-12-25\",\n \"licenseJurisdiction\": \"il\",\n \"privilegeId\": \"\",\n \"compact\": \"aslp\",\n \"jurisdiction\": \"mi\",\n \"type\": \"privilege\",\n \"providerId\": \"b119e009-e3eb-4e39-a447-d1f5a0d988bf\",\n \"status\": \"inactive\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"deactivation\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"nm\",\n \"compact\": \"aslp\",\n \"jurisdiction\": \"ut\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"2223-12-26\",\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"2850-10-08\",\n \"privilegeId\": \"\",\n \"providerId\": \"af1366f2-f7b6-473d-b051-1a4a8283155d\",\n \"dateOfRenewal\": \"1460-06-08\",\n \"dateOfUpdate\": \"1832-12-14\",\n \"status\": \"active\"\n }\n },\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"1183-11-31\",\n \"jurisdiction\": \"wv\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"2933-09-11\",\n \"dateOfIssuance\": \"2180-10-02\",\n \"dateOfRenewal\": \"1762-02-07\",\n \"dateOfUpdate\": \"2602-11-05\",\n \"licenseJurisdiction\": \"mn\",\n \"privilegeId\": \"\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"wv\",\n \"type\": \"privilege\",\n \"providerId\": \"b41e9a0f-0596-401e-9e13-dd17170e1a1c\",\n \"status\": \"inactive\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"lifting_encumbrance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"occupational therapist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"pr\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"sd\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"2472-11-09\",\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"1343-12-16\",\n \"privilegeId\": \"\",\n \"providerId\": \"3040c8ef-5bd6-40e4-882a-4657292afe28\",\n \"dateOfRenewal\": \"2523-10-30\",\n \"dateOfUpdate\": \"2533-04-19\",\n \"status\": \"inactive\"\n }\n }\n ],\n \"jurisdiction\": \"ia\",\n \"licenseJurisdiction\": \"sc\",\n \"licenseType\": \"licensed professional counselor\",\n \"privilegeId\": \"\",\n \"providerId\": \"54c8c814-9dfb-4f13-8b96-722dd65cd6f9\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"1172-10-05\",\n \"dateOfUpdate\": \"2404-07-05\",\n \"effectiveStartDate\": \"2365-03-30\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"md\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"098a460c-fd37-4c28-899e-85dbf064cb56\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1464-07-01\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"aslp\",\n \"creationDate\": \"2725-03-23\",\n \"dateOfUpdate\": \"2839-04-26\",\n \"effectiveStartDate\": \"1105-12-01\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"il\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"26b21d87-9527-433f-aa95-752626fca36f\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2025-05-26\",\n \"liftingUser\": \"\"\n }\n ]\n }\n ],\n \"providerId\": \"83940727-a1af-4b19-99bb-c35b22f25c66\",\n \"type\": \"provider\",\n \"npi\": \"4129573768\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1535-03-08\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"sd\",\n \"ssnLastFour\": \"5379\",\n \"licenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"compactConnectRegisteredEmailAddress\": \"\"\n}", + "body": "{\n \"birthMonthDay\": \"10-13\",\n \"compact\": \"octp\",\n \"dateOfExpiration\": \"2708-12-19\",\n \"dateOfUpdate\": \"2235-11-07\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"licenseJurisdiction\": \"or\",\n \"licenses\": [\n {\n \"compact\": \"octp\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfExpiration\": \"1194-11-07\",\n \"dateOfIssuance\": \"1811-01-06\",\n \"dateOfRenewal\": \"1005-01-30\",\n \"dateOfUpdate\": \"1228-10-17\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"history\": [\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"1122-08-31\",\n \"jurisdiction\": \"de\",\n \"previous\": {\n \"dateOfExpiration\": \"2825-06-30\",\n \"dateOfIssuance\": \"2552-11-09\",\n \"dateOfRenewal\": \"1554-03-08\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"7904266478\",\n \"compactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1130-10-09\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+127199520822501\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"expiration\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"7996207438\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"2689-12-23\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"2349-01-07\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"1981-10-31\",\n \"phoneNumber\": \"+48186155665\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"2985-03-02\",\n \"licenseStatus\": \"active\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n },\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2799-03-17\",\n \"jurisdiction\": \"pa\",\n \"previous\": {\n \"dateOfExpiration\": \"1712-01-28\",\n \"dateOfIssuance\": \"2124-05-31\",\n \"dateOfRenewal\": \"1804-12-25\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"3975501387\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"1678-08-23\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+80432649\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"deactivation\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"speech-language pathologist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"5745410699\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"2459-01-20\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"2074-05-31\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"1606-04-30\",\n \"phoneNumber\": \"+38094519029451\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"2402-11-03\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n }\n ],\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdiction\": \"mo\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"licenseStatus\": \"active\",\n \"licenseType\": \"audiologist\",\n \"middleName\": \"\",\n \"providerId\": \"d6a677d3-d7fb-4780-9aa5-0b54def3f5fb\",\n \"type\": \"license-home\",\n \"homeAddressStreet2\": \"\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"licenseNumber\": \"\",\n \"npi\": \"6162231934\",\n \"dateOfBirth\": \"2116-11-23\",\n \"ssnLastFour\": \"2827\",\n \"phoneNumber\": \"+316315679209\",\n \"licenseStatusName\": \"\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"2958-09-30\",\n \"dateOfUpdate\": \"1010-09-30\",\n \"effectiveStartDate\": \"2967-11-11\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"md\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"92cf3f74-4eba-4e03-8960-fe8244789ade\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"2333-10-23\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"2829-11-23\",\n \"dateOfUpdate\": \"1986-11-31\",\n \"effectiveStartDate\": \"1863-08-02\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"ca\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"3ebb12e1-61e9-4764-bc27-deb0c708968b\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"2426-05-14\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n }\n ]\n },\n {\n \"compact\": \"coun\",\n \"compactEligibility\": \"eligible\",\n \"dateOfExpiration\": \"2303-05-13\",\n \"dateOfIssuance\": \"1600-02-08\",\n \"dateOfRenewal\": \"1136-11-23\",\n \"dateOfUpdate\": \"2758-11-26\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"history\": [\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"2228-10-08\",\n \"jurisdiction\": \"or\",\n \"previous\": {\n \"dateOfExpiration\": \"1909-03-15\",\n \"dateOfIssuance\": \"1920-12-19\",\n \"dateOfRenewal\": \"1820-11-05\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"4309547090\",\n \"compactEligibility\": \"eligible\",\n \"dateOfBirth\": \"2575-01-06\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+282921155\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"encumbrance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"1272654411\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"2191-12-26\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"2166-09-22\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"2233-10-31\",\n \"phoneNumber\": \"+83080416937936\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"1714-09-03\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n },\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1525-12-30\",\n \"jurisdiction\": \"ca\",\n \"previous\": {\n \"dateOfExpiration\": \"1149-10-31\",\n \"dateOfIssuance\": \"1206-01-04\",\n \"dateOfRenewal\": \"2125-10-28\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"7139133672\",\n \"compactEligibility\": \"eligible\",\n \"dateOfBirth\": \"2503-11-06\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+22157243484\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"issuance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"occupational therapist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"5902669871\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"1846-06-16\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"1530-10-31\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"2630-10-29\",\n \"phoneNumber\": \"+463314989084\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"2898-04-19\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n }\n ],\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdiction\": \"ri\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"licenseStatus\": \"active\",\n \"licenseType\": \"occupational therapy assistant\",\n \"middleName\": \"\",\n \"providerId\": \"90bf4c45-b2bc-4e1c-9055-23adc019b9ff\",\n \"type\": \"license-home\",\n \"homeAddressStreet2\": \"\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"licenseNumber\": \"\",\n \"npi\": \"6796883381\",\n \"dateOfBirth\": \"2836-10-24\",\n \"ssnLastFour\": \"3288\",\n \"phoneNumber\": \"+58540754234\",\n \"licenseStatusName\": \"\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"aslp\",\n \"creationDate\": \"1925-08-08\",\n \"dateOfUpdate\": \"2975-04-19\",\n \"effectiveStartDate\": \"2776-11-04\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"tn\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"17990d99-1def-4abd-8a8a-3122ca3219da\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"2663-04-30\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"1285-04-03\",\n \"dateOfUpdate\": \"2856-10-30\",\n \"effectiveStartDate\": \"2544-08-30\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"ky\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"2b1d1723-dfb8-40bc-90cf-902c703548c9\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"1523-10-10\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n }\n ]\n }\n ],\n \"militaryAffiliations\": [\n {\n \"affiliationType\": \"militaryMemberSpouse\",\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2565-05-30\",\n \"dateOfUpload\": \"2261-11-03\",\n \"fileNames\": [\n \"\",\n \"\"\n ],\n \"providerId\": \"84e50f08-03c5-4137-b371-2550b5369cdb\",\n \"status\": \"inactive\",\n \"type\": \"militaryAffiliation\",\n \"downloadLinks\": [\n {\n \"fileName\": \"\",\n \"url\": \"\"\n },\n {\n \"fileName\": \"\",\n \"url\": \"\"\n }\n ]\n },\n {\n \"affiliationType\": \"militaryMember\",\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2471-04-28\",\n \"dateOfUpload\": \"2015-12-30\",\n \"fileNames\": [\n \"\",\n \"\"\n ],\n \"providerId\": \"6850e115-8f7f-4f2e-bb91-d0710a6fc6c7\",\n \"status\": \"active\",\n \"type\": \"militaryAffiliation\",\n \"downloadLinks\": [\n {\n \"fileName\": \"\",\n \"url\": \"\"\n },\n {\n \"fileName\": \"\",\n \"url\": \"\"\n }\n ]\n }\n ],\n \"privilegeJurisdictions\": [\n \"il\",\n \"wa\"\n ],\n \"privileges\": [\n {\n \"administratorSetStatus\": \"inactive\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compact\": \"aslp\",\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1403-11-30\",\n \"dateOfIssuance\": \"2058-06-04\",\n \"dateOfRenewal\": \"2848-04-31\",\n \"dateOfUpdate\": \"2721-10-29\",\n \"history\": [\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2232-10-08\",\n \"jurisdiction\": \"hi\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"2380-07-31\",\n \"dateOfIssuance\": \"1675-11-01\",\n \"dateOfRenewal\": \"1533-01-06\",\n \"dateOfUpdate\": \"1664-10-31\",\n \"licenseJurisdiction\": \"dc\",\n \"privilegeId\": \"\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"oh\",\n \"type\": \"privilege\",\n \"providerId\": \"f215ffd6-257c-40c5-8daa-9a21135d1b03\",\n \"status\": \"inactive\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"lifting_encumbrance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"occupational therapist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"id\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"sc\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"2178-07-01\",\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"2128-01-07\",\n \"privilegeId\": \"\",\n \"providerId\": \"11b11933-f36a-4eb7-83a0-542011f49873\",\n \"dateOfRenewal\": \"2696-05-20\",\n \"dateOfUpdate\": \"1259-03-06\",\n \"status\": \"inactive\"\n }\n },\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1899-11-28\",\n \"jurisdiction\": \"id\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1808-12-25\",\n \"dateOfIssuance\": \"1867-04-31\",\n \"dateOfRenewal\": \"1948-03-09\",\n \"dateOfUpdate\": \"1544-11-09\",\n \"licenseJurisdiction\": \"pr\",\n \"privilegeId\": \"\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"ak\",\n \"type\": \"privilege\",\n \"providerId\": \"98e3f59c-0fbc-4aa4-bce1-7d5689f18812\",\n \"status\": \"inactive\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"renewal\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"occupational therapist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"wv\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"id\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"1221-02-30\",\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"2814-11-15\",\n \"privilegeId\": \"\",\n \"providerId\": \"532d563d-a1bc-40dc-a5f0-8a0a86f05451\",\n \"dateOfRenewal\": \"1885-12-31\",\n \"dateOfUpdate\": \"1384-02-11\",\n \"status\": \"active\"\n }\n }\n ],\n \"jurisdiction\": \"vt\",\n \"licenseJurisdiction\": \"mn\",\n \"licenseType\": \"occupational therapy assistant\",\n \"privilegeId\": \"\",\n \"providerId\": \"4b524f8c-6a30-4ee6-ab6c-55c37a68167f\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"2986-01-02\",\n \"dateOfUpdate\": \"1994-10-13\",\n \"effectiveStartDate\": \"1242-11-28\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"sc\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"bbf662ac-7e91-4140-903c-0c350d7dc5f7\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"2961-12-04\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"2886-12-31\",\n \"dateOfUpdate\": \"2098-11-30\",\n \"effectiveStartDate\": \"1188-03-30\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"me\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"7a3ab2b7-4041-47eb-94c4-e50ec792a958\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"2457-03-28\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n }\n ]\n },\n {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compact\": \"coun\",\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1412-03-31\",\n \"dateOfIssuance\": \"1750-01-08\",\n \"dateOfRenewal\": \"2654-02-08\",\n \"dateOfUpdate\": \"1882-06-30\",\n \"history\": [\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"1696-11-03\",\n \"jurisdiction\": \"fl\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"2747-09-30\",\n \"dateOfIssuance\": \"2819-02-21\",\n \"dateOfRenewal\": \"1924-12-14\",\n \"dateOfUpdate\": \"2059-01-31\",\n \"licenseJurisdiction\": \"pr\",\n \"privilegeId\": \"\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"ks\",\n \"type\": \"privilege\",\n \"providerId\": \"81e91006-0dfe-4322-8a41-b7d78aae5f69\",\n \"status\": \"active\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"licenseDeactivation\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"speech-language pathologist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"az\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"sc\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"1608-08-04\",\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"2931-11-31\",\n \"privilegeId\": \"\",\n \"providerId\": \"c4cc5de7-00ec-43e9-97f0-5dab5c0ae1a6\",\n \"dateOfRenewal\": \"1003-10-19\",\n \"dateOfUpdate\": \"1809-12-04\",\n \"status\": \"inactive\"\n }\n },\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1973-11-16\",\n \"jurisdiction\": \"ia\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1210-10-31\",\n \"dateOfIssuance\": \"1470-12-02\",\n \"dateOfRenewal\": \"2582-01-31\",\n \"dateOfUpdate\": \"1348-05-14\",\n \"licenseJurisdiction\": \"ks\",\n \"privilegeId\": \"\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"ok\",\n \"type\": \"privilege\",\n \"providerId\": \"e364f6bd-3d30-4881-ad2e-99d25dd13612\",\n \"status\": \"inactive\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"emailChange\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"speech-language pathologist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"md\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"me\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"1321-02-30\",\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"1415-12-13\",\n \"privilegeId\": \"\",\n \"providerId\": \"2550a822-a6a2-46f5-9d6f-381ad5c7ad50\",\n \"dateOfRenewal\": \"1441-10-20\",\n \"dateOfUpdate\": \"2823-01-02\",\n \"status\": \"active\"\n }\n }\n ],\n \"jurisdiction\": \"ky\",\n \"licenseJurisdiction\": \"ne\",\n \"licenseType\": \"speech-language pathologist\",\n \"privilegeId\": \"\",\n \"providerId\": \"e7d03cad-55f3-4a69-bf06-109772196128\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"1836-11-03\",\n \"dateOfUpdate\": \"1386-07-12\",\n \"effectiveStartDate\": \"2383-04-14\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"ar\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"91d01ece-89f1-46d0-8105-52a9517f6a70\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"1297-12-28\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"1188-10-30\",\n \"dateOfUpdate\": \"2977-10-31\",\n \"effectiveStartDate\": \"2846-08-30\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"fl\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"5205a6c0-1147-4655-a17b-ff3780c163d9\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"1879-11-24\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n }\n ]\n }\n ],\n \"providerId\": \"94022a97-0d0d-4153-bda8-a15afc713ee2\",\n \"type\": \"provider\",\n \"npi\": \"8197107476\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"dateOfBirth\": \"2021-12-30\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"sc\",\n \"ssnLastFour\": \"2592\",\n \"licenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"compactConnectRegisteredEmailAddress\": \"\"\n}", "code": 200, "cookie": [], "header": [ @@ -1454,7 +1300,7 @@ "value": "application/json" } ], - "id": "44acb98f-f78b-4463-a6f1-a7a45e99c7ee", + "id": "512a4239-02c5-46f6-a941-c12d567186bb", "name": "200 response", "originalRequest": { "body": {}, @@ -1512,7 +1358,7 @@ "item": [ { "event": [], - "id": "53c9e443-2ec6-4920-bd4a-6fda18c34f92", + "id": "ddb6a23b-e741-469f-86c8-fffeccfe494d", "name": "/v1/compacts/:compact/providers/:providerId/licenses/jurisdiction/:jurisdiction/licenseType/:licenseType/encumbrance", "protocolProfileBehavior": { "disableBodyPruning": true @@ -1526,7 +1372,7 @@ "language": "json" } }, - "raw": "{\n \"clinicalPrivilegeActionCategory\": \"\",\n \"encumbranceEffectiveDate\": \"2902-12-31\",\n \"encumbranceType\": \"revocation\"\n}" + "raw": "{\n \"encumbranceEffectiveDate\": \"1374-10-13\",\n \"encumbranceType\": \"modification of previous action-reduction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"clinicalPrivilegeActionCategory\": \"\"\n}" }, "description": {}, "header": [ @@ -1615,7 +1461,7 @@ "value": "application/json" } ], - "id": "df7a55a0-13f1-4d9e-92fe-ca80d8bb8c30", + "id": "0546c709-01f6-48af-8188-7bb7ce545fee", "name": "200 response", "originalRequest": { "body": { @@ -1626,7 +1472,7 @@ "language": "json" } }, - "raw": "{\n \"clinicalPrivilegeActionCategory\": \"\",\n \"encumbranceEffectiveDate\": \"2902-12-31\",\n \"encumbranceType\": \"revocation\"\n}" + "raw": "{\n \"encumbranceEffectiveDate\": \"1374-10-13\",\n \"encumbranceType\": \"modification of previous action-reduction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"clinicalPrivilegeActionCategory\": \"\"\n}" }, "header": [ { @@ -1677,7 +1523,7 @@ "item": [ { "event": [], - "id": "8a6f952e-b548-464d-b5fe-40fe7727f054", + "id": "86336bac-1cc0-40ec-9aff-da7bf05456d6", "name": "/v1/compacts/:compact/providers/:providerId/licenses/jurisdiction/:jurisdiction/licenseType/:licenseType/encumbrance/:encumbranceId", "protocolProfileBehavior": { "disableBodyPruning": true @@ -1691,7 +1537,7 @@ "language": "json" } }, - "raw": "{\n \"effectiveLiftDate\": \"1840-05-08\"\n}" + "raw": "{\n \"effectiveLiftDate\": \"1227-11-31\"\n}" }, "description": {}, "header": [ @@ -1791,7 +1637,7 @@ "value": "application/json" } ], - "id": "884da41c-a402-4383-b1d4-8a90af9a2908", + "id": "1b56ea75-2ac2-47dd-9cce-536ad61b0715", "name": "200 response", "originalRequest": { "body": { @@ -1802,7 +1648,7 @@ "language": "json" } }, - "raw": "{\n \"effectiveLiftDate\": \"1840-05-08\"\n}" + "raw": "{\n \"effectiveLiftDate\": \"1227-11-31\"\n}" }, "header": [ { @@ -1890,7 +1736,7 @@ "item": [ { "event": [], - "id": "595819aa-14ed-446b-b1bd-79b784d1ad15", + "id": "1a4164fb-221a-443a-b36a-4cb6c74d3206", "name": "/v1/compacts/:compact/providers/:providerId/privileges/jurisdiction/:jurisdiction/licenseType/:licenseType/deactivate", "protocolProfileBehavior": { "disableBodyPruning": true @@ -1993,7 +1839,7 @@ "value": "application/json" } ], - "id": "a57a09a4-c7df-400e-863d-2cba82b20fda", + "id": "cc5c5986-e041-40ac-95da-c1a77ff06a1c", "name": "200 response", "originalRequest": { "body": { @@ -2058,7 +1904,7 @@ "item": [ { "event": [], - "id": "981a70bc-5eb8-4922-9ad0-c8c2a2fa2b2e", + "id": "a652d362-1a74-4a53-a434-eccd030006f1", "name": "/v1/compacts/:compact/providers/:providerId/privileges/jurisdiction/:jurisdiction/licenseType/:licenseType/encumbrance", "protocolProfileBehavior": { "disableBodyPruning": true @@ -2072,7 +1918,7 @@ "language": "json" } }, - "raw": "{\n \"clinicalPrivilegeActionCategory\": \"\",\n \"encumbranceEffectiveDate\": \"2902-12-31\",\n \"encumbranceType\": \"revocation\"\n}" + "raw": "{\n \"encumbranceEffectiveDate\": \"1374-10-13\",\n \"encumbranceType\": \"modification of previous action-reduction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"clinicalPrivilegeActionCategory\": \"\"\n}" }, "description": {}, "header": [ @@ -2161,7 +2007,7 @@ "value": "application/json" } ], - "id": "1e5eb73a-ff53-476c-bcdf-2db5e6f51922", + "id": "52e1d309-2101-4f9d-856d-1c22fe2f8e45", "name": "200 response", "originalRequest": { "body": { @@ -2172,7 +2018,7 @@ "language": "json" } }, - "raw": "{\n \"clinicalPrivilegeActionCategory\": \"\",\n \"encumbranceEffectiveDate\": \"2902-12-31\",\n \"encumbranceType\": \"revocation\"\n}" + "raw": "{\n \"encumbranceEffectiveDate\": \"1374-10-13\",\n \"encumbranceType\": \"modification of previous action-reduction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"clinicalPrivilegeActionCategory\": \"\"\n}" }, "header": [ { @@ -2223,7 +2069,7 @@ "item": [ { "event": [], - "id": "26cb2cb6-a19c-4bca-be2f-7c852b428912", + "id": "1d5f45e7-fb36-46fe-9280-c6fceb3c49ef", "name": "/v1/compacts/:compact/providers/:providerId/privileges/jurisdiction/:jurisdiction/licenseType/:licenseType/encumbrance/:encumbranceId", "protocolProfileBehavior": { "disableBodyPruning": true @@ -2237,7 +2083,7 @@ "language": "json" } }, - "raw": "{\n \"effectiveLiftDate\": \"1840-05-08\"\n}" + "raw": "{\n \"effectiveLiftDate\": \"1227-11-31\"\n}" }, "description": {}, "header": [ @@ -2337,7 +2183,7 @@ "value": "application/json" } ], - "id": "9c4f8a0a-155c-4fc7-b330-e4455bb332f3", + "id": "1441370d-65bb-43d1-ae42-be7d0a48031b", "name": "200 response", "originalRequest": { "body": { @@ -2348,7 +2194,7 @@ "language": "json" } }, - "raw": "{\n \"effectiveLiftDate\": \"1840-05-08\"\n}" + "raw": "{\n \"effectiveLiftDate\": \"1227-11-31\"\n}" }, "header": [ { @@ -2406,7 +2252,7 @@ "item": [ { "event": [], - "id": "5f71f6c5-c018-4578-b137-23a2cf02af4a", + "id": "a8cb4b3d-8c95-4096-928e-3f3ea7d894fc", "name": "/v1/compacts/:compact/providers/:providerId/privileges/jurisdiction/:jurisdiction/licenseType/:licenseType/history", "protocolProfileBehavior": { "disableBodyPruning": true @@ -2487,7 +2333,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"compact\": \"aslp\",\n \"events\": [\n {\n \"createDate\": \"2045-12-31\",\n \"dateOfUpdate\": \"1129-07-16\",\n \"effectiveDate\": \"2387-02-11\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"renewal\",\n \"note\": \"\"\n },\n {\n \"createDate\": \"2088-04-04\",\n \"dateOfUpdate\": \"2290-11-08\",\n \"effectiveDate\": \"2973-10-31\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"licenseDeactivation\",\n \"note\": \"\"\n }\n ],\n \"jurisdiction\": \"wi\",\n \"licenseType\": \"occupational therapy assistant\",\n \"privilegeId\": \"\",\n \"providerId\": \"ac8c9bc7-3eff-45a8-bd01-e4e0e4746cfd\"\n}", + "body": "{\n \"compact\": \"octp\",\n \"events\": [\n {\n \"createDate\": \"2076-04-30\",\n \"dateOfUpdate\": \"2073-12-31\",\n \"effectiveDate\": \"2942-07-31\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"deactivation\",\n \"note\": \"\"\n },\n {\n \"createDate\": \"1430-12-20\",\n \"dateOfUpdate\": \"2556-06-30\",\n \"effectiveDate\": \"2731-07-30\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"registration\",\n \"note\": \"\"\n }\n ],\n \"jurisdiction\": \"or\",\n \"licenseType\": \"occupational therapist\",\n \"privilegeId\": \"\",\n \"providerId\": \"629b1a4f-7c8c-47cf-a9be-aabf6bf4e69e\"\n}", "code": 200, "cookie": [], "header": [ @@ -2496,7 +2342,7 @@ "value": "application/json" } ], - "id": "cff30401-7a31-4e2d-91a9-a79a25e81454", + "id": "48e29d51-12b0-4477-953b-d0fe92b8dd78", "name": "200 response", "originalRequest": { "body": {}, @@ -2563,7 +2409,7 @@ "item": [ { "event": [], - "id": "bee4355f-cdb0-403d-9d4b-1e426889e9b1", + "id": "ab2d0ef3-5216-4d3e-b32c-9b0d1dcaff52", "name": "/v1/compacts/:compact/providers/:providerId/ssn", "protocolProfileBehavior": { "disableBodyPruning": true @@ -2619,7 +2465,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"ssn\": \"172-12-8247\"\n}", + "body": "{\n \"ssn\": \"800-97-5405\"\n}", "code": 200, "cookie": [], "header": [ @@ -2628,7 +2474,7 @@ "value": "application/json" } ], - "id": "e651c5eb-d895-47ba-873f-49de5d2b42a5", + "id": "7c33d4d3-7398-4140-ac69-a1c5c872f4ee", "name": "200 response", "originalRequest": { "body": {}, @@ -2681,7 +2527,7 @@ "item": [ { "event": [], - "id": "54d66f86-c11d-45a5-a71b-edd76de9babb", + "id": "d0013ea7-8b5a-45e2-b88b-2168845c48f9", "name": "/v1/compacts/:compact/staff-users", "protocolProfileBehavior": { "disableBodyPruning": true @@ -2725,7 +2571,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"pagination\": {\n \"prevLastKey\": {},\n \"lastKey\": {},\n \"pageSize\": \"\"\n },\n \"users\": [\n {\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"inactive\",\n \"userId\": \"\"\n },\n {\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_3\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"inactive\",\n \"userId\": \"\"\n }\n ]\n}", + "body": "{\n \"pagination\": {\n \"prevLastKey\": {},\n \"lastKey\": {},\n \"pageSize\": \"\"\n },\n \"users\": [\n {\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"dolor_f\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"deserunt_f\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"active\",\n \"userId\": \"\"\n },\n {\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"officiaa07\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"ut_841\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"reprehenderit__83\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"magna_e2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"enim8\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"dolore_17\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"irure6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"pariatur_d1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"dolored0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"inactive\",\n \"userId\": \"\"\n }\n ]\n}", "code": 200, "cookie": [], "header": [ @@ -2743,7 +2589,7 @@ "value": "" } ], - "id": "6c3a420b-f667-4ff6-b766-4902011ce6e8", + "id": "3fcc47bf-17c8-42af-9bb7-0efeae4cf2d9", "name": "200 response", "originalRequest": { "body": {}, @@ -2782,7 +2628,7 @@ }, { "event": [], - "id": "9f5cd004-d32d-4874-abb6-24250d4b316e", + "id": "6510ac56-b3f6-4012-b24c-a9e233011dbf", "name": "/v1/compacts/:compact/staff-users", "protocolProfileBehavior": { "disableBodyPruning": true @@ -2796,7 +2642,7 @@ "language": "json" } }, - "raw": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n }\n}" + "raw": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"incididuntb7\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"ea_d\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"in4f6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"reprehenderit_a2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"occaecat3\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"nisi_b\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"ut_3\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n }\n}" }, "description": {}, "header": [ @@ -2839,7 +2685,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"active\",\n \"userId\": \"\"\n}", + "body": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"officia_25\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"exercitation_2d6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"proident8e6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"Duis_912\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"non9\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"fugiat_\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"inactive\",\n \"userId\": \"\"\n}", "code": 200, "cookie": [], "header": [ @@ -2857,7 +2703,7 @@ "value": "" } ], - "id": "b9a0bbed-474f-4831-a485-503edbd9cc9f", + "id": "7be83ef7-5255-4e95-bf52-65dc18487b97", "name": "200 response", "originalRequest": { "body": { @@ -2868,7 +2714,7 @@ "language": "json" } }, - "raw": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n }\n}" + "raw": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"incididuntb7\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"ea_d\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"in4f6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"reprehenderit_a2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"occaecat3\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"nisi_b\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"ut_3\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n }\n}" }, "header": [ { @@ -2912,7 +2758,7 @@ "item": [ { "event": [], - "id": "f9b11053-7ad6-41ff-b5e6-98afe6716fb2", + "id": "6c788cc6-0f48-42fe-a8fb-b0996c4e66b3", "name": "/v1/compacts/:compact/staff-users/:userId", "protocolProfileBehavior": { "disableBodyPruning": true @@ -2967,7 +2813,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"active\",\n \"userId\": \"\"\n}", + "body": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"officia_25\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"exercitation_2d6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"proident8e6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"Duis_912\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"non9\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"fugiat_\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"inactive\",\n \"userId\": \"\"\n}", "code": 200, "cookie": [], "header": [ @@ -2985,7 +2831,7 @@ "value": "" } ], - "id": "993e2a5b-49c8-4a3f-8f52-69b1c325148e", + "id": "b9a6a299-3522-4276-9ec2-62b6cd9061a1", "name": "200 response", "originalRequest": { "body": {}, @@ -3032,7 +2878,7 @@ "value": "application/json" } ], - "id": "183e0dd7-d1f2-456d-8bef-6fed2d05f575", + "id": "4adec6a5-5ac8-46ec-9cea-5f7f69f63552", "name": "404 response", "originalRequest": { "body": {}, @@ -3072,7 +2918,7 @@ }, { "event": [], - "id": "c6e3a762-0076-4377-bfcf-96323fc4be88", + "id": "faac95c0-dda5-4354-b7f6-7c8224d80055", "name": "/v1/compacts/:compact/staff-users/:userId", "protocolProfileBehavior": { "disableBodyPruning": true @@ -3136,7 +2982,7 @@ "value": "application/json" } ], - "id": "18566da3-8a86-4418-bbb5-bf5b1dcdf41d", + "id": "f37e0722-008d-481d-a42c-a3f79f8214d5", "name": "200 response", "originalRequest": { "body": {}, @@ -3183,7 +3029,7 @@ "value": "application/json" } ], - "id": "8fb3cde9-c0d1-4d5d-87ef-1febf8f70e08", + "id": "ed1880c9-d3c6-48ec-8483-51c82e1d293d", "name": "404 response", "originalRequest": { "body": {}, @@ -3223,7 +3069,7 @@ }, { "event": [], - "id": "de777b08-534d-4b0e-a3e0-8beb87fd4b81", + "id": "a47cb45f-1f16-453d-8878-eb05ed833ee8", "name": "/v1/compacts/:compact/staff-users/:userId", "protocolProfileBehavior": { "disableBodyPruning": true @@ -3237,7 +3083,7 @@ "language": "json" } }, - "raw": "{\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n }\n}" + "raw": "{\n \"permissions\": {\n \"nonc4\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"dolor88c\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"adipisicing_63\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"laboris98a\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"mollita1a\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"non4b9\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"dolor3\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"do__\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"occaecat_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"fugiat5\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n }\n}" }, "description": {}, "header": [ @@ -3291,7 +3137,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"active\",\n \"userId\": \"\"\n}", + "body": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"officia_25\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"exercitation_2d6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"proident8e6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"Duis_912\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"non9\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"fugiat_\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"inactive\",\n \"userId\": \"\"\n}", "code": 200, "cookie": [], "header": [ @@ -3309,7 +3155,7 @@ "value": "" } ], - "id": "953b30de-0870-4c25-8e4e-a4ea36f257d1", + "id": "6cd6fa0f-c3f1-4eb6-870d-962a75127d25", "name": "200 response", "originalRequest": { "body": { @@ -3320,7 +3166,7 @@ "language": "json" } }, - "raw": "{\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n }\n}" + "raw": "{\n \"permissions\": {\n \"nonc4\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"dolor88c\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"adipisicing_63\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"laboris98a\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"mollita1a\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"non4b9\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"dolor3\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"do__\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"occaecat_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"fugiat5\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n }\n}" }, "header": [ { @@ -3369,7 +3215,7 @@ "value": "application/json" } ], - "id": "678d42a1-fb71-4ee3-9d16-02a159e57b0d", + "id": "e18b71ff-9c60-4064-bb86-483b0159a83c", "name": "404 response", "originalRequest": { "body": { @@ -3380,7 +3226,7 @@ "language": "json" } }, - "raw": "{\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n }\n}" + "raw": "{\n \"permissions\": {\n \"nonc4\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"dolor88c\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"adipisicing_63\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"laboris98a\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"mollita1a\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"non4b9\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"dolor3\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"do__\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"occaecat_2\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"fugiat5\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n }\n}" }, "header": [ { @@ -3425,7 +3271,7 @@ "item": [ { "event": [], - "id": "37431eba-9269-4f2e-b5cd-d29086712dd7", + "id": "f08dcc99-66b0-4c52-981c-85861c222ca4", "name": "/v1/compacts/:compact/staff-users/:userId/reinvite", "protocolProfileBehavior": { "disableBodyPruning": true @@ -3490,7 +3336,7 @@ "value": "application/json" } ], - "id": "35dcee34-292c-4843-9f26-2cd9f67d5b71", + "id": "ecf11a79-81a1-4f45-9be1-27c4f92bd712", "name": "200 response", "originalRequest": { "body": {}, @@ -3538,7 +3384,7 @@ "value": "application/json" } ], - "id": "5d62643f-3434-425c-ac6a-586c59d0f6a0", + "id": "a216484d-3c39-4539-8c73-fe2264f8fe76", "name": "404 response", "originalRequest": { "body": {}, @@ -3603,7 +3449,7 @@ "item": [ { "event": [], - "id": "29b03e3b-ece9-41fe-acfb-080f481f7ea7", + "id": "f998ed90-65ef-4574-982d-e74f490a03c6", "name": "/v1/flags/:flagId/check", "protocolProfileBehavior": { "disableBodyPruning": true @@ -3620,7 +3466,7 @@ "language": "json" } }, - "raw": "{\n \"context\": {\n \"userId\": \"\",\n \"customAttributes\": {\n \"key_0\": \"\",\n \"key_1\": \"\"\n }\n }\n}" + "raw": "{\n \"context\": {\n \"userId\": \"\",\n \"customAttributes\": {\n \"cillum__f\": \"\",\n \"in_dab\": \"\",\n \"eiusmod63\": \"\"\n }\n }\n}" }, "description": {}, "header": [ @@ -3672,7 +3518,7 @@ "value": "application/json" } ], - "id": "526a261a-ef21-4de4-a499-e9a5d8f6aac0", + "id": "63181a7e-3f53-4525-9165-6e44e9203dba", "name": "200 response", "originalRequest": { "body": { @@ -3683,7 +3529,7 @@ "language": "json" } }, - "raw": "{\n \"context\": {\n \"userId\": \"\",\n \"customAttributes\": {\n \"key_0\": \"\",\n \"key_1\": \"\"\n }\n }\n}" + "raw": "{\n \"context\": {\n \"userId\": \"\",\n \"customAttributes\": {\n \"cillum__f\": \"\",\n \"in_dab\": \"\",\n \"eiusmod63\": \"\"\n }\n }\n}" }, "header": [ { @@ -3741,7 +3587,7 @@ "item": [ { "event": [], - "id": "bb60b0cb-9a3d-4223-8832-18d43a3f2d8a", + "id": "75981dbd-08de-4f58-85b4-49ff1b4c4ab2", "name": "/v1/provider-users/initiateRecovery", "protocolProfileBehavior": { "disableBodyPruning": true @@ -3758,7 +3604,7 @@ "language": "json" } }, - "raw": "{\n \"compact\": \"coun\",\n \"dob\": \"1421-10-08\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdiction\": \"fl\",\n \"licenseType\": \"occupational therapist\",\n \"partialSocial\": \"7143\",\n \"password\": \"\",\n \"recaptchaToken\": \"\",\n \"username\": \"\"\n}" + "raw": "{\n \"compact\": \"octp\",\n \"dob\": \"1878-12-30\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdiction\": \"ak\",\n \"licenseType\": \"licensed professional counselor\",\n \"partialSocial\": \"0818\",\n \"password\": \"\",\n \"recaptchaToken\": \"\",\n \"username\": \"\"\n}" }, "description": {}, "header": [ @@ -3798,7 +3644,7 @@ "value": "application/json" } ], - "id": "e130482e-b115-45f0-9ace-04054ab2b2c1", + "id": "3b850382-90d7-4229-8439-da59d5446ad3", "name": "200 response", "originalRequest": { "body": { @@ -3809,7 +3655,7 @@ "language": "json" } }, - "raw": "{\n \"compact\": \"coun\",\n \"dob\": \"1421-10-08\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdiction\": \"fl\",\n \"licenseType\": \"occupational therapist\",\n \"partialSocial\": \"7143\",\n \"password\": \"\",\n \"recaptchaToken\": \"\",\n \"username\": \"\"\n}" + "raw": "{\n \"compact\": \"octp\",\n \"dob\": \"1878-12-30\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdiction\": \"ak\",\n \"licenseType\": \"licensed professional counselor\",\n \"partialSocial\": \"0818\",\n \"password\": \"\",\n \"recaptchaToken\": \"\",\n \"username\": \"\"\n}" }, "header": [ { @@ -3847,7 +3693,7 @@ "item": [ { "event": [], - "id": "338d97c6-0953-4f70-b7f0-0ab38bf45c3c", + "id": "35b736e9-e074-48ed-a195-3972a61c841c", "name": "/v1/provider-users/me", "protocolProfileBehavior": { "disableBodyPruning": true @@ -3879,7 +3725,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"birthMonthDay\": \"18-05\",\n \"compact\": \"aslp\",\n \"dateOfExpiration\": \"1114-09-12\",\n \"dateOfUpdate\": \"1433-03-23\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"licenseJurisdiction\": \"ar\",\n \"licenses\": [\n {\n \"compact\": \"aslp\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfExpiration\": \"1306-03-08\",\n \"dateOfIssuance\": \"1030-12-30\",\n \"dateOfRenewal\": \"2474-02-05\",\n \"dateOfUpdate\": \"2475-10-30\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"history\": [\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"1010-10-30\",\n \"jurisdiction\": \"nm\",\n \"previous\": {\n \"dateOfExpiration\": \"2000-10-31\",\n \"dateOfIssuance\": \"1844-02-31\",\n \"dateOfRenewal\": \"1608-11-02\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"1753423147\",\n \"compactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1452-01-06\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+1309397612826\",\n \"licenseStatus\": \"active\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"encumbrance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"occupational therapy assistant\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"3671735098\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"2873-07-02\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"1031-11-02\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"1975-11-12\",\n \"phoneNumber\": \"+17851605\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"1695-07-10\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n },\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"1541-11-31\",\n \"jurisdiction\": \"ma\",\n \"previous\": {\n \"dateOfExpiration\": \"1936-10-30\",\n \"dateOfIssuance\": \"2331-04-30\",\n \"dateOfRenewal\": \"2842-11-30\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"9804384619\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"2010-11-16\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+71413357\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"other\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"8250482424\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"eligible\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1069-04-05\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"2613-04-31\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"2711-11-03\",\n \"phoneNumber\": \"+2050697721898\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"1517-05-02\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n }\n ],\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdiction\": \"az\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"licenseStatus\": \"inactive\",\n \"licenseType\": \"licensed professional counselor\",\n \"middleName\": \"\",\n \"providerId\": \"b0496763-ec92-4a47-ab2f-4536b681bd38\",\n \"type\": \"license-home\",\n \"homeAddressStreet2\": \"\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"licenseNumber\": \"\",\n \"npi\": \"6095695256\",\n \"dateOfBirth\": \"1320-04-03\",\n \"ssnLastFour\": \"1076\",\n \"phoneNumber\": \"+382839208006\",\n \"licenseStatusName\": \"\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"aslp\",\n \"creationDate\": \"1214-10-30\",\n \"dateOfUpdate\": \"2390-11-06\",\n \"effectiveStartDate\": \"2953-01-18\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"hi\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"0b8fe736-c033-4136-91f5-eda7f2b8ba7f\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2194-04-08\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"1503-05-25\",\n \"dateOfUpdate\": \"1262-01-13\",\n \"effectiveStartDate\": \"2162-09-31\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"id\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"3d8e7a68-4df4-47c3-adb9-d5e575911bc0\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2812-01-31\",\n \"liftingUser\": \"\"\n }\n ]\n },\n {\n \"compact\": \"octp\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfExpiration\": \"2646-12-18\",\n \"dateOfIssuance\": \"1304-11-30\",\n \"dateOfRenewal\": \"1212-10-06\",\n \"dateOfUpdate\": \"2731-02-08\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"history\": [\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"2968-11-05\",\n \"jurisdiction\": \"oh\",\n \"previous\": {\n \"dateOfExpiration\": \"1495-02-09\",\n \"dateOfIssuance\": \"2074-08-09\",\n \"dateOfRenewal\": \"2897-05-18\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"3591668223\",\n \"compactEligibility\": \"eligible\",\n \"dateOfBirth\": \"2528-12-16\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+925332212023\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"renewal\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"licensed professional counselor\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"3128128708\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1615-03-27\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"1858-12-12\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"2093-05-06\",\n \"phoneNumber\": \"+88862351397\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"2188-02-03\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n },\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"1014-09-30\",\n \"jurisdiction\": \"nc\",\n \"previous\": {\n \"dateOfExpiration\": \"2200-12-17\",\n \"dateOfIssuance\": \"1483-08-09\",\n \"dateOfRenewal\": \"1580-11-04\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"7107653147\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"1684-12-09\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+982749013585799\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"licenseDeactivation\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"speech-language pathologist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"1201882644\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1252-11-27\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"1019-08-30\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"1397-11-30\",\n \"phoneNumber\": \"+52496923166065\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"2633-03-17\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n }\n ],\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdiction\": \"md\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"licenseStatus\": \"active\",\n \"licenseType\": \"occupational therapist\",\n \"middleName\": \"\",\n \"providerId\": \"e3b45a75-ebd9-4b90-aa3e-93a1ccef8db3\",\n \"type\": \"license-home\",\n \"homeAddressStreet2\": \"\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"licenseNumber\": \"\",\n \"npi\": \"1310126629\",\n \"dateOfBirth\": \"2033-10-30\",\n \"ssnLastFour\": \"4546\",\n \"phoneNumber\": \"+2458662829273\",\n \"licenseStatusName\": \"\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"1494-09-09\",\n \"dateOfUpdate\": \"1137-01-30\",\n \"effectiveStartDate\": \"1605-10-27\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"de\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"77f72e9e-b1c0-4550-8378-2ef810a520b5\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2220-10-30\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"1487-10-03\",\n \"dateOfUpdate\": \"2605-12-30\",\n \"effectiveStartDate\": \"1965-06-14\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"il\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"a4311387-4e26-4f26-ba5a-1deafc45e728\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1069-05-25\",\n \"liftingUser\": \"\"\n }\n ]\n }\n ],\n \"militaryAffiliations\": [\n {\n \"affiliationType\": \"militaryMember\",\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1725-12-30\",\n \"dateOfUpload\": \"2049-12-25\",\n \"fileNames\": [\n \"\",\n \"\"\n ],\n \"providerId\": \"e0e86c9f-b5eb-426a-90ac-36829f8388bd\",\n \"status\": \"active\",\n \"type\": \"militaryAffiliation\",\n \"downloadLinks\": [\n {\n \"fileName\": \"\",\n \"url\": \"\"\n },\n {\n \"fileName\": \"\",\n \"url\": \"\"\n }\n ]\n },\n {\n \"affiliationType\": \"militaryMember\",\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1892-12-11\",\n \"dateOfUpload\": \"1877-11-07\",\n \"fileNames\": [\n \"\",\n \"\"\n ],\n \"providerId\": \"8385072b-15c4-4e87-b06b-97a1eb9e68a7\",\n \"status\": \"active\",\n \"type\": \"militaryAffiliation\",\n \"downloadLinks\": [\n {\n \"fileName\": \"\",\n \"url\": \"\"\n },\n {\n \"fileName\": \"\",\n \"url\": \"\"\n }\n ]\n }\n ],\n \"privilegeJurisdictions\": [\n \"mn\",\n \"tn\"\n ],\n \"privileges\": [\n {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compact\": \"octp\",\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1446-11-31\",\n \"dateOfIssuance\": \"1724-04-07\",\n \"dateOfRenewal\": \"2644-08-21\",\n \"dateOfUpdate\": \"2229-06-07\",\n \"history\": [\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"2991-04-08\",\n \"jurisdiction\": \"il\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1660-12-30\",\n \"dateOfIssuance\": \"1313-03-24\",\n \"dateOfRenewal\": \"2145-12-31\",\n \"dateOfUpdate\": \"2403-05-30\",\n \"licenseJurisdiction\": \"vi\",\n \"privilegeId\": \"\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"il\",\n \"type\": \"privilege\",\n \"providerId\": \"d4ad584f-9f2b-4b92-ba60-7fe995bbf582\",\n \"status\": \"active\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"issuance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"va\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"al\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"1534-03-30\",\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"2504-03-30\",\n \"privilegeId\": \"\",\n \"providerId\": \"e3713f86-cda1-48f5-8683-caf9abb02462\",\n \"dateOfRenewal\": \"2667-12-07\",\n \"dateOfUpdate\": \"2148-10-04\",\n \"status\": \"inactive\"\n }\n },\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"2016-07-31\",\n \"jurisdiction\": \"ks\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"2781-11-17\",\n \"dateOfIssuance\": \"2079-03-20\",\n \"dateOfRenewal\": \"2623-10-31\",\n \"dateOfUpdate\": \"2572-07-31\",\n \"licenseJurisdiction\": \"la\",\n \"privilegeId\": \"\",\n \"compact\": \"aslp\",\n \"jurisdiction\": \"ne\",\n \"type\": \"privilege\",\n \"providerId\": \"eb1f0881-30a4-40ff-b2b1-fac2a1af50d3\",\n \"status\": \"active\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"licenseDeactivation\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"ar\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"tn\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"2044-12-09\",\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"1521-08-30\",\n \"privilegeId\": \"\",\n \"providerId\": \"09e6288d-de40-4fc0-b519-d19cf7e84a25\",\n \"dateOfRenewal\": \"2128-07-18\",\n \"dateOfUpdate\": \"1744-04-06\",\n \"status\": \"inactive\"\n }\n }\n ],\n \"jurisdiction\": \"ga\",\n \"licenseJurisdiction\": \"md\",\n \"licenseType\": \"occupational therapy assistant\",\n \"privilegeId\": \"\",\n \"providerId\": \"e5e4b3ff-d893-4958-a1d3-50e1fddb2521\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"aslp\",\n \"creationDate\": \"2273-02-08\",\n \"dateOfUpdate\": \"1801-06-24\",\n \"effectiveStartDate\": \"2299-08-30\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"ms\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"7540c90b-f2ce-4e8d-aff7-00ed6bf8a3b8\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2819-12-30\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"2967-12-30\",\n \"dateOfUpdate\": \"2051-03-19\",\n \"effectiveStartDate\": \"2562-10-31\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"wi\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"9a1790c1-066a-493c-af95-06983d3362be\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1103-10-12\",\n \"liftingUser\": \"\"\n }\n ]\n },\n {\n \"administratorSetStatus\": \"inactive\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compact\": \"aslp\",\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1800-11-05\",\n \"dateOfIssuance\": \"2485-03-30\",\n \"dateOfRenewal\": \"1669-04-31\",\n \"dateOfUpdate\": \"1350-10-05\",\n \"history\": [\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2614-10-01\",\n \"jurisdiction\": \"ne\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1548-10-30\",\n \"dateOfIssuance\": \"2661-11-09\",\n \"dateOfRenewal\": \"2248-01-29\",\n \"dateOfUpdate\": \"2755-12-25\",\n \"licenseJurisdiction\": \"il\",\n \"privilegeId\": \"\",\n \"compact\": \"aslp\",\n \"jurisdiction\": \"mi\",\n \"type\": \"privilege\",\n \"providerId\": \"b119e009-e3eb-4e39-a447-d1f5a0d988bf\",\n \"status\": \"inactive\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"deactivation\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"nm\",\n \"compact\": \"aslp\",\n \"jurisdiction\": \"ut\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"2223-12-26\",\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"2850-10-08\",\n \"privilegeId\": \"\",\n \"providerId\": \"af1366f2-f7b6-473d-b051-1a4a8283155d\",\n \"dateOfRenewal\": \"1460-06-08\",\n \"dateOfUpdate\": \"1832-12-14\",\n \"status\": \"active\"\n }\n },\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"1183-11-31\",\n \"jurisdiction\": \"wv\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"2933-09-11\",\n \"dateOfIssuance\": \"2180-10-02\",\n \"dateOfRenewal\": \"1762-02-07\",\n \"dateOfUpdate\": \"2602-11-05\",\n \"licenseJurisdiction\": \"mn\",\n \"privilegeId\": \"\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"wv\",\n \"type\": \"privilege\",\n \"providerId\": \"b41e9a0f-0596-401e-9e13-dd17170e1a1c\",\n \"status\": \"inactive\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"lifting_encumbrance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"occupational therapist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"pr\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"sd\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"2472-11-09\",\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"1343-12-16\",\n \"privilegeId\": \"\",\n \"providerId\": \"3040c8ef-5bd6-40e4-882a-4657292afe28\",\n \"dateOfRenewal\": \"2523-10-30\",\n \"dateOfUpdate\": \"2533-04-19\",\n \"status\": \"inactive\"\n }\n }\n ],\n \"jurisdiction\": \"ia\",\n \"licenseJurisdiction\": \"sc\",\n \"licenseType\": \"licensed professional counselor\",\n \"privilegeId\": \"\",\n \"providerId\": \"54c8c814-9dfb-4f13-8b96-722dd65cd6f9\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"1172-10-05\",\n \"dateOfUpdate\": \"2404-07-05\",\n \"effectiveStartDate\": \"2365-03-30\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"md\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"098a460c-fd37-4c28-899e-85dbf064cb56\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1464-07-01\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"compact\": \"aslp\",\n \"creationDate\": \"2725-03-23\",\n \"dateOfUpdate\": \"2839-04-26\",\n \"effectiveStartDate\": \"1105-12-01\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"il\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"26b21d87-9527-433f-aa95-752626fca36f\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2025-05-26\",\n \"liftingUser\": \"\"\n }\n ]\n }\n ],\n \"providerId\": \"83940727-a1af-4b19-99bb-c35b22f25c66\",\n \"type\": \"provider\",\n \"npi\": \"4129573768\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1535-03-08\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"sd\",\n \"ssnLastFour\": \"5379\",\n \"licenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"compactConnectRegisteredEmailAddress\": \"\"\n}", + "body": "{\n \"birthMonthDay\": \"10-13\",\n \"compact\": \"octp\",\n \"dateOfExpiration\": \"2708-12-19\",\n \"dateOfUpdate\": \"2235-11-07\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"licenseJurisdiction\": \"or\",\n \"licenses\": [\n {\n \"compact\": \"octp\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfExpiration\": \"1194-11-07\",\n \"dateOfIssuance\": \"1811-01-06\",\n \"dateOfRenewal\": \"1005-01-30\",\n \"dateOfUpdate\": \"1228-10-17\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"history\": [\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"1122-08-31\",\n \"jurisdiction\": \"de\",\n \"previous\": {\n \"dateOfExpiration\": \"2825-06-30\",\n \"dateOfIssuance\": \"2552-11-09\",\n \"dateOfRenewal\": \"1554-03-08\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"7904266478\",\n \"compactEligibility\": \"eligible\",\n \"dateOfBirth\": \"1130-10-09\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+127199520822501\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"expiration\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"7996207438\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"2689-12-23\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"2349-01-07\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"1981-10-31\",\n \"phoneNumber\": \"+48186155665\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"2985-03-02\",\n \"licenseStatus\": \"active\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n },\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2799-03-17\",\n \"jurisdiction\": \"pa\",\n \"previous\": {\n \"dateOfExpiration\": \"1712-01-28\",\n \"dateOfIssuance\": \"2124-05-31\",\n \"dateOfRenewal\": \"1804-12-25\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"3975501387\",\n \"compactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"1678-08-23\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+80432649\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"deactivation\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"speech-language pathologist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"5745410699\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"2459-01-20\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"2074-05-31\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"1606-04-30\",\n \"phoneNumber\": \"+38094519029451\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"2402-11-03\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n }\n ],\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdiction\": \"mo\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"licenseStatus\": \"active\",\n \"licenseType\": \"audiologist\",\n \"middleName\": \"\",\n \"providerId\": \"d6a677d3-d7fb-4780-9aa5-0b54def3f5fb\",\n \"type\": \"license-home\",\n \"homeAddressStreet2\": \"\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"licenseNumber\": \"\",\n \"npi\": \"6162231934\",\n \"dateOfBirth\": \"2116-11-23\",\n \"ssnLastFour\": \"2827\",\n \"phoneNumber\": \"+316315679209\",\n \"licenseStatusName\": \"\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"2958-09-30\",\n \"dateOfUpdate\": \"1010-09-30\",\n \"effectiveStartDate\": \"2967-11-11\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"md\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"92cf3f74-4eba-4e03-8960-fe8244789ade\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"2333-10-23\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"2829-11-23\",\n \"dateOfUpdate\": \"1986-11-31\",\n \"effectiveStartDate\": \"1863-08-02\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"ca\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"3ebb12e1-61e9-4764-bc27-deb0c708968b\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"2426-05-14\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n }\n ]\n },\n {\n \"compact\": \"coun\",\n \"compactEligibility\": \"eligible\",\n \"dateOfExpiration\": \"2303-05-13\",\n \"dateOfIssuance\": \"1600-02-08\",\n \"dateOfRenewal\": \"1136-11-23\",\n \"dateOfUpdate\": \"2758-11-26\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"history\": [\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"2228-10-08\",\n \"jurisdiction\": \"or\",\n \"previous\": {\n \"dateOfExpiration\": \"1909-03-15\",\n \"dateOfIssuance\": \"1920-12-19\",\n \"dateOfRenewal\": \"1820-11-05\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"4309547090\",\n \"compactEligibility\": \"eligible\",\n \"dateOfBirth\": \"2575-01-06\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+282921155\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"encumbrance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"audiologist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"1272654411\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"2191-12-26\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"2166-09-22\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"2233-10-31\",\n \"phoneNumber\": \"+83080416937936\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"1714-09-03\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n },\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1525-12-30\",\n \"jurisdiction\": \"ca\",\n \"previous\": {\n \"dateOfExpiration\": \"1149-10-31\",\n \"dateOfIssuance\": \"1206-01-04\",\n \"dateOfRenewal\": \"2125-10-28\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"homeAddressStreet2\": \"\",\n \"npi\": \"7139133672\",\n \"compactEligibility\": \"eligible\",\n \"dateOfBirth\": \"2503-11-06\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"phoneNumber\": \"+22157243484\",\n \"licenseStatus\": \"inactive\",\n \"licenseNumber\": \"\",\n \"licenseStatusName\": \"\"\n },\n \"type\": \"licenseUpdate\",\n \"updateType\": \"issuance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"occupational therapist\",\n \"updatedValues\": {\n \"homeAddressStreet2\": \"\",\n \"npi\": \"5902669871\",\n \"homeAddressPostalCode\": \"\",\n \"givenName\": \"\",\n \"homeAddressStreet1\": \"\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"dateOfBirth\": \"1846-06-16\",\n \"jurisdictionUploadedLicenseStatus\": \"inactive\",\n \"suffix\": \"\",\n \"dateOfIssuance\": \"1530-10-31\",\n \"emailAddress\": \"\",\n \"dateOfExpiration\": \"2630-10-29\",\n \"phoneNumber\": \"+463314989084\",\n \"homeAddressState\": \"\",\n \"dateOfRenewal\": \"2898-04-19\",\n \"licenseStatus\": \"inactive\",\n \"familyName\": \"\",\n \"homeAddressCity\": \"\",\n \"licenseNumber\": \"\",\n \"middleName\": \"\",\n \"licenseStatusName\": \"\"\n }\n }\n ],\n \"homeAddressCity\": \"\",\n \"homeAddressPostalCode\": \"\",\n \"homeAddressState\": \"\",\n \"homeAddressStreet1\": \"\",\n \"jurisdiction\": \"ri\",\n \"jurisdictionUploadedCompactEligibility\": \"ineligible\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"licenseStatus\": \"active\",\n \"licenseType\": \"occupational therapy assistant\",\n \"middleName\": \"\",\n \"providerId\": \"90bf4c45-b2bc-4e1c-9055-23adc019b9ff\",\n \"type\": \"license-home\",\n \"homeAddressStreet2\": \"\",\n \"suffix\": \"\",\n \"emailAddress\": \"\",\n \"licenseNumber\": \"\",\n \"npi\": \"6796883381\",\n \"dateOfBirth\": \"2836-10-24\",\n \"ssnLastFour\": \"3288\",\n \"phoneNumber\": \"+58540754234\",\n \"licenseStatusName\": \"\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"aslp\",\n \"creationDate\": \"1925-08-08\",\n \"dateOfUpdate\": \"2975-04-19\",\n \"effectiveStartDate\": \"2776-11-04\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"tn\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"17990d99-1def-4abd-8a8a-3122ca3219da\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"2663-04-30\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"1285-04-03\",\n \"dateOfUpdate\": \"2856-10-30\",\n \"effectiveStartDate\": \"2544-08-30\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"ky\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"2b1d1723-dfb8-40bc-90cf-902c703548c9\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"1523-10-10\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n }\n ]\n }\n ],\n \"militaryAffiliations\": [\n {\n \"affiliationType\": \"militaryMemberSpouse\",\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2565-05-30\",\n \"dateOfUpload\": \"2261-11-03\",\n \"fileNames\": [\n \"\",\n \"\"\n ],\n \"providerId\": \"84e50f08-03c5-4137-b371-2550b5369cdb\",\n \"status\": \"inactive\",\n \"type\": \"militaryAffiliation\",\n \"downloadLinks\": [\n {\n \"fileName\": \"\",\n \"url\": \"\"\n },\n {\n \"fileName\": \"\",\n \"url\": \"\"\n }\n ]\n },\n {\n \"affiliationType\": \"militaryMember\",\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2471-04-28\",\n \"dateOfUpload\": \"2015-12-30\",\n \"fileNames\": [\n \"\",\n \"\"\n ],\n \"providerId\": \"6850e115-8f7f-4f2e-bb91-d0710a6fc6c7\",\n \"status\": \"active\",\n \"type\": \"militaryAffiliation\",\n \"downloadLinks\": [\n {\n \"fileName\": \"\",\n \"url\": \"\"\n },\n {\n \"fileName\": \"\",\n \"url\": \"\"\n }\n ]\n }\n ],\n \"privilegeJurisdictions\": [\n \"il\",\n \"wa\"\n ],\n \"privileges\": [\n {\n \"administratorSetStatus\": \"inactive\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compact\": \"aslp\",\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1403-11-30\",\n \"dateOfIssuance\": \"2058-06-04\",\n \"dateOfRenewal\": \"2848-04-31\",\n \"dateOfUpdate\": \"2721-10-29\",\n \"history\": [\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2232-10-08\",\n \"jurisdiction\": \"hi\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"2380-07-31\",\n \"dateOfIssuance\": \"1675-11-01\",\n \"dateOfRenewal\": \"1533-01-06\",\n \"dateOfUpdate\": \"1664-10-31\",\n \"licenseJurisdiction\": \"dc\",\n \"privilegeId\": \"\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"oh\",\n \"type\": \"privilege\",\n \"providerId\": \"f215ffd6-257c-40c5-8daa-9a21135d1b03\",\n \"status\": \"inactive\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"lifting_encumbrance\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"occupational therapist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"id\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"sc\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"2178-07-01\",\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"2128-01-07\",\n \"privilegeId\": \"\",\n \"providerId\": \"11b11933-f36a-4eb7-83a0-542011f49873\",\n \"dateOfRenewal\": \"2696-05-20\",\n \"dateOfUpdate\": \"1259-03-06\",\n \"status\": \"inactive\"\n }\n },\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1899-11-28\",\n \"jurisdiction\": \"id\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1808-12-25\",\n \"dateOfIssuance\": \"1867-04-31\",\n \"dateOfRenewal\": \"1948-03-09\",\n \"dateOfUpdate\": \"1544-11-09\",\n \"licenseJurisdiction\": \"pr\",\n \"privilegeId\": \"\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"ak\",\n \"type\": \"privilege\",\n \"providerId\": \"98e3f59c-0fbc-4aa4-bce1-7d5689f18812\",\n \"status\": \"inactive\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"renewal\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"occupational therapist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"wv\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"id\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"1221-02-30\",\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"2814-11-15\",\n \"privilegeId\": \"\",\n \"providerId\": \"532d563d-a1bc-40dc-a5f0-8a0a86f05451\",\n \"dateOfRenewal\": \"1885-12-31\",\n \"dateOfUpdate\": \"1384-02-11\",\n \"status\": \"active\"\n }\n }\n ],\n \"jurisdiction\": \"vt\",\n \"licenseJurisdiction\": \"mn\",\n \"licenseType\": \"occupational therapy assistant\",\n \"privilegeId\": \"\",\n \"providerId\": \"4b524f8c-6a30-4ee6-ab6c-55c37a68167f\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"2986-01-02\",\n \"dateOfUpdate\": \"1994-10-13\",\n \"effectiveStartDate\": \"1242-11-28\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"sc\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"bbf662ac-7e91-4140-903c-0c350d7dc5f7\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"2961-12-04\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"2886-12-31\",\n \"dateOfUpdate\": \"2098-11-30\",\n \"effectiveStartDate\": \"1188-03-30\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"me\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"7a3ab2b7-4041-47eb-94c4-e50ec792a958\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"2457-03-28\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n }\n ]\n },\n {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compact\": \"coun\",\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1412-03-31\",\n \"dateOfIssuance\": \"1750-01-08\",\n \"dateOfRenewal\": \"2654-02-08\",\n \"dateOfUpdate\": \"1882-06-30\",\n \"history\": [\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"1696-11-03\",\n \"jurisdiction\": \"fl\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"2747-09-30\",\n \"dateOfIssuance\": \"2819-02-21\",\n \"dateOfRenewal\": \"1924-12-14\",\n \"dateOfUpdate\": \"2059-01-31\",\n \"licenseJurisdiction\": \"pr\",\n \"privilegeId\": \"\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"ks\",\n \"type\": \"privilege\",\n \"providerId\": \"81e91006-0dfe-4322-8a41-b7d78aae5f69\",\n \"status\": \"active\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"licenseDeactivation\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"speech-language pathologist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"az\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"sc\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"1608-08-04\",\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"2931-11-31\",\n \"privilegeId\": \"\",\n \"providerId\": \"c4cc5de7-00ec-43e9-97f0-5dab5c0ae1a6\",\n \"dateOfRenewal\": \"1003-10-19\",\n \"dateOfUpdate\": \"1809-12-04\",\n \"status\": \"inactive\"\n }\n },\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1973-11-16\",\n \"jurisdiction\": \"ia\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"compactTransactionId\": \"\",\n \"dateOfExpiration\": \"1210-10-31\",\n \"dateOfIssuance\": \"1470-12-02\",\n \"dateOfRenewal\": \"2582-01-31\",\n \"dateOfUpdate\": \"1348-05-14\",\n \"licenseJurisdiction\": \"ks\",\n \"privilegeId\": \"\",\n \"compact\": \"coun\",\n \"jurisdiction\": \"ok\",\n \"type\": \"privilege\",\n \"providerId\": \"e364f6bd-3d30-4881-ad2e-99d25dd13612\",\n \"status\": \"inactive\"\n },\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"emailChange\",\n \"removedValues\": [\n \"\",\n \"\"\n ],\n \"licenseType\": \"speech-language pathologist\",\n \"updatedValues\": {\n \"licenseJurisdiction\": \"md\",\n \"compact\": \"octp\",\n \"jurisdiction\": \"me\",\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"\"\n }\n ],\n \"type\": \"privilege\",\n \"compactTransactionId\": \"\",\n \"dateOfIssuance\": \"1321-02-30\",\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"1415-12-13\",\n \"privilegeId\": \"\",\n \"providerId\": \"2550a822-a6a2-46f5-9d6f-381ad5c7ad50\",\n \"dateOfRenewal\": \"1441-10-20\",\n \"dateOfUpdate\": \"2823-01-02\",\n \"status\": \"active\"\n }\n }\n ],\n \"jurisdiction\": \"ky\",\n \"licenseJurisdiction\": \"ne\",\n \"licenseType\": \"speech-language pathologist\",\n \"privilegeId\": \"\",\n \"providerId\": \"e7d03cad-55f3-4a69-bf06-109772196128\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"1836-11-03\",\n \"dateOfUpdate\": \"1386-07-12\",\n \"effectiveStartDate\": \"2383-04-14\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"ar\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"91d01ece-89f1-46d0-8105-52a9517f6a70\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"1297-12-28\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"1188-10-30\",\n \"dateOfUpdate\": \"2977-10-31\",\n \"effectiveStartDate\": \"2846-08-30\",\n \"encumbranceType\": \"\",\n \"jurisdiction\": \"fl\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"5205a6c0-1147-4655-a17b-ff3780c163d9\",\n \"type\": \"adverseAction\",\n \"clinicalPrivilegeActionCategories\": [\n \"\",\n \"\"\n ],\n \"effectiveLiftDate\": \"1879-11-24\",\n \"clinicalPrivilegeActionCategory\": \"\",\n \"liftingUser\": \"\"\n }\n ]\n }\n ],\n \"providerId\": \"94022a97-0d0d-4153-bda8-a15afc713ee2\",\n \"type\": \"provider\",\n \"npi\": \"8197107476\",\n \"compactEligibility\": \"ineligible\",\n \"jurisdictionUploadedCompactEligibility\": \"eligible\",\n \"dateOfBirth\": \"2021-12-30\",\n \"jurisdictionUploadedLicenseStatus\": \"active\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"sc\",\n \"ssnLastFour\": \"2592\",\n \"licenseStatus\": \"inactive\",\n \"middleName\": \"\",\n \"compactConnectRegisteredEmailAddress\": \"\"\n}", "code": 200, "cookie": [], "header": [ @@ -3888,7 +3734,7 @@ "value": "application/json" } ], - "id": "d814fa51-d6d3-4b8b-a80c-c8be12366bb5", + "id": "ef115f6d-e0a3-422d-adda-71e0a169c54e", "name": "200 response", "originalRequest": { "body": {}, @@ -3929,7 +3775,7 @@ "item": [ { "event": [], - "id": "b3f5a9a9-7252-4808-a3aa-0e0d5087bf42", + "id": "8a6a586e-c161-4748-bdfa-8bcb5a734955", "name": "/v1/provider-users/me/email", "protocolProfileBehavior": { "disableBodyPruning": true @@ -3984,7 +3830,7 @@ "value": "application/json" } ], - "id": "cbe67273-226e-42b0-9239-e2862a58cd7b", + "id": "f7f9ab26-3204-49c3-9253-fd7381331dde", "name": "200 response", "originalRequest": { "body": { @@ -4039,7 +3885,7 @@ "item": [ { "event": [], - "id": "cce2d524-d6db-4b8a-9143-19c2fef73e90", + "id": "a43d9841-7ee0-41c4-a364-04637f05e883", "name": "/v1/provider-users/me/email/verify", "protocolProfileBehavior": { "disableBodyPruning": true @@ -4053,7 +3899,7 @@ "language": "json" } }, - "raw": "{\n \"verificationCode\": \"1519\"\n}" + "raw": "{\n \"verificationCode\": \"4687\"\n}" }, "description": {}, "header": [ @@ -4095,7 +3941,7 @@ "value": "application/json" } ], - "id": "b96ca4c3-5ca4-46d4-aceb-03f67f9a1fb2", + "id": "61562898-53a1-4020-b719-a20260bbdaca", "name": "200 response", "originalRequest": { "body": { @@ -4106,7 +3952,7 @@ "language": "json" } }, - "raw": "{\n \"verificationCode\": \"1519\"\n}" + "raw": "{\n \"verificationCode\": \"4687\"\n}" }, "header": [ { @@ -4157,7 +4003,7 @@ "item": [ { "event": [], - "id": "c5fad2d0-070a-4985-8315-7b570ec93d41", + "id": "a746e45a-0c44-4899-abbe-7521954345e2", "name": "/v1/provider-users/me/home-jurisdiction", "protocolProfileBehavior": { "disableBodyPruning": true @@ -4171,7 +4017,7 @@ "language": "json" } }, - "raw": "{\n \"jurisdiction\": \"tx\"\n}" + "raw": "{\n \"jurisdiction\": \"in\"\n}" }, "description": {}, "header": [ @@ -4212,7 +4058,7 @@ "value": "application/json" } ], - "id": "a890bb29-d0ee-44cf-82c2-ea0487bf7234", + "id": "d65672bf-7766-4a37-b426-7ff948be4d38", "name": "200 response", "originalRequest": { "body": { @@ -4223,7 +4069,7 @@ "language": "json" } }, - "raw": "{\n \"jurisdiction\": \"tx\"\n}" + "raw": "{\n \"jurisdiction\": \"in\"\n}" }, "header": [ { @@ -4282,7 +4128,7 @@ "item": [ { "event": [], - "id": "be81c466-cd83-4548-b88b-eb877f706ea0", + "id": "7f40a1a9-5d3e-4aa5-9993-4c9405cab673", "name": "/v1/provider-users/me/jurisdiction/:jurisdiction/licenseType/:licenseType/history", "protocolProfileBehavior": { "disableBodyPruning": true @@ -4340,7 +4186,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"compact\": \"aslp\",\n \"events\": [\n {\n \"createDate\": \"2045-12-31\",\n \"dateOfUpdate\": \"1129-07-16\",\n \"effectiveDate\": \"2387-02-11\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"renewal\",\n \"note\": \"\"\n },\n {\n \"createDate\": \"2088-04-04\",\n \"dateOfUpdate\": \"2290-11-08\",\n \"effectiveDate\": \"2973-10-31\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"licenseDeactivation\",\n \"note\": \"\"\n }\n ],\n \"jurisdiction\": \"wi\",\n \"licenseType\": \"occupational therapy assistant\",\n \"privilegeId\": \"\",\n \"providerId\": \"ac8c9bc7-3eff-45a8-bd01-e4e0e4746cfd\"\n}", + "body": "{\n \"compact\": \"octp\",\n \"events\": [\n {\n \"createDate\": \"2076-04-30\",\n \"dateOfUpdate\": \"2073-12-31\",\n \"effectiveDate\": \"2942-07-31\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"deactivation\",\n \"note\": \"\"\n },\n {\n \"createDate\": \"1430-12-20\",\n \"dateOfUpdate\": \"2556-06-30\",\n \"effectiveDate\": \"2731-07-30\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"registration\",\n \"note\": \"\"\n }\n ],\n \"jurisdiction\": \"or\",\n \"licenseType\": \"occupational therapist\",\n \"privilegeId\": \"\",\n \"providerId\": \"629b1a4f-7c8c-47cf-a9be-aabf6bf4e69e\"\n}", "code": 200, "cookie": [], "header": [ @@ -4349,7 +4195,7 @@ "value": "application/json" } ], - "id": "20b3ab17-30a5-428e-b97c-c066c5e3a064", + "id": "fe1903b1-2204-420b-9a09-4fec8b494042", "name": "200 response", "originalRequest": { "body": {}, @@ -4410,7 +4256,7 @@ "item": [ { "event": [], - "id": "08fbb1eb-4400-42dd-9460-9c4543f538ee", + "id": "36e62486-f4b8-48a8-b460-4cc6623d29de", "name": "/v1/provider-users/me/military-affiliation", "protocolProfileBehavior": { "disableBodyPruning": true @@ -4456,7 +4302,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"affiliationType\": \"militaryMemberSpouse\",\n \"dateOfUpdate\": \"1822-11-31\",\n \"dateOfUpload\": \"1077-04-08\",\n \"documentUploadFields\": [\n {\n \"fields\": {\n \"key_0\": \"\",\n \"key_1\": \"\"\n },\n \"url\": \"\"\n },\n {\n \"fields\": {\n \"key_0\": \"\",\n \"key_1\": \"\",\n \"key_2\": \"\",\n \"key_3\": \"\"\n },\n \"url\": \"\"\n }\n ],\n \"status\": \"\",\n \"fileNames\": [\n \"\",\n \"\"\n ]\n}", + "body": "{\n \"affiliationType\": \"militaryMember\",\n \"dateOfUpdate\": \"2086-12-29\",\n \"dateOfUpload\": \"2560-01-09\",\n \"documentUploadFields\": [\n {\n \"fields\": {\n \"ex4\": \"\",\n \"aliqua73\": \"\"\n },\n \"url\": \"\"\n },\n {\n \"fields\": {\n \"tempor_2\": \"\"\n },\n \"url\": \"\"\n }\n ],\n \"status\": \"\",\n \"fileNames\": [\n \"\",\n \"\"\n ]\n}", "code": 200, "cookie": [], "header": [ @@ -4465,7 +4311,7 @@ "value": "application/json" } ], - "id": "07943649-508c-47f6-9506-418cfd90460d", + "id": "52718662-2da1-4cc6-bc09-fb135f9c207f", "name": "200 response", "originalRequest": { "body": { @@ -4517,7 +4363,7 @@ }, { "event": [], - "id": "40bb4075-7159-416d-928d-2ca3271a890b", + "id": "4cd4a2e8-7354-42bf-a1fc-5244a1e64f54", "name": "/v1/provider-users/me/military-affiliation", "protocolProfileBehavior": { "disableBodyPruning": true @@ -4572,7 +4418,7 @@ "value": "application/json" } ], - "id": "cfe18cab-cf43-444e-b587-fda2561502c2", + "id": "eaa51e6c-c82d-4b31-9cf1-3e1bd59c3695", "name": "200 response", "originalRequest": { "body": { @@ -4633,7 +4479,7 @@ "item": [ { "event": [], - "id": "b9e4c83a-e086-4bf3-bb34-30adae5d0f1a", + "id": "4e8a3d15-581b-42a2-a4f6-3ae1c869973e", "name": "/v1/provider-users/registration", "protocolProfileBehavior": { "disableBodyPruning": true @@ -4650,7 +4496,7 @@ "language": "json" } }, - "raw": "{\n \"compact\": \"\",\n \"dob\": \"1752-02-28\",\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdiction\": \"ar\",\n \"licenseType\": \"speech-language pathologist\",\n \"partialSocial\": \"\",\n \"token\": \"\"\n}" + "raw": "{\n \"compact\": \"\",\n \"dob\": \"1502-06-08\",\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdiction\": \"or\",\n \"licenseType\": \"speech-language pathologist\",\n \"partialSocial\": \"\",\n \"token\": \"\"\n}" }, "description": {}, "header": [ @@ -4690,7 +4536,7 @@ "value": "application/json" } ], - "id": "1696c659-00f2-4575-ad6b-bd08af4d7e95", + "id": "5b0560e7-4616-45d2-8cd7-ade7c1d840e5", "name": "200 response", "originalRequest": { "body": { @@ -4701,7 +4547,7 @@ "language": "json" } }, - "raw": "{\n \"compact\": \"\",\n \"dob\": \"1752-02-28\",\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdiction\": \"ar\",\n \"licenseType\": \"speech-language pathologist\",\n \"partialSocial\": \"\",\n \"token\": \"\"\n}" + "raw": "{\n \"compact\": \"\",\n \"dob\": \"1502-06-08\",\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"jurisdiction\": \"or\",\n \"licenseType\": \"speech-language pathologist\",\n \"partialSocial\": \"\",\n \"token\": \"\"\n}" }, "header": [ { @@ -4739,7 +4585,7 @@ "item": [ { "event": [], - "id": "64398b24-7748-4169-a330-116a0061a61e", + "id": "5094b70a-c826-4cfc-a07d-8c96be7cf9ba", "name": "/v1/provider-users/verifyRecovery", "protocolProfileBehavior": { "disableBodyPruning": true @@ -4756,7 +4602,7 @@ "language": "json" } }, - "raw": "{\n \"compact\": \"coun\",\n \"providerId\": \"d35f5c35-fe50-499d-ba51-d3b993d4bf63\",\n \"recaptchaToken\": \"\",\n \"recoveryToken\": \"\"\n}" + "raw": "{\n \"compact\": \"octp\",\n \"providerId\": \"22fa6d0d-cbb5-4ad7-809c-0e4f2e140a52\",\n \"recaptchaToken\": \"\",\n \"recoveryToken\": \"\"\n}" }, "description": {}, "header": [ @@ -4796,7 +4642,7 @@ "value": "application/json" } ], - "id": "3e3f4ab2-328e-4539-b3af-fd1730e11e86", + "id": "8a5731e0-a67c-4e3f-8728-4f425f7c04bf", "name": "200 response", "originalRequest": { "body": { @@ -4807,7 +4653,7 @@ "language": "json" } }, - "raw": "{\n \"compact\": \"coun\",\n \"providerId\": \"d35f5c35-fe50-499d-ba51-d3b993d4bf63\",\n \"recaptchaToken\": \"\",\n \"recoveryToken\": \"\"\n}" + "raw": "{\n \"compact\": \"octp\",\n \"providerId\": \"22fa6d0d-cbb5-4ad7-809c-0e4f2e140a52\",\n \"recaptchaToken\": \"\",\n \"recoveryToken\": \"\"\n}" }, "header": [ { @@ -4857,7 +4703,7 @@ "item": [ { "event": [], - "id": "2abc3398-bf30-4256-b7ec-b2ec9d9f57b9", + "id": "e24dd7ed-c6ae-4544-a340-5ba18fa139ce", "name": "/v1/public/compacts/:compact/jurisdictions", "protocolProfileBehavior": { "disableBodyPruning": true @@ -4914,7 +4760,7 @@ "value": "application/json" } ], - "id": "57e70b3b-1395-4661-8e0e-795919c3b727", + "id": "1516c3ad-a3b2-47f8-815b-602af9653e76", "name": "200 response", "originalRequest": { "body": {}, @@ -4955,7 +4801,7 @@ "item": [ { "event": [], - "id": "99303856-17ea-4e1e-bed1-79a661417ede", + "id": "f16b5d56-7250-423f-ae3c-1c0a9e474365", "name": "/v1/public/compacts/:compact/providers/query", "protocolProfileBehavior": { "disableBodyPruning": true @@ -4972,7 +4818,7 @@ "language": "json" } }, - "raw": "{\n \"query\": {\n \"providerId\": \"7e651bfc-493a-488f-86bc-5751905747cf\",\n \"jurisdiction\": \"nm\",\n \"givenName\": \"\",\n \"familyName\": \"\"\n },\n \"pagination\": {\n \"lastKey\": \"\",\n \"pageSize\": \"\"\n },\n \"sorting\": {\n \"key\": \"dateOfUpdate\",\n \"direction\": \"descending\"\n }\n}" + "raw": "{\n \"query\": {\n \"providerId\": \"3f3c1b6f-4d02-4048-adef-7a8ec269307b\",\n \"jurisdiction\": \"co\",\n \"givenName\": \"\",\n \"familyName\": \"\"\n },\n \"pagination\": {\n \"lastKey\": \"\",\n \"pageSize\": \"\"\n },\n \"sorting\": {\n \"key\": \"dateOfUpdate\",\n \"direction\": \"descending\"\n }\n}" }, "description": {}, "header": [ @@ -5017,7 +4863,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"pagination\": {\n \"prevLastKey\": {},\n \"lastKey\": {},\n \"pageSize\": \"\"\n },\n \"providers\": [\n {\n \"compact\": \"octp\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"licenseJurisdiction\": \"or\",\n \"privilegeJurisdictions\": [\n \"dc\",\n \"ok\"\n ],\n \"providerId\": \"940de4cb-fb1e-47e3-98c4-3928fbbf9948\",\n \"type\": \"provider\",\n \"npi\": \"0370788298\",\n \"middleName\": \"\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"other\",\n \"dateOfUpdate\": \"1260-04-02\"\n },\n {\n \"compact\": \"octp\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"licenseJurisdiction\": \"ky\",\n \"privilegeJurisdictions\": [\n \"ia\",\n \"ma\"\n ],\n \"providerId\": \"d3f7628c-5fe3-4225-8101-79131587a314\",\n \"type\": \"provider\",\n \"npi\": \"9671937403\",\n \"middleName\": \"\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"id\",\n \"dateOfUpdate\": \"2449-04-30\"\n }\n ],\n \"query\": {\n \"providerId\": \"b497bdf2-8c97-4de7-a23f-eb6f5853175f\",\n \"jurisdiction\": \"ct\",\n \"givenName\": \"\",\n \"familyName\": \"\"\n },\n \"sorting\": {\n \"key\": \"familyName\",\n \"direction\": \"descending\"\n }\n}", + "body": "{\n \"pagination\": {\n \"prevLastKey\": {},\n \"lastKey\": {},\n \"pageSize\": \"\"\n },\n \"providers\": [\n {\n \"compact\": \"coun\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"licenseJurisdiction\": \"pa\",\n \"privilegeJurisdictions\": [\n \"md\",\n \"wa\"\n ],\n \"providerId\": \"014cf23e-586d-4830-96f6-498dd0bc17e4\",\n \"type\": \"provider\",\n \"npi\": \"1686568488\",\n \"middleName\": \"\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"nv\",\n \"dateOfUpdate\": \"1336-11-30\"\n },\n {\n \"compact\": \"octp\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"licenseJurisdiction\": \"md\",\n \"privilegeJurisdictions\": [\n \"mt\",\n \"ny\"\n ],\n \"providerId\": \"154db0c4-a576-4ff9-9918-0f8e34b6766a\",\n \"type\": \"provider\",\n \"npi\": \"9316133384\",\n \"middleName\": \"\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"or\",\n \"dateOfUpdate\": \"1296-10-26\"\n }\n ],\n \"query\": {\n \"providerId\": \"351f5560-8387-4142-b51c-a66f228464fa\",\n \"jurisdiction\": \"hi\",\n \"givenName\": \"\",\n \"familyName\": \"\"\n },\n \"sorting\": {\n \"key\": \"familyName\",\n \"direction\": \"ascending\"\n }\n}", "code": 200, "cookie": [], "header": [ @@ -5026,7 +4872,7 @@ "value": "application/json" } ], - "id": "3e5d6201-2278-43d6-913b-b8047bccfb0c", + "id": "0e2f42bf-3c0b-48b1-8319-cb6e4a8b3a04", "name": "200 response", "originalRequest": { "body": { @@ -5037,7 +4883,7 @@ "language": "json" } }, - "raw": "{\n \"query\": {\n \"providerId\": \"7e651bfc-493a-488f-86bc-5751905747cf\",\n \"jurisdiction\": \"nm\",\n \"givenName\": \"\",\n \"familyName\": \"\"\n },\n \"pagination\": {\n \"lastKey\": \"\",\n \"pageSize\": \"\"\n },\n \"sorting\": {\n \"key\": \"dateOfUpdate\",\n \"direction\": \"descending\"\n }\n}" + "raw": "{\n \"query\": {\n \"providerId\": \"3f3c1b6f-4d02-4048-adef-7a8ec269307b\",\n \"jurisdiction\": \"co\",\n \"givenName\": \"\",\n \"familyName\": \"\"\n },\n \"pagination\": {\n \"lastKey\": \"\",\n \"pageSize\": \"\"\n },\n \"sorting\": {\n \"key\": \"dateOfUpdate\",\n \"direction\": \"descending\"\n }\n}" }, "header": [ { @@ -5078,7 +4924,7 @@ "item": [ { "event": [], - "id": "66fa4cb2-a06b-44b2-be78-6f47b6d107db", + "id": "28896e40-701a-408a-a09f-5c281d5df214", "name": "/v1/public/compacts/:compact/providers/:providerId", "protocolProfileBehavior": { "disableBodyPruning": true @@ -5137,7 +4983,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"1747-05-19\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"licenseJurisdiction\": \"md\",\n \"privilegeJurisdictions\": [\n \"wa\",\n \"ak\"\n ],\n \"providerId\": \"771da59b-b4f6-48e2-b6be-06c8330ba968\",\n \"type\": \"provider\",\n \"privileges\": [\n {\n \"administratorSetStatus\": \"inactive\",\n \"compact\": \"coun\",\n \"dateOfExpiration\": \"1398-12-23\",\n \"dateOfIssuance\": \"1871-01-24\",\n \"dateOfRenewal\": \"2284-10-31\",\n \"dateOfUpdate\": \"2136-03-30\",\n \"jurisdiction\": \"co\",\n \"licenseJurisdiction\": \"ga\",\n \"licenseType\": \"audiologist\",\n \"privilegeId\": \"\",\n \"providerId\": \"ffeb6149-f452-4a21-9b92-12a869a6be09\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"history\": [\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"2387-05-30\",\n \"jurisdiction\": \"wy\",\n \"licenseType\": \"licensed professional counselor\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"1705-04-04\",\n \"dateOfIssuance\": \"2342-03-03\",\n \"dateOfRenewal\": \"1853-01-30\",\n \"dateOfUpdate\": \"1473-11-06\",\n \"licenseJurisdiction\": \"co\",\n \"privilegeId\": \"\"\n },\n \"providerId\": \"e65a8a63-4f8f-4ecc-ab0b-7ffaf5e2838f\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"other\",\n \"updatedValues\": {\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"1465-01-25\",\n \"licenseJurisdiction\": \"ny\",\n \"privilegeId\": \"\",\n \"dateOfRenewal\": \"2578-10-18\",\n \"dateOfIssuance\": \"2187-11-30\",\n \"dateOfUpdate\": \"1013-05-18\"\n }\n },\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"2046-10-02\",\n \"jurisdiction\": \"va\",\n \"licenseType\": \"audiologist\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"2826-10-30\",\n \"dateOfIssuance\": \"1425-11-11\",\n \"dateOfRenewal\": \"1439-10-07\",\n \"dateOfUpdate\": \"2021-06-13\",\n \"licenseJurisdiction\": \"sc\",\n \"privilegeId\": \"\"\n },\n \"providerId\": \"df8f0241-25e7-4146-8484-08f036d6deb1\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"lifting_encumbrance\",\n \"updatedValues\": {\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"1014-03-27\",\n \"licenseJurisdiction\": \"co\",\n \"privilegeId\": \"\",\n \"dateOfRenewal\": \"1350-11-31\",\n \"dateOfIssuance\": \"2925-10-02\",\n \"dateOfUpdate\": \"1980-11-30\"\n }\n }\n ],\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"1527-09-04\",\n \"dateOfUpdate\": \"2192-11-03\",\n \"effectiveStartDate\": \"2382-02-30\",\n \"jurisdiction\": \"fl\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"b7526fbc-6e03-42ca-b2db-9d826d861509\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2037-08-30\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"1569-05-02\",\n \"dateOfUpdate\": \"1727-11-02\",\n \"effectiveStartDate\": \"1030-04-02\",\n \"jurisdiction\": \"nc\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"447c2bec-9971-4923-9e28-5131d8524b1e\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1671-07-30\"\n }\n ]\n },\n {\n \"administratorSetStatus\": \"active\",\n \"compact\": \"octp\",\n \"dateOfExpiration\": \"1603-11-06\",\n \"dateOfIssuance\": \"1632-12-13\",\n \"dateOfRenewal\": \"2095-07-30\",\n \"dateOfUpdate\": \"2370-11-31\",\n \"jurisdiction\": \"vi\",\n \"licenseJurisdiction\": \"ma\",\n \"licenseType\": \"speech-language pathologist\",\n \"privilegeId\": \"\",\n \"providerId\": \"60d06dba-64f6-42f1-ac32-44cea6e7f759\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"history\": [\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"1485-07-31\",\n \"jurisdiction\": \"ri\",\n \"licenseType\": \"licensed professional counselor\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"2169-11-20\",\n \"dateOfIssuance\": \"2988-05-04\",\n \"dateOfRenewal\": \"2576-12-31\",\n \"dateOfUpdate\": \"1571-02-06\",\n \"licenseJurisdiction\": \"md\",\n \"privilegeId\": \"\"\n },\n \"providerId\": \"d74eede7-ea20-4c78-a074-d329a8e64213\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"deactivation\",\n \"updatedValues\": {\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"1824-03-22\",\n \"licenseJurisdiction\": \"nj\",\n \"privilegeId\": \"\",\n \"dateOfRenewal\": \"2112-02-30\",\n \"dateOfIssuance\": \"2745-11-30\",\n \"dateOfUpdate\": \"2211-11-08\"\n }\n },\n {\n \"compact\": \"aslp\",\n \"dateOfUpdate\": \"1843-05-31\",\n \"jurisdiction\": \"ar\",\n \"licenseType\": \"audiologist\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"1584-06-30\",\n \"dateOfIssuance\": \"1316-01-04\",\n \"dateOfRenewal\": \"2509-09-25\",\n \"dateOfUpdate\": \"2570-06-06\",\n \"licenseJurisdiction\": \"ia\",\n \"privilegeId\": \"\"\n },\n \"providerId\": \"4a4a8bfd-3f0b-4439-9c95-ecd166b683d3\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"deactivation\",\n \"updatedValues\": {\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"2132-04-03\",\n \"licenseJurisdiction\": \"ct\",\n \"privilegeId\": \"\",\n \"dateOfRenewal\": \"2260-03-30\",\n \"dateOfIssuance\": \"1698-08-06\",\n \"dateOfUpdate\": \"2919-10-09\"\n }\n }\n ],\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"1951-09-31\",\n \"dateOfUpdate\": \"1879-12-25\",\n \"effectiveStartDate\": \"1776-09-20\",\n \"jurisdiction\": \"wy\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"88301cf5-2fb1-47d6-b34f-3132f496d510\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2801-12-31\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"2409-06-03\",\n \"dateOfUpdate\": \"2968-02-15\",\n \"effectiveStartDate\": \"2813-07-01\",\n \"jurisdiction\": \"de\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"a1a2458f-fcb7-4a30-80f6-5f55d330df2f\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1255-09-20\"\n }\n ]\n }\n ],\n \"npi\": \"6010456029\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"va\",\n \"middleName\": \"\"\n}", + "body": "{\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"1011-08-30\",\n \"familyName\": \"\",\n \"givenName\": \"\",\n \"licenseJurisdiction\": \"pr\",\n \"privilegeJurisdictions\": [\n \"co\",\n \"ia\"\n ],\n \"providerId\": \"f455e628-8579-49a3-ae90-7095f55097a5\",\n \"type\": \"provider\",\n \"privileges\": [\n {\n \"administratorSetStatus\": \"active\",\n \"compact\": \"coun\",\n \"dateOfExpiration\": \"1565-02-09\",\n \"dateOfIssuance\": \"2336-05-01\",\n \"dateOfRenewal\": \"2666-11-31\",\n \"dateOfUpdate\": \"2639-02-19\",\n \"jurisdiction\": \"la\",\n \"licenseJurisdiction\": \"al\",\n \"licenseType\": \"licensed professional counselor\",\n \"privilegeId\": \"\",\n \"providerId\": \"e3e54276-58ab-4e11-9212-135f2098ac51\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"history\": [\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"2396-05-06\",\n \"jurisdiction\": \"ma\",\n \"licenseType\": \"speech-language pathologist\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"1229-10-08\",\n \"dateOfIssuance\": \"2576-11-24\",\n \"dateOfRenewal\": \"2625-10-04\",\n \"dateOfUpdate\": \"1013-10-10\",\n \"licenseJurisdiction\": \"wv\",\n \"privilegeId\": \"\"\n },\n \"providerId\": \"ed6b9805-1800-4118-8330-082c7c1b6a8b\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"emailChange\",\n \"updatedValues\": {\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"1318-05-03\",\n \"licenseJurisdiction\": \"pr\",\n \"privilegeId\": \"\",\n \"dateOfRenewal\": \"2761-02-30\",\n \"dateOfIssuance\": \"2043-12-09\",\n \"dateOfUpdate\": \"1009-06-23\"\n }\n },\n {\n \"compact\": \"coun\",\n \"dateOfUpdate\": \"1608-04-23\",\n \"jurisdiction\": \"de\",\n \"licenseType\": \"audiologist\",\n \"previous\": {\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"2155-11-15\",\n \"dateOfIssuance\": \"1685-12-30\",\n \"dateOfRenewal\": \"2371-06-04\",\n \"dateOfUpdate\": \"1882-02-09\",\n \"licenseJurisdiction\": \"mn\",\n \"privilegeId\": \"\"\n },\n \"providerId\": \"d7af652a-c11f-41d0-b91f-d4a28d9c3014\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"emailChange\",\n \"updatedValues\": {\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"2655-12-09\",\n \"licenseJurisdiction\": \"mn\",\n \"privilegeId\": \"\",\n \"dateOfRenewal\": \"2906-01-05\",\n \"dateOfIssuance\": \"1568-07-06\",\n \"dateOfUpdate\": \"2297-07-31\"\n }\n }\n ],\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"octp\",\n \"creationDate\": \"1320-04-20\",\n \"dateOfUpdate\": \"2521-08-07\",\n \"effectiveStartDate\": \"2890-10-31\",\n \"jurisdiction\": \"ut\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"9715cd73-392a-4fce-a15c-5bf0a56bb2ef\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1701-10-26\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"2026-07-06\",\n \"dateOfUpdate\": \"1536-07-30\",\n \"effectiveStartDate\": \"1831-03-22\",\n \"jurisdiction\": \"ca\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"e2a2a753-3c70-488f-8b44-3416feecb150\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1866-10-04\"\n }\n ]\n },\n {\n \"administratorSetStatus\": \"active\",\n \"compact\": \"aslp\",\n \"dateOfExpiration\": \"1327-05-13\",\n \"dateOfIssuance\": \"1552-05-04\",\n \"dateOfRenewal\": \"1094-04-31\",\n \"dateOfUpdate\": \"2694-10-31\",\n \"jurisdiction\": \"fl\",\n \"licenseJurisdiction\": \"ct\",\n \"licenseType\": \"licensed professional counselor\",\n \"privilegeId\": \"\",\n \"providerId\": \"6e7132e4-a6c9-4c28-978f-efdba89a1262\",\n \"status\": \"inactive\",\n \"type\": \"privilege\",\n \"history\": [\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"1757-10-14\",\n \"jurisdiction\": \"sd\",\n \"licenseType\": \"occupational therapy assistant\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"2915-08-30\",\n \"dateOfIssuance\": \"1938-10-06\",\n \"dateOfRenewal\": \"1570-12-30\",\n \"dateOfUpdate\": \"1805-01-31\",\n \"licenseJurisdiction\": \"in\",\n \"privilegeId\": \"\"\n },\n \"providerId\": \"09a82535-f4ab-48c7-84e4-14c518caea66\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"renewal\",\n \"updatedValues\": {\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"2935-04-04\",\n \"licenseJurisdiction\": \"nd\",\n \"privilegeId\": \"\",\n \"dateOfRenewal\": \"2766-10-30\",\n \"dateOfIssuance\": \"1195-12-08\",\n \"dateOfUpdate\": \"1839-11-02\"\n }\n },\n {\n \"compact\": \"octp\",\n \"dateOfUpdate\": \"2929-07-08\",\n \"jurisdiction\": \"ct\",\n \"licenseType\": \"occupational therapist\",\n \"previous\": {\n \"administratorSetStatus\": \"active\",\n \"dateOfExpiration\": \"2569-07-13\",\n \"dateOfIssuance\": \"1931-10-20\",\n \"dateOfRenewal\": \"2770-07-05\",\n \"dateOfUpdate\": \"1520-08-30\",\n \"licenseJurisdiction\": \"ar\",\n \"privilegeId\": \"\"\n },\n \"providerId\": \"22af5406-8d26-498c-b2c7-7d4f95605a3a\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"expiration\",\n \"updatedValues\": {\n \"administratorSetStatus\": \"inactive\",\n \"dateOfExpiration\": \"2799-10-09\",\n \"licenseJurisdiction\": \"tn\",\n \"privilegeId\": \"\",\n \"dateOfRenewal\": \"1095-02-08\",\n \"dateOfIssuance\": \"1662-12-15\",\n \"dateOfUpdate\": \"1377-11-30\"\n }\n }\n ],\n \"adverseActions\": [\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"coun\",\n \"creationDate\": \"1971-08-07\",\n \"dateOfUpdate\": \"2920-12-23\",\n \"effectiveStartDate\": \"1758-09-15\",\n \"jurisdiction\": \"la\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"05b0846e-bab4-4974-b1f0-9a5236ede55b\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"1609-08-05\"\n },\n {\n \"actionAgainst\": \"\",\n \"adverseActionId\": \"\",\n \"compact\": \"aslp\",\n \"creationDate\": \"1850-04-06\",\n \"dateOfUpdate\": \"2557-06-06\",\n \"effectiveStartDate\": \"2693-05-09\",\n \"jurisdiction\": \"az\",\n \"licenseType\": \"\",\n \"licenseTypeAbbreviation\": \"\",\n \"providerId\": \"8bc074f3-05b2-4d33-b354-93c16d359060\",\n \"type\": \"adverseAction\",\n \"effectiveLiftDate\": \"2710-10-30\"\n }\n ]\n }\n ],\n \"npi\": \"3448942259\",\n \"suffix\": \"\",\n \"currentHomeJurisdiction\": \"unknown\",\n \"middleName\": \"\"\n}", "code": 200, "cookie": [], "header": [ @@ -5146,7 +4992,7 @@ "value": "application/json" } ], - "id": "34254f79-00af-4e6b-b34f-a174441a9846", + "id": "d41d07cc-a8a4-49f0-bfe7-c38282571ba4", "name": "200 response", "originalRequest": { "body": {}, @@ -5194,7 +5040,7 @@ "item": [ { "event": [], - "id": "d0a844bf-5043-4f04-aa24-d9bde85b9c5d", + "id": "fb23515f-7944-41aa-9fde-18c4c1e02b8e", "name": "/v1/public/compacts/:compact/providers/:providerId/jurisdiction/:jurisdiction/licenseType/:licenseType/history", "protocolProfileBehavior": { "disableBodyPruning": true @@ -5278,7 +5124,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"compact\": \"aslp\",\n \"events\": [\n {\n \"createDate\": \"2045-12-31\",\n \"dateOfUpdate\": \"1129-07-16\",\n \"effectiveDate\": \"2387-02-11\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"renewal\",\n \"note\": \"\"\n },\n {\n \"createDate\": \"2088-04-04\",\n \"dateOfUpdate\": \"2290-11-08\",\n \"effectiveDate\": \"2973-10-31\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"licenseDeactivation\",\n \"note\": \"\"\n }\n ],\n \"jurisdiction\": \"wi\",\n \"licenseType\": \"occupational therapy assistant\",\n \"privilegeId\": \"\",\n \"providerId\": \"ac8c9bc7-3eff-45a8-bd01-e4e0e4746cfd\"\n}", + "body": "{\n \"compact\": \"octp\",\n \"events\": [\n {\n \"createDate\": \"2076-04-30\",\n \"dateOfUpdate\": \"2073-12-31\",\n \"effectiveDate\": \"2942-07-31\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"deactivation\",\n \"note\": \"\"\n },\n {\n \"createDate\": \"1430-12-20\",\n \"dateOfUpdate\": \"2556-06-30\",\n \"effectiveDate\": \"2731-07-30\",\n \"type\": \"privilegeUpdate\",\n \"updateType\": \"registration\",\n \"note\": \"\"\n }\n ],\n \"jurisdiction\": \"or\",\n \"licenseType\": \"occupational therapist\",\n \"privilegeId\": \"\",\n \"providerId\": \"629b1a4f-7c8c-47cf-a9be-aabf6bf4e69e\"\n}", "code": 200, "cookie": [], "header": [ @@ -5287,7 +5133,7 @@ "value": "application/json" } ], - "id": "4b891dc1-320c-4385-a389-2e51200c2166", + "id": "732e73a4-f5d3-4ef7-bff3-315de5c5a612", "name": "200 response", "originalRequest": { "body": {}, @@ -5361,7 +5207,7 @@ "item": [ { "event": [], - "id": "dc9383ca-4fa0-47c3-b2cb-1bcfb648f5ba", + "id": "e2274233-989e-4994-9327-60283ec69127", "name": "/v1/purchases/privileges", "protocolProfileBehavior": { "disableBodyPruning": true @@ -5375,7 +5221,7 @@ "language": "json" } }, - "raw": "{\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"276\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"22500886\"\n }\n ],\n \"licenseType\": \"licensed professional counselor\",\n \"orderInformation\": {\n \"opaqueData\": {\n \"dataDescriptor\": \"\",\n \"dataValue\": \"\"\n }\n },\n \"selectedJurisdictions\": [\n \"ri\",\n \"az\"\n ]\n}" + "raw": "{\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"3\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"09\"\n }\n ],\n \"licenseType\": \"licensed professional counselor\",\n \"orderInformation\": {\n \"opaqueData\": {\n \"dataDescriptor\": \"\",\n \"dataValue\": \"\"\n }\n },\n \"selectedJurisdictions\": [\n \"vi\",\n \"wi\"\n ]\n}" }, "description": {}, "header": [ @@ -5415,7 +5261,7 @@ "value": "application/json" } ], - "id": "d185a1f5-bd5c-45c4-b30d-3aa411bc66c8", + "id": "e724c3e3-1c30-4896-a034-5d211b6589b6", "name": "200 response", "originalRequest": { "body": { @@ -5426,7 +5272,7 @@ "language": "json" } }, - "raw": "{\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"276\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"22500886\"\n }\n ],\n \"licenseType\": \"licensed professional counselor\",\n \"orderInformation\": {\n \"opaqueData\": {\n \"dataDescriptor\": \"\",\n \"dataValue\": \"\"\n }\n },\n \"selectedJurisdictions\": [\n \"ri\",\n \"az\"\n ]\n}" + "raw": "{\n \"attestations\": [\n {\n \"attestationId\": \"\",\n \"version\": \"3\"\n },\n {\n \"attestationId\": \"\",\n \"version\": \"09\"\n }\n ],\n \"licenseType\": \"licensed professional counselor\",\n \"orderInformation\": {\n \"opaqueData\": {\n \"dataDescriptor\": \"\",\n \"dataValue\": \"\"\n }\n },\n \"selectedJurisdictions\": [\n \"vi\",\n \"wi\"\n ]\n}" }, "header": [ { @@ -5469,7 +5315,7 @@ "item": [ { "event": [], - "id": "cc062755-4622-439d-939c-ad5a1298cd34", + "id": "d1e08ac0-f9f4-4b94-9245-9e316a8a6d2f", "name": "/v1/purchases/privileges/options", "protocolProfileBehavior": { "disableBodyPruning": true @@ -5511,7 +5357,7 @@ "value": "application/json" } ], - "id": "21b3529a-30c8-4c16-a5e8-32120ff76409", + "id": "45d7dfef-4150-431d-af45-fb2d7b1e95e4", "name": "200 response", "originalRequest": { "body": {}, @@ -5565,7 +5411,7 @@ "item": [ { "event": [], - "id": "8e61081c-0817-45be-8ccc-06020b626fe2", + "id": "c34ac6d9-59c9-4334-a2dc-271d84ee101c", "name": "/v1/staff-users/me", "protocolProfileBehavior": { "disableBodyPruning": true @@ -5597,7 +5443,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"active\",\n \"userId\": \"\"\n}", + "body": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"officia_25\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"exercitation_2d6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"proident8e6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"Duis_912\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"non9\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"fugiat_\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"inactive\",\n \"userId\": \"\"\n}", "code": 200, "cookie": [], "header": [ @@ -5615,7 +5461,7 @@ "value": "" } ], - "id": "cb7d68ce-fa59-49e1-a4e6-5306503a1567", + "id": "ba7b63ba-648e-4c8f-a60e-e232d6eaca77", "name": "200 response", "originalRequest": { "body": {}, @@ -5660,7 +5506,7 @@ "value": "application/json" } ], - "id": "3b37e4ba-38d9-4e24-bad4-78c1d45e0f4d", + "id": "cdc8dc32-b42a-49cb-ad48-5d294fe0d448", "name": "404 response", "originalRequest": { "body": {}, @@ -5698,7 +5544,7 @@ }, { "event": [], - "id": "5ec8f4c1-859f-4fff-b4aa-828decda37a1", + "id": "7a60e7d4-3d8d-4e02-819c-cee4c0347fbe", "name": "/v1/staff-users/me", "protocolProfileBehavior": { "disableBodyPruning": true @@ -5743,7 +5589,7 @@ "response": [ { "_postman_previewlanguage": "json", - "body": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"key_0\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n },\n \"key_1\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"active\",\n \"userId\": \"\"\n}", + "body": "{\n \"attributes\": {\n \"email\": \"\",\n \"familyName\": \"\",\n \"givenName\": \"\"\n },\n \"permissions\": {\n \"officia_25\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"exercitation_2d6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"proident8e6\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"Duis_912\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n },\n \"non9\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"readSSN\": \"\"\n },\n \"jurisdictions\": {\n \"fugiat_\": {\n \"actions\": {\n \"readPrivate\": \"\",\n \"admin\": \"\",\n \"write\": \"\",\n \"readSSN\": \"\"\n }\n }\n }\n }\n },\n \"status\": \"inactive\",\n \"userId\": \"\"\n}", "code": 200, "cookie": [], "header": [ @@ -5761,7 +5607,7 @@ "value": "" } ], - "id": "464ec98c-0260-4da3-b36a-903675059d72", + "id": "fd1209c9-355a-40fe-8532-3b9943897184", "name": "200 response", "originalRequest": { "body": { @@ -5819,7 +5665,7 @@ "value": "application/json" } ], - "id": "16e98316-3b27-46e4-9b33-4a9b9214c20a", + "id": "5def400a-26b7-4d02-a0e7-2359dc3c4fd7", "name": "404 response", "originalRequest": { "body": { From d473e16fec44950fe4f2ac35b7d7f9a430b6b999 Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Tue, 21 Oct 2025 09:56:08 -0500 Subject: [PATCH 25/26] Formatting/linter --- .../function/test_handlers/test_transaction_reporting.py | 4 +--- backend/compact-connect/stacks/api_stack/v1_api/api.py | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/backend/compact-connect/lambdas/python/purchases/tests/function/test_handlers/test_transaction_reporting.py b/backend/compact-connect/lambdas/python/purchases/tests/function/test_handlers/test_transaction_reporting.py index 1ed5b2b9e..a7d8456cc 100644 --- a/backend/compact-connect/lambdas/python/purchases/tests/function/test_handlers/test_transaction_reporting.py +++ b/backend/compact-connect/lambdas/python/purchases/tests/function/test_handlers/test_transaction_reporting.py @@ -901,9 +901,7 @@ def test_generate_monthly_report_includes_expected_settled_transactions_for_full display_end = date.fromisoformat('2024-02-29') # the start time should be the first day of the montn display_start = date.fromisoformat('2024-02-01') - report_window = ReportWindow( - ReportCycle.WEEKLY, display_start_date=display_start, display_end_date=display_end - ) + report_window = ReportWindow(ReportCycle.WEEKLY, display_start_date=display_start, display_end_date=display_end) generate_transaction_reports(generate_mock_event(reporting_cycle=ReportCycle.MONTHLY), self.mock_context) diff --git a/backend/compact-connect/stacks/api_stack/v1_api/api.py b/backend/compact-connect/stacks/api_stack/v1_api/api.py index 93e310962..20849d831 100644 --- a/backend/compact-connect/stacks/api_stack/v1_api/api.py +++ b/backend/compact-connect/stacks/api_stack/v1_api/api.py @@ -3,7 +3,6 @@ from aws_cdk import Stack from aws_cdk.aws_apigateway import AuthorizationType, IResource, MethodOptions -from common_constructs.ssm_parameter_utility import SSMParameterUtility from stacks import persistent_stack as ps from stacks.api_lambda_stack import ApiLambdaStack @@ -37,7 +36,6 @@ def __init__( self.api: LicenseApi = root.api self.api_model = ApiModel(api=self.api) stack: Stack = Stack.of(self.resource) - data_event_bus = SSMParameterUtility.load_data_event_bus_from_ssm_parameter(stack) _active_compacts = persistent_stack.get_list_of_compact_abbreviations() # we only pass the API_BASE_URL env var if the API_DOMAIN_NAME is set From 866e00fdcc845dd5f67fdd6dcd612ca67c79d9ff Mon Sep 17 00:00:00 2001 From: Landon Shumway Date: Tue, 21 Oct 2025 09:56:54 -0500 Subject: [PATCH 26/26] PR feedback --- .../cc_common/data_model/schema/adverse_action/api.py | 6 ++++-- .../stacks/api_lambda_stack/provider_management.py | 10 +++++----- .../tests/app/test_api/test_purchases_api.py | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py index 1784baac0..8ab49a878 100644 --- a/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py +++ b/backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py @@ -1,7 +1,7 @@ # ruff: noqa: N801, N815 invalid-name from marshmallow import ValidationError, validates_schema from marshmallow.fields import Date, List, Raw, String -from marshmallow.validate import OneOf +from marshmallow.validate import Length, OneOf from cc_common.data_model.schema.base_record import ForgivingSchema from cc_common.data_model.schema.common import AdverseActionAgainstEnum @@ -25,7 +25,9 @@ class AdverseActionPostRequestSchema(ForgivingSchema): encumbranceEffectiveDate = Date(required=True, allow_none=False) encumbranceType = EncumbranceTypeField(required=True, allow_none=False) - clinicalPrivilegeActionCategories = List(ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False) + clinicalPrivilegeActionCategories = List( + ClinicalPrivilegeActionCategoryField(), required=False, allow_none=False, validate=Length(min=1) + ) # TODO - remove this field as part of https://github.com/csg-org/CompactConnect/issues/1136 # noqa: FIX002 clinicalPrivilegeActionCategory = ClinicalPrivilegeActionCategoryField(required=False, allow_none=False) diff --git a/backend/compact-connect/stacks/api_lambda_stack/provider_management.py b/backend/compact-connect/stacks/api_lambda_stack/provider_management.py index 343c37f55..54b61ac22 100644 --- a/backend/compact-connect/stacks/api_lambda_stack/provider_management.py +++ b/backend/compact-connect/stacks/api_lambda_stack/provider_management.py @@ -46,15 +46,15 @@ def __init__( # Create all the lambda handlers self.get_provider_handler = self._get_provider_handler(lambda_environment) - api_lambda_stack.log_groups.append(self.get_provider_handler) + api_lambda_stack.log_groups.append(self.get_provider_handler.log_group) self.query_providers_handler = self._query_providers_handler(lambda_environment) - api_lambda_stack.log_groups.append(self.query_providers_handler) + api_lambda_stack.log_groups.append(self.query_providers_handler.log_group) self.get_provider_ssn_handler = self._get_provider_ssn_handler(lambda_environment) - api_lambda_stack.log_groups.append(self.get_provider_ssn_handler) + api_lambda_stack.log_groups.append(self.get_provider_ssn_handler.log_group) self.deactivate_privilege_handler = self._deactivate_privilege_handler(lambda_environment) - api_lambda_stack.log_groups.append(self.deactivate_privilege_handler) + api_lambda_stack.log_groups.append(self.deactivate_privilege_handler.log_group) self.provider_encumbrance_handler = self._add_provider_encumbrance_handler(lambda_environment) - api_lambda_stack.log_groups.append(self.provider_encumbrance_handler) + api_lambda_stack.log_groups.append(self.provider_encumbrance_handler.log_group) def _get_provider_handler( self, diff --git a/backend/compact-connect/tests/app/test_api/test_purchases_api.py b/backend/compact-connect/tests/app/test_api/test_purchases_api.py index c1dc08d1e..c95ec0dd2 100644 --- a/backend/compact-connect/tests/app/test_api/test_purchases_api.py +++ b/backend/compact-connect/tests/app/test_api/test_purchases_api.py @@ -84,7 +84,7 @@ def test_synth_generates_post_purchases_privileges_handler_with_required_secret_ policy = next( policy for policy_logical_id, policy in api_lambda_stack_template.find_resources('AWS::IAM::Policy').items() - if handler_role_logical_id in policy['Properties']['Roles'][0]['Ref'] + if handler_role_logical_id in policy['Properties']['Roles'][0].get('Ref', '') ) # We need to ensure the lambda can read these secrets, else all transactions will fail