Review: CRM tab (admin): business pipeline with search and promotion
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 atapp/controllers/crm_controller.rbwithrequire_role :admin. Routes haveget "/crm", to: "crm#index"(line 37, top-level), not undernamespace :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 atapp/views/crm/index.html.erb(stub). Should beapp/views/crm/. - [ ]
app/views/admin/crm/_business_card.html.erb— ISSUE: Should beapp/views/crm/_business_card.html.erbper above. - [ ]
app/views/admin/crm/show.html.erb— ISSUE: Should beapp/views/crm/show.html.erbper above. - [x]
app/assets/stylesheets/admin_crm.css— to be created; pattern matches existingadmin_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.rb→app/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