Add Kiro specs, hooks, and steering files — development tooling archive
This commit is contained in:
116
.kiro/specs/batch-finding-disposition/tasks.md
Normal file
116
.kiro/specs/batch-finding-disposition/tasks.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# Implementation Plan: Batch Finding Disposition
|
||||
|
||||
## Overview
|
||||
|
||||
Add multi-select capability to the Vulnerability Triage findings table with a batch-add-to-queue API endpoint. The backend gets a new `POST /api/ivanti/todo-queue/batch` route in `ivantiTodoQueue.js`. The frontend gets selection state, checkbox dual-mode logic, a SelectionToolbar component, shift-click range select, select-all, and Escape-to-clear — all within `ReportingPage.js`.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] 1. Add `POST /api/ivanti/todo-queue/batch` endpoint
|
||||
- [x] 1.1 Add batch route handler to `backend/routes/ivantiTodoQueue.js`
|
||||
- Add `POST /batch` route inside `createIvantiTodoQueueRouter`, before the `POST /` route
|
||||
- Apply `requireAuth(db)` and `requireGroup('Admin', 'Standard_User')` middleware
|
||||
- Validate request body: `findings` array (1–200 items), each with non-empty `finding_id` string
|
||||
- Validate `workflow_type` is one of `FP`, `Archer`, `CARD`
|
||||
- Validate `vendor`: required non-empty string ≤200 chars for FP/Archer; ignored for CARD
|
||||
- If any validation fails, return 400 with descriptive error message and reject entire batch
|
||||
- _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.8, 3.10_
|
||||
- [x] 1.2 Implement transactional batch insert with SQLite
|
||||
- Use `db.serialize()` with `BEGIN TRANSACTION` / `COMMIT` to insert all findings atomically
|
||||
- For each finding: insert row into `ivanti_todo_queue` with `user_id`, `finding_id`, `finding_title`, `cves_json`, `ip_address`, `vendor`, `workflow_type`
|
||||
- On success: fetch all inserted rows, parse `cves_json` back to arrays, return 201 with `{ items: [...] }`
|
||||
- On any DB error: `ROLLBACK` the transaction and return 500
|
||||
- _Requirements: 3.7, 3.8, 3.9, 3.11_
|
||||
- [x] 1.3 Add audit logging for batch additions
|
||||
- After successful commit, call `logAudit(db, { ... })` with action `'batch_add_to_queue'`, entityType `'ivanti_todo_queue'`, and details including the count and workflow_type
|
||||
- Import `logAudit` from `../helpers/auditLog`
|
||||
- _Requirements: 3.7_
|
||||
|
||||
- [x] 2. Checkpoint — Verify backend endpoint
|
||||
- Ensure the batch endpoint is syntactically correct and the route file has no errors. Ask the user if questions arise.
|
||||
|
||||
- [x] 3. Add multi-select state and checkbox dual-mode logic to `ReportingPage.js`
|
||||
- [x] 3.1 Add selection state variables to `VulnerabilityTriagePage`
|
||||
- Add `selectedIds` (`new Set()`), `lastClickedId` (null), `batchSubmitting` (false), `batchError` (null), `batchWorkflowType` ('FP'), `batchVendor` ('') as new `useState` hooks
|
||||
- _Requirements: 1.1, 2.1_
|
||||
- [x] 3.2 Implement checkbox dual-mode click handler
|
||||
- Replace the existing `<td>` onClick in the checkbox cell with new logic:
|
||||
- If finding is already queued → no-op (existing behavior)
|
||||
- If `selectedIds.size === 0` AND not shift-click → open `AddToQueuePopover` (preserves single-select flow)
|
||||
- If shift-click AND `lastClickedId` exists → range-select all visible non-queued findings between `lastClickedId` and current finding in the `sorted` array
|
||||
- Otherwise → toggle finding.id in `selectedIds`
|
||||
- Always update `lastClickedId` when toggling selection
|
||||
- _Requirements: 1.1, 1.2, 5.1, 5.2, 6.1_
|
||||
- [x] 3.3 Add visual highlighting for selected rows
|
||||
- When a finding's ID is in `selectedIds`, apply a highlighted background (e.g. `rgba(14,165,233,0.12)`) to the row
|
||||
- Override the existing alternating row background and hover for selected rows
|
||||
- _Requirements: 1.3_
|
||||
- [x] 3.4 Disable checkbox for already-queued findings
|
||||
- Keep existing behavior: queued findings show checked + disabled checkbox, preventing re-selection
|
||||
- Ensure queued findings are excluded from shift-click range select and select-all
|
||||
- _Requirements: 1.5_
|
||||
|
||||
- [x] 4. Implement Select All / Deselect All in column header
|
||||
- Modify the checkbox column `<th>` to render a clickable "Select All" checkbox when `selectedIds.size > 0` or when the user interacts with it
|
||||
- Click behavior: if not all visible non-queued findings are selected → select all visible non-queued; if all are selected → deselect all
|
||||
- _Requirements: 1.6, 1.7_
|
||||
|
||||
- [x] 5. Add selection pruning on filter changes
|
||||
- Add a `useEffect` that watches `filtered` (the filtered findings array) and prunes `selectedIds` to only include IDs still present in the filtered set
|
||||
- This ensures selection stays consistent when `columnFilters`, `actionFilter`, or `excFilter` change
|
||||
- _Requirements: 1.4_
|
||||
|
||||
- [x] 6. Implement SelectionToolbar component
|
||||
- [x] 6.1 Create the `SelectionToolbar` inline component in `ReportingPage.js`
|
||||
- Render between the panel header controls and the `<table>` element, only when `selectedIds.size > 0`
|
||||
- Use `position: sticky` with appropriate `top` value to stay visible during scroll
|
||||
- Follow the dark theme design system: monospace fonts, dark gradient background, accent-colored borders
|
||||
- _Requirements: 2.1, 2.8_
|
||||
- [x] 6.2 Add toolbar controls: count badge, Clear Selection, workflow toggles, vendor input, submit button
|
||||
- Display selected count badge (e.g. "12 selected")
|
||||
- "Clear Selection" button that empties `selectedIds` and hides toolbar
|
||||
- Workflow type toggle buttons (FP / Archer / CARD) using existing color scheme: FP = amber (`#F59E0B`), Archer = blue (`#0EA5E9`), CARD = green (`#10B981`)
|
||||
- Vendor text input (hidden when CARD is selected, show "No vendor required" indicator for CARD)
|
||||
- "Add to Queue" submit button — enabled only when workflow_type is CARD, or vendor is non-empty
|
||||
- _Requirements: 2.2, 2.3, 2.4, 2.5, 2.6, 2.7_
|
||||
|
||||
- [x] 7. Implement batch submission flow
|
||||
- [x] 7.1 Add `submitBatch` async function to `VulnerabilityTriagePage`
|
||||
- Build request payload from `selectedIds` (map each ID to its finding object from `sorted`/`filtered` for `finding_id`, `finding_title`, `cves`, `ip_address`), plus `batchWorkflowType` and `batchVendor`
|
||||
- POST to `${API_BASE}/ivanti/todo-queue/batch` with `credentials: 'include'`
|
||||
- Set `batchSubmitting = true` before request, `false` after
|
||||
- _Requirements: 4.1, 4.2_
|
||||
- [x] 7.2 Handle batch success response
|
||||
- On 201: merge returned items into `queueItems` state (sorted by vendor then id, matching existing pattern)
|
||||
- Clear `selectedIds`, reset `batchWorkflowType` to 'FP', reset `batchVendor` to '', clear `batchError`
|
||||
- The newly queued findings will automatically show as checked+disabled via the existing `isQueued()` helper
|
||||
- _Requirements: 4.3, 4.4, 4.6_
|
||||
- [x] 7.3 Handle batch error response
|
||||
- On 4xx/5xx: parse error message from response JSON, set `batchError` to display in toolbar
|
||||
- On network failure: set `batchError` to "Network error — please try again"
|
||||
- Keep selection intact on error so user can retry
|
||||
- _Requirements: 4.5_
|
||||
|
||||
- [x] 8. Add Escape key handler to clear selection
|
||||
- Add a `useEffect` with a `keydown` listener for Escape that clears `selectedIds` when the SelectionToolbar is visible (i.e. `selectedIds.size > 0`)
|
||||
- Ensure it doesn't conflict with the existing Escape handler on `AddToQueuePopover`
|
||||
- _Requirements: 6.3_
|
||||
|
||||
- [x] 9. Ensure keyboard Tab accessibility for SelectionToolbar
|
||||
- Verify all interactive elements in the toolbar (workflow buttons, vendor input, submit button, clear button) are focusable via Tab key
|
||||
- Use native `<button>` and `<input>` elements (which are inherently tabbable) rather than `<div>` with onClick
|
||||
- _Requirements: 6.2_
|
||||
|
||||
- [x] 10. Final checkpoint — Full integration verification
|
||||
- Ensure all files have no syntax errors or diagnostic issues
|
||||
- Verify the checkbox dual-mode logic: no selection → popover, existing selection → toggle
|
||||
- Verify the SelectionToolbar renders/hides correctly based on selection state
|
||||
- Verify batch submit wires through to the backend endpoint and updates queue state
|
||||
- Ensure all tests pass, ask the user if questions arise.
|
||||
|
||||
## Notes
|
||||
|
||||
- No new database migration needed — batch insert reuses the existing `ivanti_todo_queue` schema
|
||||
- The batch endpoint must be registered before `POST /` in the router to avoid Express route conflicts
|
||||
- All testing is done on the dev server after push — no local test tasks included
|
||||
- Each task references specific acceptance criteria from the requirements document for traceability
|
||||
Reference in New Issue
Block a user