Sync .kiro/ from master — v2.2.0 release batch
New specs: archer-template-library, ccp-metrics-view-restructure, compliance-list-stale-after-sidebar-edit, compliance-metric-estimated-resolution-date, compliance-remediation-display-fix, flexible-jira-ticket-creation, forecast-burndown-chart, granite-loader-export, ivanti-queue-clear-completed-fix, multi-item-jira-ticket, queue-collapsible-sections, vendor-issue-type-dropdown New steering: archer-template-gen.md Updated: migration-registration-check hook, remediation-plan-history spec, gitlab-workflow, tech, versioning steering files
This commit is contained in:
@@ -1,51 +1,85 @@
|
||||
# Tasks — Remediation Plan History
|
||||
# Implementation Plan: Remediation Plan History — Per-Metric Extension
|
||||
|
||||
## Task 1: Create migration for compliance_item_history table [Requirement 2, 7]
|
||||
- [x] Create `backend/migrations/add_compliance_item_history.js` with the schema from the design doc
|
||||
- [~] Table: `compliance_item_history` (id, hostname, field_name, old_value, new_value, change_reason, changed_by, changed_at)
|
||||
- [~] Add CHECK constraint on field_name: IN ('resolution_date', 'remediation_plan')
|
||||
- [~] Add index on (hostname, field_name)
|
||||
- [~] Add index on (changed_at)
|
||||
- [~] Register in `migrations/run-all.js`
|
||||
- [~] Run migration and verify table exists
|
||||
## Overview
|
||||
|
||||
## Task 2: Modify PATCH /items/:hostname/metadata to record history [Requirement 1, 6]
|
||||
- [~] In `backend/routes/compliance.js`, locate the PATCH metadata handler
|
||||
- [~] Accept new optional `change_reason` field (max 500 chars, validated)
|
||||
- [~] Before updating compliance_items, SELECT current resolution_date and remediation_plan for the hostname
|
||||
- [~] For each field where old !== new, INSERT into compliance_item_history (hostname, field_name, old_value, new_value, change_reason, changed_by)
|
||||
- [~] Skip history insert if old === new (no-op changes)
|
||||
- [~] Wrap history insert + item update in a transaction
|
||||
- [~] Handle NULL → value and value → NULL transitions
|
||||
- [~] Add audit log entry with old/new values
|
||||
- [~] Verify existing response shape is preserved
|
||||
Extends the existing remediation plan history system to support per-metric scoping of resolution_date and remediation_plan. The original hostname-level implementation (Tasks 1–6) is already complete. Tasks 7–12 add metric_id targeting to the PATCH endpoint, a metric selector UI in the detail panel, per-metric history tracking, and verification that reporting queries work correctly with per-metric resolution dates. This addresses GitLab issue #19.
|
||||
|
||||
## Task 3: Extend GET /items/:hostname to return history [Requirement 4]
|
||||
- [~] In the existing `/items/:hostname` handler, add a query: `SELECT id, field_name, old_value, new_value, change_reason, changed_by, changed_at FROM compliance_item_history WHERE hostname = $1 ORDER BY changed_at DESC LIMIT 10`
|
||||
- [~] Add `history` array to the response object
|
||||
- [~] If query fails, return empty array (graceful degradation) and log error
|
||||
- [~] Verify response includes history alongside existing metrics and notes
|
||||
## Tasks
|
||||
|
||||
## Task 4: Modify bulk update commit to track history [Requirement 6]
|
||||
- [~] In the bulk update flow (POST /vcl/bulk-commit), before updating each hostname's resolution_date or remediation_plan, query current values
|
||||
- [~] For each changed field, INSERT into compliance_item_history with changed_by = req.user.username
|
||||
- [~] Skip if value is unchanged
|
||||
- [~] No change_reason for bulk updates (set to NULL)
|
||||
- [x] 1. Create migration for compliance_item_history table
|
||||
- [x] 1.1 Create `backend/migrations/add_compliance_item_history.js` with schema, CHECK constraint, indexes, register in run-all.js, and verify table exists
|
||||
- _Requirements: 2, 7_
|
||||
|
||||
## Task 5: Add change_reason input and history section to ComplianceDetailPanel [Requirement 5]
|
||||
- [~] Add `changeReason` state and a single-line text input between the Save button and Notes section
|
||||
- [~] Pass `change_reason` in the PATCH request body when saving
|
||||
- [~] Clear changeReason after successful save
|
||||
- [~] Add "Change History" section below the remediation plan area
|
||||
- [~] Fetch history from the GET /items/:hostname response
|
||||
- [~] Display entries: field icon, old → new, username, date, reason (if present)
|
||||
- [~] Resolution dates formatted as YYYY-MM-DD, NULL shown as "—"
|
||||
- [~] Remediation plan values truncated to 60 chars with title tooltip
|
||||
- [~] Show "No changes recorded" when history is empty
|
||||
- [~] Run `npm run build` after changes
|
||||
- [x] 2. Modify PATCH /items/:hostname/metadata to record history
|
||||
- [x] 2.1 Accept change_reason, SELECT current values, INSERT history for changed fields, wrap in transaction, handle NULL transitions, add audit log
|
||||
- _Requirements: 1, 6_
|
||||
|
||||
## Task 6: Verify VCL burndown is unaffected [Requirement 3]
|
||||
- [~] Confirm burndown query in vclMultiVertical.js reads from compliance_items.resolution_date only
|
||||
- [~] Confirm donut query uses MAX(resolution_date) grouped by hostname
|
||||
- [~] Set a resolution date, change it multiple times, verify device appears once in burndown
|
||||
- [~] No code changes expected — verification only
|
||||
- [x] 3. Extend GET /items/:hostname to return history
|
||||
- [x] 3.1 Add history query, include history array in response, graceful degradation on failure
|
||||
- _Requirements: 4_
|
||||
|
||||
- [x] 4. Modify bulk update commit to track history
|
||||
- [x] 4.1 Query current values before update, INSERT history for changed fields, skip unchanged, NULL change_reason
|
||||
- _Requirements: 6_
|
||||
|
||||
- [x] 5. Add change_reason input and history section to ComplianceDetailPanel
|
||||
- [x] 5.1 Add changeReason state and input, pass in PATCH body, display Change History section with formatted entries, run npm run build
|
||||
- _Requirements: 5_
|
||||
|
||||
- [x] 6. Verify VCL burndown is unaffected
|
||||
- [x] 6.1 Confirm burndown and donut queries read from compliance_items.resolution_date only, no code changes
|
||||
- _Requirements: 3_
|
||||
|
||||
- [x] 7. Create migration to add metric_id column to compliance_item_history
|
||||
- [x] 7.1 Create `backend/migrations/add_compliance_history_metric_id.js` that adds nullable `metric_id TEXT` column (idempotent check if column exists), creates index on (hostname, metric_id), register in run-all.js, run migration and verify column exists, verify existing rows retain NULL
|
||||
- _Requirements: 14_
|
||||
|
||||
- [x] 8. Extend PATCH /items/:hostname/metadata to support per-metric scoping
|
||||
- [x] 8.1 Accept optional `metric_id` (string) and `metric_ids` (array) in request body; if both provided use metric_ids; validate non-empty and max 100 chars; validate each corresponds to active compliance_item
|
||||
- _Requirements: 8_
|
||||
- [x] 8.2 When metric_ids provided: SELECT current values per targeted metric, INSERT history with metric_id per changed field, UPDATE only matching rows
|
||||
- _Requirements: 8, 11_
|
||||
- [x] 8.3 When neither metric_id nor metric_ids provided: preserve hostname-level behavior with NULL metric_id in history entries
|
||||
- _Requirements: 15_
|
||||
|
||||
- [x] 9. Extend GET /items/:hostname to include metric_id in history entries
|
||||
- [x] 9.1 Update history query to SELECT metric_id column, include metric_id in each history entry in response, verify NULL entries returned correctly
|
||||
- _Requirements: 4, 11_
|
||||
|
||||
- [x] 10. Add MetricChipSelector for metadata editing in ComplianceDetailPanel
|
||||
- [x] 10.1 Add metricSelection state separate from notes selector, default all active metrics selected on panel open, render MetricChipSelector above resolution_date/remediation_plan inputs with category-colored chips and Select All/Deselect All toggle
|
||||
- _Requirements: 9_
|
||||
- [x] 10.2 Implement computeSharedValues: display shared value when all selected metrics agree, show "Multiple values" placeholder when they differ, omit unchanged fields from PATCH
|
||||
- _Requirements: 10_
|
||||
- [x] 10.3 When all metrics selected omit metric_ids from request body (backward compat), when subset selected include metric_ids, run npm run build
|
||||
- _Requirements: 15_
|
||||
|
||||
- [x] 11. Update history display to show per-metric labels
|
||||
- [x] 11.1 When history entry has non-null metric_id display MetricChip, when null display "All metrics" label, build metricMap from metrics array, verify existing entries display correctly, run npm run build
|
||||
- _Requirements: 12_
|
||||
|
||||
- [x] 12. Verify per-metric burndown reporting works correctly
|
||||
- [x] 12.1 Confirm burndown forecast reads resolution_date per compliance_items row, donut uses per-row presence, aggregated view uses MAX(resolution_date), no code changes expected
|
||||
- _Requirements: 13_
|
||||
|
||||
## Notes
|
||||
|
||||
- Tasks 1–6 are already implemented (hostname-level history tracking is live in production)
|
||||
- Tasks 7–12 implement the per-metric extension from GitLab issue #19
|
||||
- Task 7 must run first as it adds the metric_id column needed by all subsequent tasks
|
||||
- Tasks 10 and 11 can run in parallel after Task 9 completes
|
||||
- Task 12 is verification-only and depends on both frontend tasks completing
|
||||
|
||||
## Task Dependency Graph
|
||||
|
||||
```json
|
||||
{
|
||||
"waves": [
|
||||
{ "id": 0, "tasks": ["7.1"] },
|
||||
{ "id": 1, "tasks": ["8.1", "8.2", "8.3"] },
|
||||
{ "id": 2, "tasks": ["9.1"] },
|
||||
{ "id": 3, "tasks": ["10.1", "10.2", "10.3", "11.1"] },
|
||||
{ "id": 4, "tasks": ["12.1"] }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user