- All 16 route files now import pool from ../db directly
- Removed db parameter from all factory functions
- All callbacks replaced with async/await pool.query()
- All ? placeholders converted to $1, $2... numbered params
- datetime('now') → NOW(), INSERT OR IGNORE → ON CONFLICT DO NOTHING
- LIKE → ILIKE for case-insensitive searches
- Error detection: err.code === '23505' for unique violations
- server.js no longer passes pool/db/requireAuth to route factories
- Only ivantiFindings.js still receives pool (pending task 8 rewrite)
- Add GET /api/ivanti/fp-workflow/documents/search endpoint for querying the document library
- Update POST /api/ivanti/fp-workflow to accept libraryDocIds for attaching library documents on create
- Update POST .../submissions/:id/attachments to accept libraryDocIds on edit
- Add AttachmentSourcePicker component with local upload and library search modes
- Integrate picker into FpWorkflowModal (create) and FpEditModal (edit)
- Track attachment source (local/library) in attachment_results_json for traceability
- Add resolveWorkflowBatchUuid helper that searches Ivanti API for UUID by batch ID and caches it locally
- Use UUID resolver in findings and attachments endpoints instead of relying on stored UUID
- Store UUID on new FP creation by searching Ivanti after workflow batch is created
- Fix frontend attachment upload field name from 'files' to 'attachments' to match Multer config
- Add migration for lifecycle_status, batch UUID, updated_at columns and submission history table
- Add backend endpoints: GET/PUT/POST/PATCH for viewing, editing, adding findings/attachments, and status changes
- Add pure helpers: validateLifecycleTransition, mergeFindings, buildSubmissionHistoryEntry
- Add FpEditModal with tabbed UI (Details, Findings, Attachments, History)
- Make workflow badges clickable for Reworked/Rejected/Expired states with pencil icon
- Add submissions list section to QueuePanel with lifecycle status badges
- Wire state and data flow in ReportingPage for submissions fetch and edit callbacks
The API expects { subject: 'hostFinding', filterRequest: { filters } }
not a flat filter object. Confirmed working via direct curl test —
workflow ID 33418832 created successfully.
Remove extra fields (orWithPrevious, implicitFilters, subject) that
aren't in the Swagger filter schema. Add projection and sort fields
to match the search endpoint format.
The /workflowBatch/falsePositive/request endpoint expects
multipart/form-data with text fields (name, reason, description,
expirationDate, overrideControl, subjectFilterRequest, isEmptyWorkflow)
and inline file uploads — not a JSON body with separate attachment calls.
- Add ivantiFormPost() helper for mixed form fields + files
- Replace buildIvantiPayload with buildIvantiFormFields + buildSubjectFilterRequest
- Remove separate attachment upload loop (files sent inline)
- Update response handling for { id, created } shape
- Fix copy-paste bug in ivantiFpWorkflow.js where both ternary branches
returned 'partial'; simplified to direct assignment
- Remove unused shouldShowFpButton() from ReportingPage.js (canWrite
from useAuth() is used instead)
- Hoist repeated isCreateFpButtonEnabled() calls into a single variable
in QueuePanel render