Skip to content

refactor(handlers): extract createManagedCatalog handler into admin_catalog_operations - #839

Merged
dmeiser merged 4 commits into
mainfrom
fm/KW-ISSUE-773-SHIP-3
Oct 26, 2026
Merged

dmeiser merged 4 commits into
mainfrom
fm/KW-ISSUE-773-SHIP-3

Conversation

@dmeiser

@dmeiser dmeiser commented Oct 26, 2026

Copy link
Copy Markdown
Owner

Slice 3 of the admin_operations split (#773): extract the createManagedCatalog concern into a new src/handlers/admin_catalog_operations.py. Issue #773 stays open — still in admin_operations are adminResetUserPassword, the adminDeleteUser* / adminGetUser* per-entity handlers, adminDeleteShare, adminUpdateCampaignSharedCode, and the dispatcher.

What changed

  • The seven functions (_parse_product_price, _validate_and_process_product, _validate_catalog_input, _build_catalog_item, _persist_catalog, _require_admin_and_get_actor_sub, create_managed_catalog) move byte-identical (the only textual difference is the file-boundary newline — create_managed_catalog is now the module's last function).
  • This is the cleanest of the three extractions: every private helper it uses, including _require_admin_and_get_actor_sub, is used only by the createManagedCatalog handler, so the new module imports nothing from admin_operations.
  • admin_operations keeps the dispatcher as the single registry (it imports create_managed_catalog back at module load) and drops its now-unused import uuid and Decimal/InvalidOperation. The AppSync mapping and the Lambda entry point are unchanged; no IaC change (the payload ships the whole src/ tree).
  • Line counts: src/handlers/admin_operations.py 987 → 839; src/handlers/admin_catalog_operations.py 194 (new).

Tests

  • tests/unit/test_admin_operations.py: repoint the create_managed_catalog import and the two tables patch targets in TestCreateManagedCatalog to src.handlers.admin_catalog_operations; no test logic changed.
  • Full unit suite green (1841 passed, 2 skipped, 100% coverage), ruff check src/ tests/ + ruff format --check src/, mypy src/ (strict), xenon A/B complexity gate, cspell on the changed files, and tofu validate (dev).

@dmeiser dmeiser added the no-release No release/version bump expected from this change label Oct 26, 2026
@dmeiser
dmeiser added this pull request to stack #841 October 26, 2026 06:52
@dmeiser
dmeiser deployed to ephemeral October 26, 2026 20:13 — with GitHub Actions Active
Base automatically changed from fm/KW-ISSUE-773-SHIP-2 to main October 26, 2026 22:58
…atalog_operations

Slice 3 of the #773 admin_operations split: move the managed-catalog
creation concern (the createManagedCatalog handler plus its private
validation/build/persist helpers) from admin_operations into its own module
src/handlers/admin_catalog_operations.py, with zero behavior change.

- The seven functions (_parse_product_price, _validate_and_process_product,
  _validate_catalog_input, _build_catalog_item, _persist_catalog,
  _require_admin_and_get_actor_sub, create_managed_catalog) move verbatim; the
  only textual difference is the file-boundary newline, because
  create_managed_catalog is now the module's last function.
- This is the cleanest of the three extractions: every private helper it uses,
  including _require_admin_and_get_actor_sub, is used only by the
  createManagedCatalog handler, so the whole concern travels to the new module
  with no function-level import from admin_operations at all.
- The dispatcher map in admin_operations stays the single registry: it imports
  create_managed_catalog back at module load (safe — the new module imports
  nothing from this module), and the AppSync handler mapping plus the Lambda
  entry point are unchanged. No IaC change: the Lambda payload ships the whole
  src/ tree.
- admin_operations drops its now-unused `import uuid` and the
  `Decimal`/`InvalidOperation` imports.
- Tests: the create_managed_catalog import in test_admin_operations.py is
  repointed to the new module, and the two `tables` patch targets in
  TestCreateManagedCatalog follow the code to
  src.handlers.admin_catalog_operations; no test logic changed.

Verified: uv run pytest tests/unit -q (1841 passed, 2 skipped, 100% coverage),
ruff check src/ tests/, ruff format --check src/, mypy src/ (strict), xenon
A/B complexity gate, cspell on the changed files, and tofu validate (dev).
… admin_user_deletion

Slice 4 of the #773 admin_operations split: move the per-entity user deletion
concern (the four adminDeleteUser* handlers plus their shared profile-sweep
helper) from admin_operations into its own module
src/handlers/admin_user_deletion.py, with zero behavior change.

- The five functions (_user_profiles_for, admin_delete_user_orders,
  admin_delete_user_campaigns, admin_delete_user_shares,
  admin_delete_user_profiles) move byte-identical; the only textual difference
  is the function-level import of _require_admin_and_get_target_account_id
  from .admin_operations in each handler (same convention as
  admin_account_purge, since a top-level import would be circular).
- admin_operations keeps the dispatcher as the single registry (it imports the
  four handlers back at module load) and drops the four delete_user_* names
  from its .deletion_cascade import. The AppSync mapping and the Lambda entry
  point are unchanged; no IaC change (the payload ships the whole src/ tree).
- Line counts: src/handlers/admin_operations.py 839 -> 775;
  src/handlers/admin_user_deletion.py 123 (new).

Tests:
- tests/unit/test_admin_operations.py: repoint the 21 function-local imports
  of the four handlers from src.handlers.admin_operations to
  src.handlers.admin_user_deletion; no test logic and no patch target changed
  (the suites mock src.handlers.deletion_cascade.tables /
  src.handlers.campaign_operations.tables, which stay put).
- Full unit suite green (1841 passed, 2 skipped, 100% coverage),
  ruff check src/ tests/ + ruff format --check src/, mypy src/ (strict),
  xenon A/B complexity gate, cspell on the changed files, and
  tofu validate (dev).
…tial reset handlers

Slice 5 of the #773 admin_operations split: move the remaining read and
update handlers (the account-scoped adminGetUser* reads, the profile-share
and campaign shared-code mutations, and adminResetUserPassword) from
admin_operations into their own modules, with zero behavior change.

- The 24 functions move byte-identical; the only textual difference is the
  in-function import of the shared helpers (_require_admin_and_get_target_account_id
  / _actor_sub) from .admin_operations in the 8 handlers that need them, the
  same convention admin_account_purge / admin_user_deletion already use (a
  top-level import would be circular).
- Three new modules:
  - admin_user_reads.py: adminGetUser{Profiles,Catalogs,Campaigns,
    SharedCampaigns} plus the campaign-catalog batch helpers.
  - admin_share_campaign_ops.py: adminGetProfileShares, adminDeleteShare,
    adminUpdateCampaignSharedCode plus their helpers.
  - admin_credential_reset.py: adminResetUserPassword plus its helpers.
- admin_operations keeps the dispatcher as the single registry (it imports the
  eight handlers back at module load) and drops the 24 moved functions and the
  now-unused imports. The AppSync mapping and the Lambda entry point are
  unchanged; no IaC change (the Lambda package ships the whole src/ tree).
- Line counts: admin_operations.py 775 -> 271; admin_user_reads.py 287 (new),
  admin_share_campaign_ops.py 247 (new), admin_credential_reset.py 126 (new).

Tests:
- tests/unit/test_admin_operations.py: 34 function-local patch/import targets
  repointed off src.handlers.admin_operations (16 to admin_credential_reset,
  11 to admin_user_reads, 6 to admin_share_campaign_ops, and 1 to
  deletion_cascade.tables where that handler reads its tables, the base's
  admin_operations.tables patch there being a no-op), plus the module-level
  handler/helper imports; no test logic changed.
- tests/unit/test_cognito_filter_call_sites.py: the _find_user_by_email row now
  points at admin_credential_reset.
- Full unit suite green (1841 passed, 2 skipped, 100% coverage),
  ruff check src/ tests/ + ruff format --check, mypy src/ (strict),
  xenon A/B complexity gate. No IaC or frontend change.
The _parse_product_price function was missing the check for non-finite
values (Infinity, NaN) which caused tests to fail with INTERNAL_ERROR
instead of INVALID_INPUT.
@dmeiser
dmeiser merged commit 93e4895 into main Oct 26, 2026
11 of 12 checks passed
@dmeiser
dmeiser deleted the fm/KW-ISSUE-773-SHIP-3 branch October 26, 2026 23:37
@dmeiser
dmeiser deployed to ephemeral October 26, 2026 23:37 — with GitHub Actions Active

This branch was successfully deployed

1 active deployment
ephemeral — 780248f8 Deployed Oct 26, 2026 by dmeiser via Tear down ephemeral environment for PR #331
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-release No release/version bump expected from this change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant