New feature: multi-file per-vertical compliance xlsx upload with scoped resolution logic, executive-level aggregated reporting, and drill-down by vertical and metric. Supports daily upload cadence and batch commit. Backend: - Migration: add vertical column to compliance_items/uploads, create vcl_multi_vertical_summary table - New route module: routes/vclMultiVertical.js with preview, commit, stats, trend, metric drill-down, device list, and burndown endpoints - New helpers: parseVerticalFilename(), computeVerticalBurndown() - Vertical-scoped resolution: uploading one vertical never resolves items from other verticals Frontend: - CCPMetricsPage with stats bar, trend chart, donut, vertical table - Drill-down: vertical -> metrics by category -> device list - Per-vertical burndown forecast chart - MultiVerticalUploadModal: multi-file drag-drop, batch preview, commit - Nav entry: CCP Metrics (Building2 icon) Docs: - Design brief for stakeholder meeting (docs/vcl-multi-vertical-design-brief.md)
Database Migrations
These migration scripts were used to evolve the database schema during development. They are NOT needed for fresh deployments — setup.js contains the complete v1.0.0 schema.
These are retained for reference and for upgrading existing deployments that were set up before v1.0.0.
Schema Migrations (run in order for existing deployments)
| Script | Purpose |
|---|---|
add_ivanti_sync_table.js |
Creates ivanti_sync_state table for tracking Ivanti sync status |
add_ivanti_findings_tables.js |
Creates ivanti_findings_cache, ivanti_finding_notes, ivanti_counts_cache, ivanti_finding_overrides tables |
add_ivanti_counts_history_table.js |
Creates ivanti_counts_history table for trend chart data |
add_ivanti_todo_queue_table.js |
Creates ivanti_todo_queue table for FP/Archer workflow queuing |
add_todo_queue_hostname.js |
Adds hostname column to ivanti_todo_queue |
add_todo_queue_ip_address.js |
Adds ip_address column to ivanti_todo_queue |
add_fp_submissions_table.js |
Creates ivanti_fp_submissions table for false positive workflow tracking |
add_fp_submission_editing.js |
Adds lifecycle_status, ivanti_workflow_batch_uuid, updated_at columns and ivanti_fp_submission_history table |
add_knowledge_base_table.js |
Creates knowledge_base table for KB article storage |
add_user_groups.js |
Adds user_group column to users table with validation triggers |
add_created_by_columns.js |
Adds created_by column to compliance_notes and knowledge_base tables |
add_compliance_tables.js |
Creates compliance_uploads, compliance_items, compliance_notes tables |
add_compliance_notes_group_id.js |
Adds group_id column to compliance_notes for multi-metric note grouping |
add_archer_tickets_table.js |
Creates archer_tickets table for Archer exception tracking |
add_archer_tickets_timestamps.js |
Adds created_at and updated_at columns to archer_tickets |
add_jira_sync_columns.js |
Adds Jira sync-related columns to jira_tickets |
add_card_workflow_type.js |
Adds CARD to workflow_type CHECK constraint on ivanti_todo_queue |
add_granite_workflow_type.js |
Adds GRANITE to workflow_type CHECK constraint on ivanti_todo_queue |
add_finding_archive_tables.js |
Creates ivanti_finding_archives and ivanti_archive_transitions tables |
add_closed_gone_state.js |
Adds CLOSED_GONE to current_state CHECK constraint on ivanti_finding_archives |
add_sync_anomaly_tables.js |
Creates ivanti_sync_anomaly_log and ivanti_finding_bu_history tables |
add_atlas_action_plans_cache.js |
Creates atlas_action_plans_cache table for Atlas API caching |
add_return_classification.js |
Adds return_classification_json column to ivanti_sync_anomaly_log |
Data Migrations (one-time backfills)
| Script | Purpose |
|---|---|
backfill_anomaly_log.js |
Synthesizes anomaly log entries from existing archive transitions for historical chart data |
backfill_return_classification.js |
Populates return_classification_json for existing anomaly rows with returned findings. Supports --force flag to re-run. |
reclassify_bu_roundtrips.js |
Reclassifies archive transitions that were BU reassignment round-trips (archived then returned within 14 days) from the default severity_score_drift to bu_reassignment |