Review: CRM tab (admin): business pipeline with search and promotion

review-1826-2026-07-18 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — replaces #14
  • [x] Repo — ldraney/intelligentstaffingsystems
  • [x] User Story — As the admin, I want a searchable pipeline...
  • [x] Context — models after landscaping-assistant today tab
  • [x] File Targets — 7 files listed plus exclusions
  • [x] Feature Flag — none (core admin functionality)
  • [x] Acceptance Criteria — 13 items
  • [x] Test Expectations — 9 items plus run command
  • [x] Constraints — 6 constraints listed
  • [x] Checklist — standard 3-item
  • [x] Related — references project and related issues

Traceability

  • [ ] story:crm label — MISMATCH: project-iss user-stories section lists key "admin" (Epic 6: US-6.1–6.2, "Pipeline list; lead→client promotion with audit") but board item uses story:crm. The user-stories.md doc has "Epic 7: CRM (Admin)" as a distinct epic. [SCOPE] Add "crm" row to project-iss user-stories table, or change board label to story:admin.
  • [ ] arch note MISSING — [SCOPE] search for "arch-rails" returned no results. Create architecture note arch-rails for the Rails component.
  • [x] Forgejo issue — https://forgejo.tail5b443a.ts.net/ldraney/intelligentstaffingsystems/issues/56, state: open

File Targets

  • [ ] app/controllers/admin/crm_controller.rb — ISSUE: Ticket says admin-namespaced path, but existing stub is top-level at app/controllers/crm_controller.rb with require_role :admin. Routes have get "/crm", to: "crm#index" (line 37, top-level), not under namespace :admin. The tab bar pattern keeps tab controllers top-level (catalog, communications, messages all follow this). Fix file path to match existing convention: app/controllers/crm_controller.rb.
  • [ ] app/views/admin/crm/index.html.erb — ISSUE: Same namespace mismatch. Existing view is at app/views/crm/index.html.erb (stub). Should be app/views/crm/.
  • [ ] app/views/admin/crm/_business_card.html.erb — ISSUE: Should be app/views/crm/_business_card.html.erb per above.
  • [ ] app/views/admin/crm/show.html.erb — ISSUE: Should be app/views/crm/show.html.erb per above.
  • [x] app/assets/stylesheets/admin_crm.css — to be created; pattern matches existing admin_catalog.css
  • [x] app/services/keycloak_admin_service.rb — EXISTS. Currently has get_user and update_user. Ticket correctly notes "may already exist from #6". promote_to_client method needs to be added. NOTE: Keycloak role assignment uses realm-role-mapping API (POST /admin/realms/{realm}/users/{id}/role-mappings/realm), not user PUT — service needs a new HTTP method and endpoint.
  • [x] config/routes.rb — EXISTS. Currently has stub route at line 37. Will need show + promote action added.

Repo Placement

OK — issue filed on ldraney/intelligentstaffingsystems, all work targets that repo.

Dependencies

  • #6 (Keycloak OIDC auth) — DONE. Provides KeycloakAdminService foundation.
  • #51 (Projects tab) — DONE. Provides ProjectRequest model for "project requests visible on business detail" AC.
  • Messaging subsystem — DONE. Message model and threads exist for "message thread link" AC.
  • PaperTrail gem — NOT INSTALLED. AC #12 requires "audit trail (PaperTrail)" but PaperTrail gem is not in Gemfile. This is an undocumented dependency that needs to be added.
  • Lead.search scope — does NOT exist. AC #2 requires search; the model has no search scope yet.

Acceptance Criteria

13 acceptance criteria. Most are testable by an agent. Issues:
  • AC #12 (PaperTrail audit trail) — requires gem installation, migration generation, and model setup that isn't scoped in the ticket.
  • AC #9 (Keycloak role update) — requires realm-role-mapping API, not the user-attribute PUT currently in the service. Insufficiently detailed for implementation.
  • AC #5 (last activity aggregation) — complex query across messages, appointments, and project_requests. Appointments model does not appear to exist yet.

Blast Radius

  • The tab bar helper (app/helpers/tab_bar_helper.rb or similar) likely references the CRM path — route changes could break navigation.
  • The existing stub controller and view will need to be replaced in-place (not moved to admin namespace).
  • KeycloakAdminService changes affect profile sync (#13, done) — any method signature changes need to preserve existing behavior.
  • PaperTrail installation affects the entire app (adds a versions table, may need initializer configuration).

Decomposition Assessment

NEEDS DECOMPOSITION — route to skill-decompose-ticket.
  • 13 acceptance criteria (threshold: 5)
  • 7+ file targets
  • Multiple distinct concerns: search/filter UI, business detail view, Keycloak role promotion, PaperTrail audit setup, route restructuring
  • Estimated agent work: 15-20 minutes (well over 5-minute threshold)
  • 8 story points confirms this is oversized for a single pass
Suggested decomposition:
  • CRM index with search and filter (controller, view, Lead.search scope, CSS)
  • CRM business detail view (show action, detail template, related data)
  • Lead promotion (Keycloak role-mapping API, promote action, confirmation UI, PaperTrail)

Recommendation

  • [BODY] Fix file paths: app/controllers/admin/crm_controller.rbapp/controllers/crm_controller.rb; app/views/admin/crm/*app/views/crm/*
  • [BODY] Add PaperTrail gem installation to scope (Gemfile addition + migration + model setup) or remove AC #12 and defer audit trail
  • [BODY] Clarify Keycloak promotion mechanism: realm-role-mapping API, not user attribute PUT
  • [BODY] Note that "Appointments" model may not exist — AC #5 references "last appointment" but no appointment feature is built
  • [LABEL] Change story:crm to story:admin OR add "crm" key to project-iss user-stories table
  • [SCOPE] Create architecture note arch-rails for component rails
  • [SCOPE] Add "crm" entry to project-iss user-stories section if keeping story:crm label
  • [DECOMPOSE] 13 AC across search/detail/promotion concerns, route to skill-decompose-ticket