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

review-1826-2026-07-25-r2 Review

review ready

Verdict: READY

Re-review of board item #1826. All 4 findings from review-1826-2026-07-25 have been addressed.

Previous Findings Resolution

  • [x] [BODY] Add app/models/lead.rb to File Targets -- FIXED. Now listed with description: "add Lead.search scope for case-insensitive search by name, email, and business_name"
  • [x] [BODY] Add test/controllers/crm_controller_test.rb to File Targets -- FIXED. Now listed with description: "already exists with 7 stub tests; expand with the ~10 tests described in Test Expectations below"
  • [x] [BODY] Note make_request POST support in keycloak_admin_service.rb description -- FIXED. Description now notes: "make_request (around line 127) currently only handles GET and PUT in its case statement; add :post to support the realm-role-mapping endpoint"
  • [x] [SCOPE] Add "crm" story entry to project-iss user-stories section -- FIXED. Row now present: key=crm, backing="docs/ui-ux.md (CRM tab layout) + Epic 6 (US-6.1-6.2)", role=Admin

Template Completeness

  • [x] Type -- Feature
  • [x] Lineage
  • [x] Repo
  • [x] User Story
  • [x] Context
  • [x] Dependencies
  • [x] File Targets (10 entries, all verified)
  • [x] Feature Flag -- none (appropriate for core admin functionality)
  • [x] Acceptance Criteria (13 items)
  • [x] Test Expectations (10 items)
  • [x] Constraints
  • [x] Checklist
  • [x] Related
All 12 required sections present. Template is complete.

Traceability

  • [x] story:crm label -- confirmed in project-iss user-stories table
  • [x] story note verified -- "crm" row present with backing docs and success metric
  • [x] arch:rails label -- arch-rails note exists in pal-e-docs
  • [x] arch note verified -- active note with ISS Rails Architecture content
  • [x] Forgejo issue -- ldraney/intelligentstaffingsystems#56, state: open

File Targets

  • [x] app/controllers/crm_controller.rb -- verified: stub exists with require_role :admin and empty index method (13 lines)
  • [x] app/models/lead.rb -- verified: exists (38 lines), no search scope yet. Ticket correctly identifies need for Lead.search scope
  • [x] app/views/crm/index.html.erb -- verified: placeholder "coming soon" template exists (35 lines)
  • [x] app/views/crm/_business_card.html.erb -- to be created. OK
  • [x] app/views/crm/show.html.erb -- to be created. OK
  • [x] app/assets/stylesheets/crm.css -- to be created. OK (stylesheets dir confirmed)
  • [x] app/services/keycloak_admin_service.rb -- verified: make_request at line 127, supports only :get and :put. Ticket correctly notes need for :post
  • [x] config/routes.rb -- verified: CRM stub route at line 42 (get "/crm" only). Needs expansion for show and promote actions
  • [x] Gemfile -- verified: exists, no paper_trail currently
  • [x] test/controllers/crm_controller_test.rb -- verified: exists with exactly 7 stub tests. Ticket correctly says "7 stub tests"

Repo Placement

OK. All work in ldraney/intelligentstaffingsystems. Keycloak admin calls use existing KeycloakAdminService in same repo. No cross-repo work needed.

Dependencies

  • #54 (Appointment scheduling) -- board item #1824, in validation. Correctly handled as soft dependency: "appointment data is additive, not blocking."
  • #51 (Projects tab) -- done. Project requests model exists (has_many :project_requests on Lead).
  • #6 (Keycloak auth) -- done. KeycloakAdminService exists.
  • #14 (Admin user management) -- superseded by this ticket (documented in Lineage).
  • No undocumented blockers found.

Acceptance Criteria

13 acceptance criteria, all verifiable by an agent. Test commands reference real paths (rails test test/controllers/crm_controller_test.rb). Minor observations (not blocking):
  • Lead.search scope tested via test expectations ("Model test: Lead.search scope") even though no standalone AC for it -- search behavior is covered by AC #2.
  • Constraints section covers graceful Keycloak handling ("Keycloak admin API credentials from SOPS-encrypted env vars").
  • promoted_at column already exists in schema (verified at db/schema.rb line 93). No migration needed for that field.

Blast Radius

  • KeycloakAdminService#make_request -- adding :post to case statement is low risk, isolated change.
  • paper_trail gem -- Docker build impact (bundle install). Agent must update Gemfile.lock.
  • Lead.role enum and promoted_at column already in schema -- no migration needed for promotion model support.
  • No similar promotion patterns exist elsewhere. No downstream consumers affected.

Decomposition Assessment

13 ACs across 10 files in 1 repo. Exceeds the >5 AC threshold. Per user preference (no decomposition), inclusive tickets are preferred. 8-point sizing is appropriate. All work is in a single repo and domain. No decomposition needed.

Recommendation

No action needed. All previous findings resolved. Scope is solid, file targets verified, traceability complete.