6.8 KiB
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
-
1. Fix PUT endpoint validation message
- 1.1 Update PUT
/:idworkflow_type error message inbackend/routes/ivantiTodoQueue.js- Change
"workflow_type must be FP or Archer."to"workflow_type must be FP, Archer, or CARD." - Requirements: 5.1
- Change
- 1.1 Update PUT
-
2. Add redirect endpoint to backend
-
2.1 Add
POST /:id/redirectroute inbackend/routes/ivantiTodoQueue.js- Place inside the existing
createIvantiTodoQueueRouterfactory, before the DELETE routes - Auth:
requireAuth(db),requireGroup('Admin', 'Standard_User') - Validate
workflow_typeagainst existingVALID_WORKFLOW_TYPESconstant - 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 toreq.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
- Place inside the existing
-
* 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-checkwith 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-checkwith 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-checkwith minimum 100 iterations - Validates: Requirements 2.1, 2.2
-
-
3. Checkpoint — Verify backend changes
- Ensure all tests pass, ask the user if questions arise.
-
4. Create RedirectModal frontend component
-
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}/redirectwithcredentials: '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.,
CornerUpRightorArrowRightLeft) - Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7
- Props:
-
* 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
-
-
5. Integrate redirect button and modal into QueuePanel
-
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
-
5.2 Wire RedirectModal state and rendering in QueuePanel
- Add
redirectItemstate (null or the item being redirected) - Clicking the redirect button sets
redirectItemto that item, opening the modal - On successful redirect (
onRedirectcallback): append the new item to the queue items list, show a success notification, clearredirectItem - On close: clear
redirectItem - Import and render
<RedirectModal>conditionally whenredirectItemis set - Requirements: 3.3, 4.5, 4.7
- Add
-
* 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
-
-
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