# Implementation Plan: Ivanti Queue Redirect ## Overview Implement a redirect action for completed Ivanti queue items. The feature adds a `POST /api/ivanti/todo-queue/:id/redirect` endpoint to the existing route module, fixes the PUT validation message, creates a RedirectModal frontend component, and wires a redirect button into the QueuePanel for completed items. Tasks are ordered: backend bug fix, backend endpoint, frontend modal, frontend integration, with property tests alongside each layer. ## Tasks - [x] 1. Fix PUT endpoint validation message - [x] 1.1 Update PUT `/:id` workflow_type error message in `backend/routes/ivantiTodoQueue.js` - Change `"workflow_type must be FP or Archer."` to `"workflow_type must be FP, Archer, or CARD."` - _Requirements: 5.1_ - [x] 2. Add redirect endpoint to backend - [x] 2.1 Add `POST /:id/redirect` route in `backend/routes/ivantiTodoQueue.js` - Place inside the existing `createIvantiTodoQueueRouter` factory, before the DELETE routes - Auth: `requireAuth(db)`, `requireGroup('Admin', 'Standard_User')` - Validate `workflow_type` against existing `VALID_WORKFLOW_TYPES` constant - For FP/Archer: validate vendor using existing `isValidVendor()` helper; also check length ≤ 200 - For CARD: accept without vendor - Fetch original item with `db.get()` scoped to `req.user.id`; return 404 if not found - Return 400 if original item status is not `"complete"` - INSERT new row copying finding_id, finding_title, cves_json, ip_address, hostname from original; set status `"pending"`, workflow_type and vendor from request body - Fetch the inserted row, parse cves_json, return 201 with the new item - Call `logAudit(db, ...)` fire-and-forget with action `"queue_item_redirected"`, entityType `"ivanti_todo_queue"`, entityId = original item ID, details: `{ original_workflow_type, target_workflow_type, new_item_id, vendor }` - _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 2.1, 2.2_ - [ ]* 2.2 Write property test: redirect preserves finding data - **Property 1: Redirect preserves finding data** - Generate random queue item data (finding_id, finding_title, cves_json, ip_address, hostname with varying lengths and special characters) and random valid workflow_type - Mock the database layer; verify the INSERT parameters preserve all finding fields and set status to "pending" - Use `fast-check` with minimum 100 iterations - **Validates: Requirements 1.1, 1.7** - [ ]* 2.3 Write property test: vendor requirement is conditional on workflow type - **Property 2: Vendor requirement is conditional on workflow type** - Generate random (workflow_type, vendor) pairs where workflow_type is drawn from VALID_WORKFLOW_TYPES and vendor from a mix of valid strings, empty strings, whitespace, strings of length 200, and strings of length 201 - Verify validation accepts/rejects correctly based on the conditional rule - Use `fast-check` with minimum 100 iterations - **Validates: Requirements 1.2, 1.3** - [ ]* 2.4 Write property test: successful redirect produces correct audit entry - **Property 3: Successful redirect produces correct audit entry** - Generate random successful redirect scenarios with varying item data and workflow types - Mock `logAudit`; verify the call contains action `"queue_item_redirected"`, entityType `"ivanti_todo_queue"`, original item ID as entityId, and details with original_workflow_type, target_workflow_type, new_item_id, vendor - Use `fast-check` with minimum 100 iterations - **Validates: Requirements 2.1, 2.2** - [x] 3. Checkpoint — Verify backend changes - Ensure all tests pass, ask the user if questions arise. - [x] 4. Create RedirectModal frontend component - [x] 4.1 Create `frontend/src/components/RedirectModal.js` - Props: `item` (the completed queue item), `onClose` (function), `onRedirect` (function called with new item) - Display read-only context: finding title, finding ID, current workflow type - Workflow type selector (radio buttons or select) with options FP, Archer, CARD - Vendor text input shown only when FP or Archer is selected; required for those types - Submit button calls `POST /api/ivanti/todo-queue/${item.id}/redirect` with `credentials: 'include'` - On success: call `onRedirect(newItem)`, close modal - On error: display error message from API response, keep modal open - Loading state on submit button to prevent double-clicks - Style with inline style objects following DESIGN_SYSTEM.md (dark theme, accent borders, gradient backgrounds) - Use lucide-react icons (e.g., `CornerUpRight` or `ArrowRightLeft`) - _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7_ - [ ]* 4.2 Write unit tests for RedirectModal - Test vendor field visible for FP/Archer, hidden for CARD - Test read-only context displays finding title, finding ID, current workflow type - Test error message displayed when API returns error - Test modal stays open on error - _Requirements: 4.2, 4.3, 4.4, 4.6_ - [x] 5. Integrate redirect button and modal into QueuePanel - [x] 5.1 Add redirect button to completed items in QueuePanel (inside `frontend/src/App.js`) - Add a redirect icon button (lucide-react) on each completed queue item row, next to the existing delete button - Button visible only when `item.status === 'complete'`; hidden for pending items - _Requirements: 3.1, 3.2_ - [x] 5.2 Wire RedirectModal state and rendering in QueuePanel - Add `redirectItem` state (null or the item being redirected) - Clicking the redirect button sets `redirectItem` to that item, opening the modal - On successful redirect (`onRedirect` callback): append the new item to the queue items list, show a success notification, clear `redirectItem` - On close: clear `redirectItem` - Import and render `` conditionally when `redirectItem` is set - _Requirements: 3.3, 4.5, 4.7_ - [ ]* 5.3 Write unit tests for redirect button visibility and modal integration - Test redirect button rendered on completed items - Test redirect button not rendered on pending items - Test clicking redirect button opens modal with correct item - Test successful redirect adds new item to list - _Requirements: 3.1, 3.2, 3.3, 4.5_ - [x] 6. Final checkpoint — Ensure all tests pass - Ensure all tests pass, ask the user if questions arise. ## Notes - Tasks marked with `*` are optional and can be skipped for faster MVP - Each task references specific requirements for traceability - Checkpoints ensure incremental validation - Property tests validate universal correctness properties from the design document - Unit tests validate specific examples and edge cases - The project uses plain JavaScript (no TypeScript), fast-check for PBT, and react-scripts test (Jest) - The QueuePanel component is defined inside `App.js`, not a separate file