# Specification: 038-shift-role-assignment

## Status

| Field | Value |
|-------|-------|
| **Created** | 2026-04-02 |
| **Current Phase** | Plan Reviewed - Ready for Implementation |
| **Last Updated** | 2026-04-02 |

## Documents

| Document | Status | Notes |
|----------|--------|-------|
| product-requirements.md | completed | All sections filled, validated |
| solution-design.md | completed | All sections filled, ADRs pending user confirmation |
| implementation-plan.md | completed | 7 phases, TDD approach, Codex-reviewed with fixes applied |

**Status values**: `pending` | `in_progress` | `completed` | `skipped`

## Decisions Log

| Date | Decision | Rationale |
|------|----------|-----------|
| 2026-04-02 | Start with PRD | Feature has UI, permission, and cross-system implications requiring clear requirements |
| 2026-04-02 | Position assignment optional on shifts | Backward compatibility with existing shifts; soft prompt but not enforced |
| 2026-04-02 | BuyerKiosk provider only | WhenIWork handles positions natively; feature targets native scheduling |
| 2026-04-02 | 15s auto-dismiss on clock-in confirmation | Fixed for simplicity; configurable later if needed |
| 2026-04-02 | ADRs 1-5 approved | User approved all architecture decisions |
| 2026-04-02 | 7-phase implementation plan | TDD approach with parallel opportunities |
| 2026-04-02 | Codex plan review completed | 3 blockers resolved, 6 important items addressed, 5 enhancements noted |
| 2026-04-02 | Auth pattern confirmed | SchedulingController uses checkWriteAuth() helper; new read endpoint needs checkAccess('uri_schedule') |
| 2026-04-02 | No input allowlist blocker | positionId already handled via isset() in createShift/updateShift — no silent drops |
| 2026-04-02 | No recurring shifts | ScheduleCalendar.js has no recurrence support — no position handling needed for recurring |
| 2026-04-02 | Inactive position filtering | PositionRepository::findActive() exists (line 74) — use it for positions API and validation |

## Context

**Feature Request**: Allow assigning a specific schedule position to any particular shift, rather than assuming a user always works in their default role. Two shift leads scheduled simultaneously should be able to have one assigned as "Shift Lead" and the other as "Buyer" for that specific shift.

**Key Requirements**:
1. Assign specific position/role per shift (not just per employee)
2. Permission validation - user must have the position assigned to work it
3. Edit and create shifts with explicit role selection
4. Enhanced clock-in confirmation showing assigned role and daily tasks
5. Workbook integration - "Successfully Clocked In" with shift role display

**Existing Infrastructure**:
- `schedulePositions` table with 7 default positions
- `scheduleShifts` table already has `positionId` column (FK to schedulePositions)
- `employeeSchedulePositions` junction table for multi-position assignment
- `EmployeePositionRepository` with `getPositionsForEmployee()`
- TimePunchController handles clock-in flow with PIN verification
- WhenIWork integration for external scheduling

---
*This file is managed by the specification-management skill.*
