feat: add Ivanti Queue redirect for completed items
This commit is contained in:
105
.kiro/specs/ivanti-queue-redirect/tasks.md
Normal file
105
.kiro/specs/ivanti-queue-redirect/tasks.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# 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 `<RedirectModal>` 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
|
||||
Reference in New Issue
Block a user