Crew tab: admin oversight of team members and their daily lists #117

Closed
opened 2026-06-06 11:13:47 +00:00 by ldraney · 6 comments
Owner

Type

Feature

Lineage

Child of #107 (Auth + Roles + Audit Trail). Phase 2 — builds on the Crew tab placeholder from PR #136.

Repo

ldraney/landscaping-assistant

User Story

As an admin, I want a Crew tab where I can see team members and their roles, so I can organize my crew and know who's on the team.

Context

PR #136 created the Crew tab skeleton: CrewController with require_role :admin, :super_admin, route at /crew, placeholder view at app/views/crew/index.html.erb, and nav slot 5 (admin+ only). This ticket replaces the placeholder with real content.

Current auth state (PR #136): current_user is a session hash with :username, :email, :roles keys. Use current_user_has_role?("admin") for role checks — there is no ActiveRecord User model.

Current nav layout (5-slot CSS grid):

  • Slot 1: Today (member+)
  • Slot 2: Week (admin+)
  • Slot 3: Person (all)
  • Slot 4: Properties (lead+)
  • Slot 5: Crew (admin, super_admin)

Important limitation: There is no User model in the database. current_user comes from Keycloak session. To show crew members, the Crew tab uses a local CrewMember model that maps Keycloak usernames to display info. V1 does NOT link crew members to work queue items — WorkQueueItem has no crew member association column. Per-member queue filtering is deferred to a future ticket.

File Targets

Files to create:

  • db/migrate/YYYYMMDD_create_crew_members.rb — name, keycloak_username, role, active (boolean)
  • app/models/crew_member.rb — represents a team member
  • app/views/crew/show.html.erb — member profile (name, role, active status, Keycloak username)
  • spec/requests/crew_spec.rb — expand existing specs (60 lines exist from PR #136)
  • spec/models/crew_member_spec.rb
  • lib/tasks/crew.rake — seed/sync crew members (idempotent, like feature_flags:sync)

Files to modify:

  • app/controllers/crew_controller.rb — replace placeholder with real index + show actions
  • app/views/crew/index.html.erb — replace placeholder with member list
  • config/routes.rb — add show action to crew resources
  • app/assets/stylesheets/application.css — crew list styles (per ~/ror-css-guide)
  • spec/requests/role_access_spec.rb — update with crew show route access tests

Acceptance Criteria

  • Crew index shows list of all active crew members with their name and role badge
  • Clicking a crew member navigates to their profile page (name, role, active status, Keycloak username)
  • Admin and super_admin can access Crew tab; all other roles get 404
  • CrewMember model with validations and crew:sync rake task (idempotent, find_or_create_by!)
  • Crew member list shows active/inactive status indicator

Out of Scope

  • Per-member work queue filtering (WorkQueueItem has no crew member column — needs separate migration ticket)
  • Per-member completion counts (depends on work queue association above)
  • Real-time Turbo Stream updates (needs Solid Cable #2)
  • Favorite/unfavorite role management (complex Keycloak API interaction)
  • Week tab per-member breakdown (separate ticket)
  • Keycloak Admin REST API integration (V1 uses local model)

Test Expectations

  • Request specs: crew index (admin access, super_admin access, 404 for lead/member/client)
  • Request specs: crew show (member profile visible to admin, 404 for non-admin)
  • Model specs: CrewMember validations (name presence, keycloak_username uniqueness)
  • Run: bundle exec rspec

Constraints

  • CSS must follow ~/ror-css-guide (design tokens, component comments, no Tailwind, no inline styles)
  • No !important, no #id selectors in CSS
  • current_user is a session hash, NOT ActiveRecord. Use current_user_has_role?() helpers.
  • Feature flag consideration: Crew tab is already gated by role (admin+). No feature flag needed — this is a role-gated enhancement, not a new external integration.

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • #107 / PR #136 — created Crew tab skeleton
  • #137 — Person icon views (sibling phase:2 work)
  • docs/user-stories-auth.md — US-AUTH-11, US-AUTH-12
  • Solid Cable: #2 (prerequisite for real-time updates, out of scope here)
### Type Feature ### Lineage Child of #107 (Auth + Roles + Audit Trail). Phase 2 — builds on the Crew tab placeholder from PR #136. ### Repo `ldraney/landscaping-assistant` ### User Story As an admin, I want a Crew tab where I can see team members and their roles, so I can organize my crew and know who's on the team. ### Context PR #136 created the Crew tab skeleton: `CrewController` with `require_role :admin, :super_admin`, route at `/crew`, placeholder view at `app/views/crew/index.html.erb`, and nav slot 5 (admin+ only). This ticket replaces the placeholder with real content. **Current auth state (PR #136):** `current_user` is a session hash with `:username`, `:email`, `:roles` keys. Use `current_user_has_role?("admin")` for role checks — there is no ActiveRecord User model. **Current nav layout (5-slot CSS grid):** - Slot 1: Today (member+) - Slot 2: Week (admin+) - Slot 3: Person (all) - Slot 4: Properties (lead+) - Slot 5: Crew (admin, super_admin) **Important limitation:** There is no User model in the database. `current_user` comes from Keycloak session. To show crew members, the Crew tab uses a local `CrewMember` model that maps Keycloak usernames to display info. V1 does NOT link crew members to work queue items — `WorkQueueItem` has no crew member association column. Per-member queue filtering is deferred to a future ticket. ### File Targets Files to create: - `db/migrate/YYYYMMDD_create_crew_members.rb` — name, keycloak_username, role, active (boolean) - `app/models/crew_member.rb` — represents a team member - `app/views/crew/show.html.erb` — member profile (name, role, active status, Keycloak username) - `spec/requests/crew_spec.rb` — expand existing specs (60 lines exist from PR #136) - `spec/models/crew_member_spec.rb` - `lib/tasks/crew.rake` — seed/sync crew members (idempotent, like feature_flags:sync) Files to modify: - `app/controllers/crew_controller.rb` — replace placeholder with real index + show actions - `app/views/crew/index.html.erb` — replace placeholder with member list - `config/routes.rb` — add show action to crew resources - `app/assets/stylesheets/application.css` — crew list styles (per ~/ror-css-guide) - `spec/requests/role_access_spec.rb` — update with crew show route access tests ### Acceptance Criteria - [ ] Crew index shows list of all active crew members with their name and role badge - [ ] Clicking a crew member navigates to their profile page (name, role, active status, Keycloak username) - [ ] Admin and super_admin can access Crew tab; all other roles get 404 - [ ] CrewMember model with validations and crew:sync rake task (idempotent, `find_or_create_by!`) - [ ] Crew member list shows active/inactive status indicator ### Out of Scope - Per-member work queue filtering (`WorkQueueItem` has no crew member column — needs separate migration ticket) - Per-member completion counts (depends on work queue association above) - Real-time Turbo Stream updates (needs Solid Cable #2) - Favorite/unfavorite role management (complex Keycloak API interaction) - Week tab per-member breakdown (separate ticket) - Keycloak Admin REST API integration (V1 uses local model) ### Test Expectations - [ ] Request specs: crew index (admin access, super_admin access, 404 for lead/member/client) - [ ] Request specs: crew show (member profile visible to admin, 404 for non-admin) - [ ] Model specs: CrewMember validations (name presence, keycloak_username uniqueness) - Run: `bundle exec rspec` ### Constraints - CSS must follow `~/ror-css-guide` (design tokens, component comments, no Tailwind, no inline styles) - No `!important`, no `#id` selectors in CSS - `current_user` is a session hash, NOT ActiveRecord. Use `current_user_has_role?()` helpers. - Feature flag consideration: Crew tab is already gated by role (admin+). No feature flag needed — this is a role-gated enhancement, not a new external integration. ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes ### Related - #107 / PR #136 — created Crew tab skeleton - #137 — Person icon views (sibling phase:2 work) - `docs/user-stories-auth.md` — US-AUTH-11, US-AUTH-12 - Solid Cable: #2 (prerequisite for real-time updates, out of scope here)
Author
Owner

Issue body rewritten to reflect current codebase state:

  1. CrewController, route, and placeholder view already exist from PR #136 — removed "new" annotations
  2. Updated from old 3-role model to current 5-role model with correct nav layout
  3. Changed "403 for non-admin" to "404" per current auth pattern
  4. Scoped out Week tab enhancements, real-time Turbo Streams (needs #2), and favorite/unfavorite role management
  5. Added CrewMember local model approach (no Keycloak Admin API dependency for V1)
  6. Added current_user session hash context note
  7. Added feature flag consideration (not needed — role-gated, not external integration)
  8. Fixed lineage from "Phase 4" to "Phase 2"
**Issue body rewritten to reflect current codebase state:** 1. CrewController, route, and placeholder view already exist from PR #136 — removed "new" annotations 2. Updated from old 3-role model to current 5-role model with correct nav layout 3. Changed "403 for non-admin" to "404" per current auth pattern 4. Scoped out Week tab enhancements, real-time Turbo Streams (needs #2), and favorite/unfavorite role management 5. Added CrewMember local model approach (no Keycloak Admin API dependency for V1) 6. Added current_user session hash context note 7. Added feature flag consideration (not needed — role-gated, not external integration) 8. Fixed lineage from "Phase 4" to "Phase 2"
Author
Owner

Scope Review: NEEDS_REFINEMENT

Review note: review-1339-2026-06-06

Template is complete and file targets verified, but a critical data model gap blocks two acceptance criteria.

  • [BODY] WorkQueueItem has no user/username/crew_member_id column (property_id, work_date, position, completed only). AC #2 ("show their Today queue") and AC #5 ("completion count X/Y") cannot be implemented without adding a username column migration to work_queue_items. Add db/migrate/YYYYMMDD_add_username_to_work_queue_items.rb to File Targets, OR rewrite AC #2/AC #5 to show all work_queue_items globally (not per-member).
  • [BODY] Add spec/requests/role_access_spec.rb to "Files to modify" -- the new /crew/:id show route needs role access test coverage.
  • [SCOPE] (deferred) Missing story:auth user story entry on project page and arch-rails-app architecture note (known gaps).
## Scope Review: NEEDS_REFINEMENT Review note: `review-1339-2026-06-06` Template is complete and file targets verified, but a critical data model gap blocks two acceptance criteria. - **[BODY]** `WorkQueueItem` has no user/username/crew_member_id column (`property_id`, `work_date`, `position`, `completed` only). AC #2 ("show their Today queue") and AC #5 ("completion count X/Y") cannot be implemented without adding a `username` column migration to `work_queue_items`. Add `db/migrate/YYYYMMDD_add_username_to_work_queue_items.rb` to File Targets, OR rewrite AC #2/AC #5 to show all work_queue_items globally (not per-member). - **[BODY]** Add `spec/requests/role_access_spec.rb` to "Files to modify" -- the new `/crew/:id` show route needs role access test coverage. - **[SCOPE] (deferred)** Missing story:auth user story entry on project page and arch-rails-app architecture note (known gaps).
Author
Owner

Scope refinement (post-review review-1339-2026-06-06):

Addressed the data model gap flagged by the reviewer:

  • WorkQueueItem has no crew member association column (property_id, work_date, position, completed only)
  • Two ACs depended on per-member queue filtering which is impossible without a schema change

Changes made:

  1. AC #2: Changed from "shows their Today queue" → "navigates to their profile page (name, role, active status)"
  2. AC #5: Changed from "completion count (X/Y done today)" → "active/inactive status indicator"
  3. show.html.erb: Changed from "selected member's Today queue" → "member profile"
  4. Added spec/requests/role_access_spec.rb to "Files to modify" (already has crew tests, needs show route updates)
  5. Added explicit "Out of Scope" items for per-member queue filtering and completion counts
  6. Updated Context section to clarify the WorkQueueItem limitation

Per-member work queue association is deferred to a future ticket that adds a crew_member column to work_queue_items.

**Scope refinement (post-review `review-1339-2026-06-06`):** Addressed the data model gap flagged by the reviewer: - `WorkQueueItem` has no crew member association column (`property_id`, `work_date`, `position`, `completed` only) - Two ACs depended on per-member queue filtering which is impossible without a schema change **Changes made:** 1. **AC #2**: Changed from "shows their Today queue" → "navigates to their profile page (name, role, active status)" 2. **AC #5**: Changed from "completion count (X/Y done today)" → "active/inactive status indicator" 3. **show.html.erb**: Changed from "selected member's Today queue" → "member profile" 4. **Added** `spec/requests/role_access_spec.rb` to "Files to modify" (already has crew tests, needs show route updates) 5. **Added** explicit "Out of Scope" items for per-member queue filtering and completion counts 6. **Updated** Context section to clarify the WorkQueueItem limitation Per-member work queue association is deferred to a future ticket that adds a crew_member column to work_queue_items.
Author
Owner

Scope Review: READY (re-review)

Review note: review-1339-2026-06-06-v2
Previous review: review-1339-2026-06-06 (NEEDS_REFINEMENT)

Both [BODY] findings from the first review are resolved:

  • Data model gap — ACs rewritten to remove WorkQueueItem dependency; show page is now member profile instead of per-member queue; Out of Scope explicitly defers per-member filtering
  • Missing role_access_spec.rb — now listed in Files to modify

Remaining deferred [SCOPE] items (not blocking):

  • Create user story entry for "auth" on project-landscaping-assistant
  • Create architecture note arch-rails-app
## Scope Review: READY (re-review) Review note: `review-1339-2026-06-06-v2` Previous review: `review-1339-2026-06-06` (NEEDS_REFINEMENT) Both [BODY] findings from the first review are resolved: - **Data model gap** — ACs rewritten to remove WorkQueueItem dependency; show page is now member profile instead of per-member queue; Out of Scope explicitly defers per-member filtering - **Missing role_access_spec.rb** — now listed in Files to modify Remaining deferred [SCOPE] items (not blocking): - Create user story entry for "auth" on project-landscaping-assistant - Create architecture note arch-rails-app
Author
Owner

Validation: FAIL

Tiers executed: Tier 1 (CI tests) + Tier 3 (production deployment & route checks)
Validation note: validation-117-2026-06-07
7 checks: 0 PASS, 7 FAIL

Blocking failures:

  • Woodpecker pipeline #337 (merge commit 83bfa5d) failed at the test step — build-and-push was skipped, so no production image was built
  • Production pod still runs image 7e25894 (from PR #156, assume_ssl). Crew member code is not deployed
  • 2 test specs expect redirect to /auth/keycloak but the app (since PR #151) redirects to /login:
    • spec/requests/crew_spec.rb:93 — crew show unauthenticated redirect
    • spec/requests/role_access_spec.rb:47 — role access /crew/:id redirect

Required fix: Update the two redirect expectations from /auth/keycloak to /login, then re-trigger pipeline to build and deploy.

## Validation: FAIL Tiers executed: Tier 1 (CI tests) + Tier 3 (production deployment & route checks) Validation note: `validation-117-2026-06-07` 7 checks: 0 PASS, 7 FAIL **Blocking failures:** - Woodpecker pipeline #337 (merge commit `83bfa5d`) failed at the `test` step — `build-and-push` was **skipped**, so no production image was built - Production pod still runs image `7e25894` (from PR #156, assume_ssl). Crew member code is **not deployed** - 2 test specs expect redirect to `/auth/keycloak` but the app (since PR #151) redirects to `/login`: - `spec/requests/crew_spec.rb:93` — crew show unauthenticated redirect - `spec/requests/role_access_spec.rb:47` — role access /crew/:id redirect **Required fix:** Update the two redirect expectations from `/auth/keycloak` to `/login`, then re-trigger pipeline to build and deploy.
Author
Owner

Validation: PASS

Tiers executed: Tier 1 (code inspection) + Tier 3 (production verification)
Validation note: validation-117-2026-06-07

5 checks: 5 PASS, 0 FAIL

All acceptance criteria verified in production:

  • Crew index page loads at /crew with correct template (role badges, status indicators)
  • Show page template renders name, role, status, keycloak_username
  • require_role :admin, :super_admin confirmed in controller; unauthenticated gets 302
  • CrewMember model has all required validations (presence, uniqueness, inclusion)
  • crew:sync rake task exists and uses find_or_create_by! (idempotent)
  • Pod healthy (1/1 Running, 0 restarts), Pipeline #362 green

Note: rake crew:sync has not been run yet — crew list shows empty state. Feature is fully deployed and awaiting initial data seed.

## Validation: PASS Tiers executed: Tier 1 (code inspection) + Tier 3 (production verification) Validation note: `validation-117-2026-06-07` **5 checks: 5 PASS, 0 FAIL** All acceptance criteria verified in production: - Crew index page loads at `/crew` with correct template (role badges, status indicators) - Show page template renders name, role, status, keycloak_username - `require_role :admin, :super_admin` confirmed in controller; unauthenticated gets 302 - CrewMember model has all required validations (presence, uniqueness, inclusion) - `crew:sync` rake task exists and uses `find_or_create_by!` (idempotent) - Pod healthy (1/1 Running, 0 restarts), Pipeline #362 green Note: `rake crew:sync` has not been run yet — crew list shows empty state. Feature is fully deployed and awaiting initial data seed.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/landscaping-assistant#117
No description provided.