Skip to content

Update cosm adverse action schemas to match business requirements#1326

Open
landonshumway-ia wants to merge 16 commits intocsg-org:mainfrom
InspiringApps:feat/cosm-encumbrance
Open

Update cosm adverse action schemas to match business requirements#1326
landonshumway-ia wants to merge 16 commits intocsg-org:mainfrom
InspiringApps:feat/cosm-encumbrance

Conversation

@landonshumway-ia
Copy link
Copy Markdown
Collaborator

@landonshumway-ia landonshumway-ia commented Mar 31, 2026

Cosmetology will be using slightly different values for the encumbrance types and categories for encumbrances uploaded into the system. This updates those values along with any tests and api schemas that were referencing them.

Closes #1316

Summary by CodeRabbit

  • Refactor
    • Standardized clinical privilege action categories to: fraud, consumer harm, and other.
    • Narrowed encumbrance type options to: suspension, revocation, and surrender of license.
  • Validation
    • Require exactly one clinical privilege action category on adverse-action posts.
  • Tests
    • Updated fixtures, unit tests, snapshots, and smoke tests to align with new categories, encumbrance values, jurisdiction changes, and revised test helpers/workflows.
  • Documentation
    • Added smoke test README describing setup and running instructions.
  • Chores
    • Removed provider-specific encumbrance notification email methods and updated pinned dependency versions.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

Narrowed allowed encumbrance types to three values and standardized clinical privilege action categories to fraud, consumer harm, and other. Updated enums, JSON schemas, API models, request validation, tests/fixtures, smoke tests, removed provider-targeted encumbrance email methods, and added jurisdiction-live validation in encumbrance handlers.

Changes

Cohort / File(s) Summary
Data model enums
backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/common.py
Removed many EncumbranceType members leaving SUSPENSION, REVOCATION, SURRENDER_OF_LICENSE; simplified ClinicalPrivilegeActionCategory values to fraud, consumer harm, other.
API models / schemas
backend/cosmetology-app/stacks/api_stack/v1_api/api_model.py, backend/cosmetology-app/stacks/search_api_stack/v1_api/api_model.py
Centralized clinicalPrivilegeActionCategories schema to an enum ['fraud','consumer harm','other'] and narrowed encumbranceType enum to ['suspension','revocation','surrender of license'].
JSON Schema snapshots
backend/cosmetology-app/tests/resources/snapshots/*, .../GET_PROVIDER_RESPONSE_SCHEMA.json, .../PROVIDER_USER_RESPONSE_SCHEMA.json
Updated snapshot schemas to reflect narrowed encumbranceType enum and added clinicalPrivilegeActionCategories.items.enum ["fraud","consumer harm","other"].
API validation
backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py
Changed AdverseActionPostRequestSchema.clinicalPrivilegeActionCategories validation from Length(min=1) to Length(equal=1) (require exactly one category).
Tests & fixtures
backend/cosmetology-app/lambdas/python/common/common_test/test_constants.py, .../tests/resources/api/adverse-action-post.json, .../tests/unit/.../test_adverse_action.py, .../test_investigation.py
Updated constants, fixtures, and expected test outputs to new category strings and adjusted encumbrance values in test data.
Provider / handler tests
backend/cosmetology-app/lambdas/python/provider-data-v1/tests/function/...
Adjusted test helpers and payloads to use new category values and removed some encumbrance override usages.
Encumbrance handlers
backend/cosmetology-app/lambdas/python/provider-data-v1/handlers/encumbrance.py
Added _ensure_jurisdiction_live(compact, jurisdiction) calling config.compact_configuration_client.is_jurisdiction_live_in_compact(...) and invoked it at handler entry points.
Email client
backend/cosmetology-app/lambdas/python/common/cc_common/email_service_client.py
Removed four provider-targeted encumbrance notification methods (license/privilege encumbrance and lifting variants).
Smoke tests & helpers
backend/cosmetology-app/tests/smoke/smoke_common.py, .../encumbrance_smoke_tests.py, .../investigation_smoke_tests.py, .../config.py, .../smoke_tests_env_example.json, .../license_*_smoke_tests.py, .../compact_configuration_smoke_tests.py, .../rollback_license_upload_smoke_tests.py
Reworked smoke-test auth/provider lookup to use test_provider_id and call_provider_details_endpoint(...), removed /me auth helpers, paginated provider DB queries, moved defaults to AZ, normalized categories/encumbranceType payloads, and refactored multiple test flows and signatures.
Provider stack permissions
backend/cosmetology-app/stacks/api_lambda_stack/provider_management.py
Granted ProviderEncumbranceHandler read access to compact_configuration_table.
Formatting / minor refactors
backend/cosmetology-app/lambdas/python/common/cc_common/provider_record_util.py, backend/cosmetology-app/lambdas/python/search/tests/function/test_search_providers.py
Small formatting/conditional rewraps and test-signature formatting with no functional changes.
Dependency pin bumps
multiple requirements*.txt files
Bumped pinned dev/runtime dependencies (boto3, botocore, requests, werkzeug, tzdata, etc.) across many lambda/service requirements files.

Sequence Diagram(s)

(Skipped — changes do not present a multi-component sequential flow requiring diagramming under the rules.)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • jlkravitz

Poem

🐰 I nibbled enums down to three, so neat and spry,
One category per case, concise and shy.
I hopped through schemas, tests, and a tiny permission plea,
Snipped obsolete mailers, then thumped a leaf—whee!
From the burrow: tidy code and a carrot emoji—🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 4

❌ Failed checks (3 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is too brief and omits required sections from the template. Missing: detailed requirements list, comprehensive description of all changes, and a complete testing checklist with specific verification steps. Expand the description to include the full template sections: itemize specific requirements from issue #1316, detail all schema changes across files, and confirm all testing steps were performed (unit tests, build, API spec updates, CDK tests if applicable).
Out of Scope Changes check ⚠️ Warning Multiple out-of-scope changes detected: email notification methods removed, provider authentication refactored (removed Cognito user credentials), smoke test jurisdiction changed from 'ne' to 'az', provider data access rearchitected, and several smoke test features removed/rewritten without corresponding issue requirements. Isolate schema/enum updates into a focused PR addressing only issue #1316. Move unrelated refactoring (email service, auth changes, smoke test redesign, jurisdiction changes) to separate PRs with corresponding issue tracking.
Docstring Coverage ⚠️ Warning Docstring coverage is 73.97% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive Issue #1316 contains only placeholder tasks without specific implementation requirements, making it difficult to validate whether code changes fully address the stated objectives beyond schema updates. Review issue #1316 for clarification on whether the schema/enum updates constitute the complete encumbrance backend implementation or if additional work remains in scope.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: updating adverse action schemas for cosmetology to match business requirements regarding encumbrance types and categories.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
backend/cosmetology-app/stacks/search_api_stack/v1_api/api_model.py (1)

359-362: Remove enum constraint from response schema.

Response schemas should remain unconstrained for flexibility. The enum validation belongs in the runtime layer (ClinicalPrivilegeActionCategoryField), not in CDK schema definitions.

Proposed change
                'clinicalPrivilegeActionCategories': JsonSchema(
                    type=JsonSchemaType.ARRAY,
-                   items=JsonSchema(
-                       type=JsonSchemaType.STRING,
-                       enum=['Fraud', 'Consumer Harm', 'Other'],
-                   ),
+                   items=JsonSchema(type=JsonSchemaType.STRING),
                ),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/cosmetology-app/stacks/search_api_stack/v1_api/api_model.py` around
lines 359 - 362, The response schema currently constrains values by including an
enum on the JsonSchema used for items (JsonSchema(type=JsonSchemaType.STRING,
enum=[...])). Remove the enum parameter from that JsonSchema so the response
schema only declares type=JsonSchemaType.STRING (or leaves items as an
unconstrained JsonSchema) and let the runtime validator
(ClinicalPrivilegeActionCategoryField) enforce the allowed values; update the
JsonSchema instantiation that contains items=JsonSchema(...) accordingly.
backend/cosmetology-app/stacks/api_stack/v1_api/api_model.py (1)

643-643: Split request and response category schemas.

_clinical_privilege_action_categories_schema is reused by both _encumbrance_request_schema and the adverseActions response objects, so the new enum now constrains response models too. Keep the enum on the request side only, and leave response items as plain strings to avoid doc drift when response payloads evolve.

♻️ Suggested split
-    def _clinical_privilege_action_categories_schema(self) -> JsonSchema:
+    def _clinical_privilege_action_categories_response_schema(self) -> JsonSchema:
         return JsonSchema(
             type=JsonSchemaType.ARRAY,
             description='The categories of clinical privilege action',
-            items=JsonSchema(
-                type=JsonSchemaType.STRING,
-                enum=['Fraud', 'Consumer Harm', 'Other'],
-            ),
+            items=JsonSchema(type=JsonSchemaType.STRING),
         )
+
+    `@property`
+    def _clinical_privilege_action_categories_request_schema(self) -> JsonSchema:
+        return JsonSchema(
+            type=JsonSchemaType.ARRAY,
+            description='The categories of clinical privilege action',
+            items=JsonSchema(type=JsonSchemaType.STRING, enum=['Fraud', 'Consumer Harm', 'Other']),
+        )
# request-only usage
'clinicalPrivilegeActionCategories': self._clinical_privilege_action_categories_request_schema

# response-only usage
'clinicalPrivilegeActionCategories': self._clinical_privilege_action_categories_response_schema

Based on learnings: request schemas should include enum validation constraints while response schemas should remain unconstrained.

Also applies to: 771-771, 810-819, 828-836

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/cosmetology-app/stacks/api_stack/v1_api/api_model.py` at line 643,
The shared enum schema _clinical_privilege_action_categories_schema is being
used for both request and response models; create two separate
schemas—_clinical_privilege_action_categories_request_schema (with the
enum/validation) and _clinical_privilege_action_categories_response_schema
(plain string/no enum)—then update usages: replace references inside
_encumbrance_request_schema (and any other request schemas) to use the request
variant and replace response object fields such as adverseActions to use the
response variant; ensure all occurrences (including the other spots referenced
around the diff) are switched so request-side validation keeps enums while
responses remain unconstrained.
backend/cosmetology-app/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py (1)

45-51: Add one regression case for a retired category value.

These helpers now only exercise the new happy-path payload. A single negative case with an old value like Unsafe Practice or Substandard Care would lock in the enum contraction introduced by this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@backend/cosmetology-app/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py`
around lines 45 - 51, The current helper _generate_test_body only builds a
happy-path payload using ClinicalPrivilegeActionCategory.FRAUD; add a regression
test that submits a payload with the retired category string "Unsafe Practice or
Substandard Care" to ensure the service rejects it (e.g., assert a validation
error / 4xx response). Implement this by either extending _generate_test_body to
accept a category override or creating a new test helper that copies
TEST_ENCUMBRANCE_EFFECTIVE_DATE and replaces clinicalPrivilegeActionCategories
with the literal "Unsafe Practice or Substandard Care", then call the existing
handler/test harness and assert the expected failure behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@backend/cosmetology-app/tests/resources/snapshots/LICENSE_ENCUMBRANCE_REQUEST_SCHEMA.json`:
- Around line 11-21: The snapshot schema for clinicalPrivilegeActionCategories
is missing the non-empty constraint; update the source schema in
backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py
to add minItems: 1 for the clinicalPrivilegeActionCategories array (the same
field that currently uses Length(min=1) at runtime), then regenerate the JSON
snapshot so the snapshot includes "minItems": 1 and matches the runtime
validator.

In `@backend/cosmetology-app/tests/smoke/encumbrance_smoke_tests.py`:
- Around line 384-399: The current match predicate only compares
clinicalPrivilegeActionCategories and can match older records; update the
matching logic in the loop that builds matching_actions to also compare the
adverse_action's encumbranceEffectiveDate.effectiveStartDate against the
request_payload's encumbranceEffectiveDate.effectiveStartDate (or equivalent
key), i.e. compute request_effective =
request_payload.get('encumbranceEffectiveDate', {}).get('effectiveStartDate')
and adverse_effective = adverse_action.get('encumbranceEffectiveDate',
{}).get('effectiveStartDate') and require action_categories ==
expected_categories AND adverse_effective == request_effective when appending to
matching_actions so the test only passes for the newly created adverse action.

---

Nitpick comments:
In
`@backend/cosmetology-app/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py`:
- Around line 45-51: The current helper _generate_test_body only builds a
happy-path payload using ClinicalPrivilegeActionCategory.FRAUD; add a regression
test that submits a payload with the retired category string "Unsafe Practice or
Substandard Care" to ensure the service rejects it (e.g., assert a validation
error / 4xx response). Implement this by either extending _generate_test_body to
accept a category override or creating a new test helper that copies
TEST_ENCUMBRANCE_EFFECTIVE_DATE and replaces clinicalPrivilegeActionCategories
with the literal "Unsafe Practice or Substandard Care", then call the existing
handler/test harness and assert the expected failure behavior.

In `@backend/cosmetology-app/stacks/api_stack/v1_api/api_model.py`:
- Line 643: The shared enum schema _clinical_privilege_action_categories_schema
is being used for both request and response models; create two separate
schemas—_clinical_privilege_action_categories_request_schema (with the
enum/validation) and _clinical_privilege_action_categories_response_schema
(plain string/no enum)—then update usages: replace references inside
_encumbrance_request_schema (and any other request schemas) to use the request
variant and replace response object fields such as adverseActions to use the
response variant; ensure all occurrences (including the other spots referenced
around the diff) are switched so request-side validation keeps enums while
responses remain unconstrained.

In `@backend/cosmetology-app/stacks/search_api_stack/v1_api/api_model.py`:
- Around line 359-362: The response schema currently constrains values by
including an enum on the JsonSchema used for items
(JsonSchema(type=JsonSchemaType.STRING, enum=[...])). Remove the enum parameter
from that JsonSchema so the response schema only declares
type=JsonSchemaType.STRING (or leaves items as an unconstrained JsonSchema) and
let the runtime validator (ClinicalPrivilegeActionCategoryField) enforce the
allowed values; update the JsonSchema instantiation that contains
items=JsonSchema(...) accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c8627d0-b48c-4200-9755-6c1d1dc9f20e

📥 Commits

Reviewing files that changed from the base of the PR and between 674ca38 and 152119a.

📒 Files selected for processing (25)
  • backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/adverse_action/__init__.py
  • backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py
  • backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/adverse_action/record.py
  • backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/common.py
  • backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/fields.py
  • backend/cosmetology-app/lambdas/python/common/common_test/test_constants.py
  • backend/cosmetology-app/lambdas/python/common/common_test/test_data_generator.py
  • backend/cosmetology-app/lambdas/python/common/tests/resources/api/adverse-action-post.json
  • backend/cosmetology-app/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py
  • backend/cosmetology-app/lambdas/python/common/tests/unit/test_data_model/test_schema/test_investigation.py
  • backend/cosmetology-app/lambdas/python/provider-data-v1/handlers/encumbrance.py
  • backend/cosmetology-app/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py
  • backend/cosmetology-app/lambdas/python/provider-data-v1/tests/function/test_handlers/test_investigation.py
  • backend/cosmetology-app/lambdas/python/search/handlers/manage_opensearch_indices.py
  • backend/cosmetology-app/lambdas/python/search/tests/function/test_manage_opensearch_indices.py
  • backend/cosmetology-app/stacks/api_stack/v1_api/api_model.py
  • backend/cosmetology-app/stacks/search_api_stack/v1_api/api_model.py
  • backend/cosmetology-app/tests/resources/snapshots/GET_PROVIDER_RESPONSE_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/LICENSE_ENCUMBRANCE_REQUEST_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/PATCH_LICENSE_INVESTIGATION_REQUEST_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/PATCH_PRIVILEGE_INVESTIGATION_REQUEST_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/PRIVILEGE_ENCUMBRANCE_REQUEST_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/PROVIDER_USER_RESPONSE_SCHEMA.json
  • backend/cosmetology-app/tests/smoke/encumbrance_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/investigation_smoke_tests.py
💤 Files with no reviewable changes (4)
  • backend/cosmetology-app/lambdas/python/search/handlers/manage_opensearch_indices.py
  • backend/cosmetology-app/lambdas/python/common/common_test/test_data_generator.py
  • backend/cosmetology-app/lambdas/python/search/tests/function/test_manage_opensearch_indices.py
  • backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/fields.py

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/cosmetology-app/tests/smoke/encumbrance_smoke_tests.py`:
- Around line 588-592: The test sets
privilege_encumbrance_body['encumbranceType'] to an invalid enum value
'reprimand'; update the test to use one of the allowed EncumbranceType values
(e.g., 'suspension', 'revocation', or 'surrender of license') so the payload
validates against the EncumbranceType enum in common.py; locate and edit the
privilege_encumbrance_body definition in the encumbrance_smoke_tests.py test and
replace 'reprimand' with a permitted value (choose the one that fits the test
scenario).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a50e6180-a5d1-40b1-8862-c523fa646bf6

📥 Commits

Reviewing files that changed from the base of the PR and between e8b539a and 1240fbd.

📒 Files selected for processing (17)
  • backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/common.py
  • backend/cosmetology-app/lambdas/python/common/common_test/test_constants.py
  • backend/cosmetology-app/lambdas/python/common/tests/resources/api/adverse-action-post.json
  • backend/cosmetology-app/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py
  • backend/cosmetology-app/lambdas/python/common/tests/unit/test_data_model/test_schema/test_investigation.py
  • backend/cosmetology-app/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py
  • backend/cosmetology-app/lambdas/python/provider-data-v1/tests/function/test_handlers/test_investigation.py
  • backend/cosmetology-app/stacks/api_stack/v1_api/api_model.py
  • backend/cosmetology-app/stacks/search_api_stack/v1_api/api_model.py
  • backend/cosmetology-app/tests/resources/snapshots/GET_PROVIDER_RESPONSE_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/LICENSE_ENCUMBRANCE_REQUEST_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/PATCH_LICENSE_INVESTIGATION_REQUEST_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/PATCH_PRIVILEGE_INVESTIGATION_REQUEST_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/PRIVILEGE_ENCUMBRANCE_REQUEST_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/PROVIDER_USER_RESPONSE_SCHEMA.json
  • backend/cosmetology-app/tests/smoke/encumbrance_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/investigation_smoke_tests.py
✅ Files skipped from review due to trivial changes (3)
  • backend/cosmetology-app/lambdas/python/common/tests/resources/api/adverse-action-post.json
  • backend/cosmetology-app/tests/smoke/investigation_smoke_tests.py
  • backend/cosmetology-app/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py
🚧 Files skipped from review as they are similar to previous changes (10)
  • backend/cosmetology-app/lambdas/python/common/tests/unit/test_data_model/test_schema/test_adverse_action.py
  • backend/cosmetology-app/lambdas/python/common/tests/unit/test_data_model/test_schema/test_investigation.py
  • backend/cosmetology-app/lambdas/python/provider-data-v1/tests/function/test_handlers/test_investigation.py
  • backend/cosmetology-app/tests/resources/snapshots/GET_PROVIDER_RESPONSE_SCHEMA.json
  • backend/cosmetology-app/lambdas/python/common/common_test/test_constants.py
  • backend/cosmetology-app/tests/resources/snapshots/PATCH_PRIVILEGE_INVESTIGATION_REQUEST_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/LICENSE_ENCUMBRANCE_REQUEST_SCHEMA.json
  • backend/cosmetology-app/tests/resources/snapshots/PRIVILEGE_ENCUMBRANCE_REQUEST_SCHEMA.json
  • backend/cosmetology-app/stacks/api_stack/v1_api/api_model.py
  • backend/cosmetology-app/tests/resources/snapshots/PROVIDER_USER_RESPONSE_SCHEMA.json

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/cosmetology-app/tests/smoke/smoke_common.py (1)

236-241: Consider simplifying the pk construction logic.

The explicit if compact is not None and provider_id is not None check is redundant since the else branch with or operators handles all cases correctly—when both are provided, the or expressions simply return the provided values.

♻️ Simplified implementation
 def get_all_provider_database_records(compact: str | None = None, provider_id: str | None = None):
-    if compact is not None and provider_id is not None:
-        pk = f'{compact}#PROVIDER#{provider_id}'
-    else:
-        resolved_compact = compact or 'cosm'
-        resolved_provider_id = provider_id or config.test_provider_id
-        pk = f'{resolved_compact}#PROVIDER#{resolved_provider_id}'
+    resolved_compact = compact or 'cosm'
+    resolved_provider_id = provider_id or config.test_provider_id
+    pk = f'{resolved_compact}#PROVIDER#{resolved_provider_id}'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/cosmetology-app/tests/smoke/smoke_common.py` around lines 236 - 241,
The pk construction is over-complicated: remove the if/else and always compute
resolved_compact = compact or 'cosm' and resolved_provider_id = provider_id or
config.test_provider_id, then set pk =
f'{resolved_compact}#PROVIDER#{resolved_provider_id}'; update the code that
currently references the explicit if (using variables compact, provider_id,
config.test_provider_id, and pk) to use this single simplified assignment.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@backend/cosmetology-app/lambdas/python/provider-data-v1/handlers/encumbrance.py`:
- Around line 39-41: The membership check in _ensure_jurisdiction_live uses raw
compact and jurisdiction values and can fail for mixed/upper-case inputs;
normalize both inputs (compact and jurisdiction) to lowercase before calling
config.compact_configuration_client.is_jurisdiction_live_in_compact and then
raise CCInvalidRequestException('Jurisdiction is not live in this compact') only
if the normalized check returns False so casing differences won't erroneously
reject valid jurisdictions.

---

Nitpick comments:
In `@backend/cosmetology-app/tests/smoke/smoke_common.py`:
- Around line 236-241: The pk construction is over-complicated: remove the
if/else and always compute resolved_compact = compact or 'cosm' and
resolved_provider_id = provider_id or config.test_provider_id, then set pk =
f'{resolved_compact}#PROVIDER#{resolved_provider_id}'; update the code that
currently references the explicit if (using variables compact, provider_id,
config.test_provider_id, and pk) to use this single simplified assignment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b2a83644-61f5-477b-b221-4c92e5d98837

📥 Commits

Reviewing files that changed from the base of the PR and between 6b2faa3 and 709879a.

📒 Files selected for processing (6)
  • backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py
  • backend/cosmetology-app/lambdas/python/provider-data-v1/handlers/encumbrance.py
  • backend/cosmetology-app/tests/smoke/config.py
  • backend/cosmetology-app/tests/smoke/encumbrance_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/smoke_common.py
  • backend/cosmetology-app/tests/smoke/smoke_tests_env_example.json
✅ Files skipped from review due to trivial changes (1)
  • backend/cosmetology-app/tests/smoke/smoke_tests_env_example.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/cosmetology-app/tests/smoke/encumbrance_smoke_tests.py

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py (1)

69-71: Minor data inconsistency: City and state mismatch.

homeAddressCity is set to 'Omaha' (a city in Nebraska) while homeAddressState is now 'AZ' (Arizona). This inconsistency may be harmless for smoke tests since these are likely not validated together, but it could cause confusion when debugging test failures.

Consider updating the city to an Arizona city (e.g., 'Phoenix' or 'Tucson') for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py`
around lines 69 - 71, Update the test data in
rollback_license_upload_smoke_tests.py so the address fields are consistent:
change the 'homeAddressCity' value to an Arizona city (e.g., 'Phoenix' or
'Tucson') to match 'homeAddressState': 'AZ'; locate the object containing
'homeAddressState' and 'homeAddressCity' and replace the city string
accordingly.
backend/cosmetology-app/tests/smoke/smoke_common.py (1)

235-250: Default argument evaluated at module load time.

The default provider_id: str = config.test_provider_id is evaluated when the module is imported. If config.test_provider_id (which reads CC_TEST_PROVIDER_ID from environment) isn't set at import time, this will raise a KeyError.

Currently this works because load_smoke_test_env() is called at module level in config.py (line 105), but it creates a subtle coupling. Consider using None as the default and resolving inside the function:

♻️ Safer default argument pattern
-def get_all_provider_database_records(compact: str = 'cosm', provider_id: str = config.test_provider_id):
+def get_all_provider_database_records(compact: str = 'cosm', provider_id: str | None = None):
 
+    if provider_id is None:
+        provider_id = config.test_provider_id
     items: list = []
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/cosmetology-app/tests/smoke/smoke_common.py` around lines 235 - 250,
The function get_all_provider_database_records uses a default argument
provider_id: str = config.test_provider_id which is evaluated at import time;
change the signature to accept provider_id: Optional[str] = None and inside the
function resolve provider_id = provider_id or config.test_provider_id before
using it (so the env lookup happens at call time), keeping the rest of the logic
(pagination, Key('pk').eq(f'{compact}#PROVIDER#{provider_id}'), and
config.provider_user_dynamodb_table.query) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py`:
- Around line 69-71: Update the test data in
rollback_license_upload_smoke_tests.py so the address fields are consistent:
change the 'homeAddressCity' value to an Arizona city (e.g., 'Phoenix' or
'Tucson') to match 'homeAddressState': 'AZ'; locate the object containing
'homeAddressState' and 'homeAddressCity' and replace the city string
accordingly.

In `@backend/cosmetology-app/tests/smoke/smoke_common.py`:
- Around line 235-250: The function get_all_provider_database_records uses a
default argument provider_id: str = config.test_provider_id which is evaluated
at import time; change the signature to accept provider_id: Optional[str] = None
and inside the function resolve provider_id = provider_id or
config.test_provider_id before using it (so the env lookup happens at call
time), keeping the rest of the logic (pagination,
Key('pk').eq(f'{compact}#PROVIDER#{provider_id}'), and
config.provider_user_dynamodb_table.query) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 496ede09-9028-42c7-8857-26310b93a855

📥 Commits

Reviewing files that changed from the base of the PR and between 6b2faa3 and f12dafe.

📒 Files selected for processing (13)
  • backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py
  • backend/cosmetology-app/lambdas/python/common/cc_common/email_service_client.py
  • backend/cosmetology-app/lambdas/python/provider-data-v1/handlers/encumbrance.py
  • backend/cosmetology-app/stacks/api_lambda_stack/provider_management.py
  • backend/cosmetology-app/tests/smoke/compact_configuration_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/config.py
  • backend/cosmetology-app/tests/smoke/encumbrance_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/investigation_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/license_upload_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/smoke_common.py
  • backend/cosmetology-app/tests/smoke/smoke_tests_env_example.json
  • backend/cosmetology-app/tests/smoke/ssn_read_throttling_smoke_tests.py
💤 Files with no reviewable changes (1)
  • backend/cosmetology-app/lambdas/python/common/cc_common/email_service_client.py
✅ Files skipped from review due to trivial changes (3)
  • backend/cosmetology-app/tests/smoke/ssn_read_throttling_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/smoke_tests_env_example.json
  • backend/cosmetology-app/tests/smoke/encumbrance_smoke_tests.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/cosmetology-app/lambdas/python/common/cc_common/data_model/schema/adverse_action/api.py
  • backend/cosmetology-app/lambdas/python/provider-data-v1/handlers/encumbrance.py

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py (1)

79-84: Scope the upload key to the run too.

familyName only isolates the later provider query. The uploaded fixture still reuses the same business identifiers every run, so any leaked rollback data in the shared sandbox can be picked up again on Step 1 and turn this from a create/delete rollback case into an update/revert case. Please verify which incoming field the license ingest dedupes on and make that field run-scoped alongside familyName.

Also applies to: 620-621

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py`
around lines 79 - 84, The uploaded fixture is not fully run-scoped: in addition
to familyName (family_name) you must identify which incoming field the license
ingest uses for deduplication (e.g., SSN or business identifier) and append the
per-run unique token to that field as well so each test run creates distinct
upload keys; update the test data where the fixture dict is constructed (the
keys familyName and the deduped field such as ssn) to include the run-scoped
suffix (use the existing family_name/run id), and apply the same change to the
other occurrence of the fixture construction referenced in the comment.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py`:
- Around line 746-749: The current call to verify_rollback_results(results,
expected_reverted, expected_skipped) is insufficient because
verify_rollback_results only logs a warning on mismatched reverted counts;
instead assert the reverted count directly so the test fails on mismatch:
compute the actual reverted count from the results object (e.g.,
results.get('num_reverted') or len(results.get('reverted_providers'))), and add
an explicit assertion like assert actual_reverted == expected_reverted (and keep
or assert skipped with expected_skipped) using the same symbols
NUM_LICENSES_TO_UPLOAD, expected_reverted, expected_skipped and results to
guarantee the test fails on partial rollback.
- Around line 646-651: The call to wait_for_all_providers_created(...) discards
the provider IDs it finds, so capture and store them immediately (e.g., assign
its return to the same variable used by the cleanup path such as
ALL_PROVIDER_IDS or a dedicated first_step_provider_ids) so the except cleanup
can delete Step 1 providers if later steps fail; update the call site where
wait_for_all_providers_created is invoked (with staff_headers,
len(uploaded_licenses), family_name=run_family_name) to assign its return value
and ensure the except block references that variable when performing cleanup.

---

Nitpick comments:
In `@backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py`:
- Around line 79-84: The uploaded fixture is not fully run-scoped: in addition
to familyName (family_name) you must identify which incoming field the license
ingest uses for deduplication (e.g., SSN or business identifier) and append the
per-run unique token to that field as well so each test run creates distinct
upload keys; update the test data where the fixture dict is constructed (the
keys familyName and the deduped field such as ssn) to include the run-scoped
suffix (use the existing family_name/run id), and apply the same change to the
other occurrence of the fixture construction referenced in the comment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee634404-4668-4a65-81eb-4fb245377955

📥 Commits

Reviewing files that changed from the base of the PR and between 996076f and 8a67b6e.

📒 Files selected for processing (17)
  • backend/cosmetology-app/lambdas/python/cognito-backup/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/cognito-backup/requirements.txt
  • backend/cosmetology-app/lambdas/python/common/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/common/requirements.txt
  • backend/cosmetology-app/lambdas/python/compact-configuration/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/custom-resources/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/data-events/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/disaster-recovery/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/provider-data-v1/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/search/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/search/requirements.txt
  • backend/cosmetology-app/lambdas/python/staff-user-pre-token/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/staff-users/requirements-dev.txt
  • backend/cosmetology-app/requirements-dev.txt
  • backend/cosmetology-app/requirements.txt
  • backend/cosmetology-app/tests/smoke/query_provider_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py
💤 Files with no reviewable changes (1)
  • backend/cosmetology-app/tests/smoke/query_provider_smoke_tests.py
✅ Files skipped from review due to trivial changes (15)
  • backend/cosmetology-app/lambdas/python/cognito-backup/requirements.txt
  • backend/cosmetology-app/lambdas/python/search/requirements.txt
  • backend/cosmetology-app/lambdas/python/common/requirements.txt
  • backend/cosmetology-app/lambdas/python/provider-data-v1/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/search/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/custom-resources/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/data-events/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/disaster-recovery/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/cognito-backup/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/compact-configuration/requirements-dev.txt
  • backend/cosmetology-app/requirements.txt
  • backend/cosmetology-app/lambdas/python/staff-users/requirements-dev.txt
  • backend/cosmetology-app/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/common/requirements-dev.txt
  • backend/cosmetology-app/lambdas/python/staff-user-pre-token/requirements-dev.txt

Comment on lines +646 to +651
wait_for_all_providers_created(
staff_headers,
len(uploaded_licenses),
max_wait_time=FIRST_UPLOAD_PROVIDER_INGEST_MAX_WAIT_SEC,
family_name=run_family_name,
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Capture the Step 1 provider IDs for failure cleanup.

This first wait_for_all_providers_created() already finds the providers created by Step 1, but the result is discarded. If Step 2 or Step 3 fails before Line 686 assigns ALL_PROVIDER_IDS, the except block cannot clean up the first upload and leaves test data behind.

💡 Proposed fix
-        wait_for_all_providers_created(
+        initial_provider_ids = wait_for_all_providers_created(
             staff_headers,
             len(uploaded_licenses),
             max_wait_time=FIRST_UPLOAD_PROVIDER_INGEST_MAX_WAIT_SEC,
             family_name=run_family_name,
         )
+        ALL_PROVIDER_IDS = initial_provider_ids.copy()
...
-        ALL_PROVIDER_IDS = provider_ids.copy()
+        ALL_PROVIDER_IDS = list(set(ALL_PROVIDER_IDS) | set(provider_ids))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py`
around lines 646 - 651, The call to wait_for_all_providers_created(...) discards
the provider IDs it finds, so capture and store them immediately (e.g., assign
its return to the same variable used by the cleanup path such as
ALL_PROVIDER_IDS or a dedicated first_step_provider_ids) so the except cleanup
can delete Step 1 providers if later steps fail; update the call site where
wait_for_all_providers_created is invoked (with staff_headers,
len(uploaded_licenses), family_name=run_family_name) to assign its return value
and ensure the except block references that variable when performing cleanup.

Comment on lines +746 to 749
# Expect all providers reverted except for the 1 skipped
expected_reverted = NUM_LICENSES_TO_UPLOAD - 1
expected_skipped = 1
verify_rollback_results(results, expected_reverted, expected_skipped)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Make the reverted-provider count fail the test.

The call here looks strict, but verify_rollback_results() only warns when num_reverted != expected_provider_count (Lines 515-517). That means this new expected_reverted = NUM_LICENSES_TO_UPLOAD - 1 check still lets a partial rollback pass as long as skipped/failed counts happen to match.

💡 Proposed fix
-    if num_reverted != expected_provider_count:
-        logger.warning(f'Expected {expected_provider_count} reverted providers but found {num_reverted}')
+    if num_reverted != expected_provider_count:
+        raise SmokeTestFailureException(
+            f'Expected {expected_provider_count} reverted providers but found {num_reverted}'
+        )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/cosmetology-app/tests/smoke/rollback_license_upload_smoke_tests.py`
around lines 746 - 749, The current call to verify_rollback_results(results,
expected_reverted, expected_skipped) is insufficient because
verify_rollback_results only logs a warning on mismatched reverted counts;
instead assert the reverted count directly so the test fails on mismatch:
compute the actual reverted count from the results object (e.g.,
results.get('num_reverted') or len(results.get('reverted_providers'))), and add
an explicit assertion like assert actual_reverted == expected_reverted (and keep
or assert skipped with expected_skipped) using the same symbols
NUM_LICENSES_TO_UPLOAD, expected_reverted, expected_skipped and results to
guarantee the test fails on partial rollback.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/cosmetology-app/tests/smoke/license_upload_smoke_tests.py`:
- Around line 206-218: The resource creation for the smoke test is happening
before the try block, so failures in create_test_staff_user or
create_test_app_client bypass the failure logging and finally cleanup; move
create_test_staff_user and create_test_app_client (and any dependent variables
like client_id/client_secret) inside the existing try that already contains
get_client_auth_headers and upload_licenses_record, or expand the try to start
above those calls so that exceptions from
create_test_staff_user/create_test_app_client are caught and the finally cleanup
runs; ensure references to create_test_staff_user, create_test_app_client,
get_client_auth_headers, and upload_licenses_record are updated accordingly.
- Around line 181-188: The cleanup query is too broad and can delete other
tests' events; narrow it to the current test run by adding a run-specific filter
(e.g., upload_id or test_run_id) when querying data_events_table in
license_ingest_record_response and the similar block at 195-201: include the run
identifier in the KeyConditionExpression or add a FilterExpression with
ExpressionAttributeValues like ':run_id' and match the run-specific field (e.g.,
run_id, upload_id, request_id) present on the license.ingest items, and only
delete rows when the run identifier matches to avoid removing unrelated events;
also ensure _cleanup_test_generated_records() uses the same run-scoped query
before deleting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2b824c26-b71f-4060-90e2-aad48d572c0d

📥 Commits

Reviewing files that changed from the base of the PR and between 8a67b6e and a5e2fa7.

📒 Files selected for processing (4)
  • backend/cosmetology-app/tests/smoke/README.md
  • backend/cosmetology-app/tests/smoke/config.py
  • backend/cosmetology-app/tests/smoke/license_upload_smoke_tests.py
  • backend/cosmetology-app/tests/smoke/query_provider_smoke_tests.py
💤 Files with no reviewable changes (1)
  • backend/cosmetology-app/tests/smoke/query_provider_smoke_tests.py
✅ Files skipped from review due to trivial changes (1)
  • backend/cosmetology-app/tests/smoke/README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/cosmetology-app/tests/smoke/config.py

Comment on lines 181 to +188
license_ingest_record_response = data_events_table.query(
KeyConditionExpression='pk = :pk AND sk BETWEEN :start_time AND :end_time',
ExpressionAttributeValues={
':pk': 'COMPACT#cosm#JURISDICTION#ne',
':pk': f'COMPACT#{COMPACT}#JURISDICTION#{JURISDICTION}',
':start_time': f'TYPE#license.ingest#TIME#{int(start_time.timestamp())}',
':end_time': f'TYPE#license.ingest#TIME#{int(event_time.timestamp())}',
},
ConsistentRead=True,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Scope the data-events cleanup to this test run.

This query still returns every license.ingest event for the COMPACT#cosm#JURISDICTION#az partition in the 15-minute window, and _cleanup_test_generated_records() deletes every returned item. In a shared sandbox, one run can erase unrelated ingest events from other uploads/tests. Please narrow the match to a run-specific identifier before cleanup, or avoid deleting data-events rows when the match is ambiguous.

Also applies to: 195-201

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/cosmetology-app/tests/smoke/license_upload_smoke_tests.py` around
lines 181 - 188, The cleanup query is too broad and can delete other tests'
events; narrow it to the current test run by adding a run-specific filter (e.g.,
upload_id or test_run_id) when querying data_events_table in
license_ingest_record_response and the similar block at 195-201: include the run
identifier in the KeyConditionExpression or add a FilterExpression with
ExpressionAttributeValues like ':run_id' and match the run-specific field (e.g.,
run_id, upload_id, request_id) present on the license.ingest items, and only
delete rows when the run identifier matches to avoid removing unrelated events;
also ensure _cleanup_test_generated_records() uses the same run-scoped query
before deleting.

Comment on lines +206 to +218
# Create staff user with permission to query providers (internal API)
test_user_sub = create_test_staff_user(
email=TEST_STAFF_USER_EMAIL,
compact=COMPACT,
jurisdiction=JURISDICTION,
permissions={'actions': {'admin'}, 'jurisdictions': {JURISDICTION: {'write', 'admin'}}},
)
client_credentials = create_test_app_client(TEST_APP_CLIENT_NAME, COMPACT, JURISDICTION)
client_id = client_credentials['client_id']
client_secret = client_credentials['client_secret']
try:
upload_licenses_record()
license_upload_headers = get_client_auth_headers(client_id, client_secret, COMPACT, JURISDICTION)
upload_licenses_record(license_upload_headers)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Move resource creation inside the try.

create_test_staff_user() and create_test_app_client() can fail before control enters the try, which skips both the smoke-test failure logging and the finally cleanup. That leaves any earlier setup resources behind on the failure path.

🧹 Proposed fix
 if __name__ == '__main__':
     load_smoke_test_env()
-    # Create staff user with permission to query providers (internal API)
-    test_user_sub = create_test_staff_user(
-        email=TEST_STAFF_USER_EMAIL,
-        compact=COMPACT,
-        jurisdiction=JURISDICTION,
-        permissions={'actions': {'admin'}, 'jurisdictions': {JURISDICTION: {'write', 'admin'}}},
-    )
-    client_credentials = create_test_app_client(TEST_APP_CLIENT_NAME, COMPACT, JURISDICTION)
-    client_id = client_credentials['client_id']
-    client_secret = client_credentials['client_secret']
+    test_user_sub = None
+    client_id = None
     try:
+        # Create staff user with permission to query providers (internal API)
+        test_user_sub = create_test_staff_user(
+            email=TEST_STAFF_USER_EMAIL,
+            compact=COMPACT,
+            jurisdiction=JURISDICTION,
+            permissions={'actions': {'admin'}, 'jurisdictions': {JURISDICTION: {'write', 'admin'}}},
+        )
+        client_credentials = create_test_app_client(TEST_APP_CLIENT_NAME, COMPACT, JURISDICTION)
+        client_id = client_credentials['client_id']
+        client_secret = client_credentials['client_secret']
         license_upload_headers = get_client_auth_headers(client_id, client_secret, COMPACT, JURISDICTION)
         upload_licenses_record(license_upload_headers)
         logger.info('License record upload smoke test passed')
     except SmokeTestFailureException as e:
         logger.error(f'License record upload smoke test failed: {str(e)}')
     finally:
-        delete_test_app_client(client_id)
-        # Clean up the test staff user
-        delete_test_staff_user(TEST_STAFF_USER_EMAIL, user_sub=test_user_sub, compact=COMPACT)
+        if client_id:
+            delete_test_app_client(client_id)
+        if test_user_sub:
+            delete_test_staff_user(TEST_STAFF_USER_EMAIL, user_sub=test_user_sub, compact=COMPACT)

Also applies to: 223-225

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/cosmetology-app/tests/smoke/license_upload_smoke_tests.py` around
lines 206 - 218, The resource creation for the smoke test is happening before
the try block, so failures in create_test_staff_user or create_test_app_client
bypass the failure logging and finally cleanup; move create_test_staff_user and
create_test_app_client (and any dependent variables like
client_id/client_secret) inside the existing try that already contains
get_client_auth_headers and upload_licenses_record, or expand the try to start
above those calls so that exceptions from
create_test_staff_user/create_test_app_client are caught and the finally cleanup
runs; ensure references to create_test_staff_user, create_test_app_client,
get_client_auth_headers, and upload_licenses_record are updated accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add encumbrance BE

1 participant