From d61383ac7b8e8ff759f5e2ed1310a555a8e09137 Mon Sep 17 00:00:00 2001 From: Jordan Ramos Date: Thu, 14 May 2026 08:15:42 -0600 Subject: [PATCH] Add VCL reporting guide, update reference manual and config wizard; untrack .kiro/steering/workflow.md --- .kiro/steering/workflow.md | 27 ----- configure.js | 33 +++--- docs/guides/full-reference-manual.md | 6 +- docs/guides/kb-vcl-reporting-guide.md | 164 ++++++++++++++++++++++++++ 4 files changed, 186 insertions(+), 44 deletions(-) delete mode 100644 .kiro/steering/workflow.md create mode 100644 docs/guides/kb-vcl-reporting-guide.md diff --git a/.kiro/steering/workflow.md b/.kiro/steering/workflow.md deleted file mode 100644 index 9e5c5bf..0000000 --- a/.kiro/steering/workflow.md +++ /dev/null @@ -1,27 +0,0 @@ -# Workflow & Context Gathering - -## Specs First - -Before making changes to any feature area, **always check `.kiro/specs/` for related spec folders first**. Specs contain the original requirements, design decisions, architecture diagrams, data models, and task breakdowns that informed the implementation. They provide critical context about: - -- Why a feature was built a certain way -- What data models and API contracts were agreed upon -- What correctness properties must hold -- What edge cases were considered - -Even if the code has evolved since the spec was written, the spec is the starting point for understanding intent. - -## Spec Folder Structure - -Each spec folder typically contains: - -- `requirements.md` — user stories and acceptance criteria -- `design.md` — architecture, data models, API contracts, error handling -- `tasks.md` — implementation task breakdown with completion status - -## When to Check Specs - -- Fixing bugs in a feature area — check the spec to understand intended behavior -- Adding to an existing feature — check the spec to understand design constraints -- Investigating unexpected behavior — the spec documents what "correct" looks like -- Refactoring — the spec documents which properties must be preserved diff --git a/configure.js b/configure.js index 8121dcf..477e832 100644 --- a/configure.js +++ b/configure.js @@ -104,9 +104,9 @@ const VARIABLE_DESCRIPTORS = [ { name: 'CORS_ORIGINS', group: 'Core Settings', - required: true, + required: false, default: null, // derived from frontend port at runtime - description: 'Comma-separated list of allowed CORS origins for the backend', + description: 'Allowed CORS origins (only needed if frontend dev server runs on a separate port)', docUrl: null, sensitive: false, validator: 'validateCorsOrigins' @@ -1229,6 +1229,21 @@ async function main() { let confirmedPort = null; for (const group of GROUP_ORDER) { + // Auto-derive Frontend Settings from PORT and API_HOST — no need to prompt + if (group === 'Frontend Settings') { + const port = confirmedPort || '3001'; + const host = values.get('API_HOST') || 'localhost'; + const apiBase = `http://${host}:${port}/api`; + const apiHost = `http://${host}:${port}`; + values.set('REACT_APP_API_BASE', apiBase); + values.set('REACT_APP_API_HOST', apiHost); + console.log(`\n=== Frontend Settings ===`); + console.log(` Auto-configured from your backend settings:`); + console.log(` REACT_APP_API_BASE = ${apiBase}`); + console.log(` REACT_APP_API_HOST = ${apiHost}`); + continue; + } + printGroupHeader(group); // For skippable groups, ask if user wants to configure @@ -1267,14 +1282,6 @@ async function main() { if (confirmedPort !== null) { currentValue = null; // Will use derived default below } - } else if (descriptor.name === 'REACT_APP_API_BASE') { - if (confirmedPort !== null) { - currentValue = null; // Will use derived default below - } - } else if (descriptor.name === 'REACT_APP_API_HOST') { - if (confirmedPort !== null) { - currentValue = null; // Will use derived default below - } } } @@ -1292,12 +1299,6 @@ async function main() { }; } else if (descriptor.name === 'CORS_ORIGINS' && currentValue === null && descriptor.default === null) { effectiveDescriptor = { ...descriptor, default: 'http://localhost:3000' }; - } else if (descriptor.name === 'REACT_APP_API_BASE' && currentValue === null && descriptor.default === null) { - const port = confirmedPort || '3001'; - effectiveDescriptor = { ...descriptor, default: `http://localhost:${port}/api` }; - } else if (descriptor.name === 'REACT_APP_API_HOST' && currentValue === null && descriptor.default === null) { - const port = confirmedPort || '3001'; - effectiveDescriptor = { ...descriptor, default: `http://localhost:${port}` }; } const result = await promptVariable(rl, effectiveDescriptor, currentValue); diff --git a/docs/guides/full-reference-manual.md b/docs/guides/full-reference-manual.md index c32fa2a..7c00313 100644 --- a/docs/guides/full-reference-manual.md +++ b/docs/guides/full-reference-manual.md @@ -684,6 +684,8 @@ All endpoints are prefixed with `/api`. All endpoints except `/api/auth/login` a | POST | `/api/ivanti/fp-workflow/submissions/:id/findings` | Admin, Standard_User | Add or remove findings on an existing submission | | POST | `/api/ivanti/fp-workflow/submissions/:id/attachments` | Admin, Standard_User | Upload additional attachments (local files and/or `libraryDocIds`) to an existing submission | | PATCH | `/api/ivanti/fp-workflow/submissions/:id/status` | Admin, Standard_User | Update submission lifecycle status | +| PATCH | `/api/ivanti/fp-workflow/submissions/:id/dismiss` | Admin, Standard_User | Dismiss a rejected submission (sets `dismissed_at` timestamp) | +| POST | `/api/ivanti/fp-workflow/submissions/:id/requeue` | Admin, Standard_User | Re-queue findings from a rejected submission into the todo queue under a new workflow type | ### Ivanti — Todo Queue @@ -889,7 +891,7 @@ All tables are defined in `backend/db-schema.sql` and created by `setup-postgres **`ivanti_todo_queue`** — Personal per-user queue of findings staged for FP, Archer, or CARD processing. Keyed by `(user_id, finding_id)`. Completed items can be redirected to a different workflow type via `POST /:id/redirect`, which creates a new pending item preserving the original finding data. -**`ivanti_fp_submissions`** — Record of FP workflow submissions to the Ivanti API. Tracks user, workflow batch ID, form fields, finding IDs, queue item IDs, attachment results, and submission status (success/partial/failed). +**`ivanti_fp_submissions`** — Record of FP workflow submissions to the Ivanti API. Tracks user, workflow batch ID, form fields, finding IDs, queue item IDs, attachment results, and submission status (success/partial/failed). Rejected submissions can be dismissed (`dismissed_at`) or re-queued to the todo queue under a different workflow type (`requeued_at`). **`compliance_uploads`** — Record of each compliance xlsx upload: filename, report date, uploader, timestamp, and new/resolved/recurring counts. @@ -1040,6 +1042,8 @@ node migrations/add_fp_submissions_table.js node migrations/add_user_groups.js node migrations/add_created_by_columns.js node migrations/add_fp_submission_editing.js +node migrations/add_fp_submissions_dismissed.js +node migrations/add_fp_submissions_requeued_at.js node migrations/add_granite_workflow_type.js node migrations/add_compliance_notes_group_id.js ``` diff --git a/docs/guides/kb-vcl-reporting-guide.md b/docs/guides/kb-vcl-reporting-guide.md new file mode 100644 index 0000000..459087e --- /dev/null +++ b/docs/guides/kb-vcl-reporting-guide.md @@ -0,0 +1,164 @@ +# VCL Executive Reporting — How It Works + +## Overview + +The VCL (Vulnerability Compliance Level) Report page generates an executive-level compliance summary from device-level data already tracked in the STEAM Security Dashboard. It aggregates individual device findings into team-level metrics, burndown projections, and compliance percentages — the same data leadership uses in the VCL deck for quarterly reporting. + +The report is not a separate data source. It reads from the same `compliance_items` table that the AEO Compliance page uses. The difference is the view: Compliance shows device-level detail, VCL shows team-level aggregation. + +--- + +## Metrics Explained + +### Stats Bar + +| Metric | What It Means | What Feeds It | +|---|---|---| +| Total Devices | Count of unique hostnames across all compliance items (active + resolved) | Weekly compliance xlsx upload | +| In-Scope | Same as Total Devices (all tracked devices are considered in-scope) | Weekly compliance xlsx upload | +| Compliant | Devices with NO active findings (all their findings are resolved) | Compliance upload resolves findings when devices drop off the report | +| Non-Compliant | Devices with at least one active finding | Compliance upload adds new findings; devices stay non-compliant until all findings resolve | +| Remediations Required | Same as Non-Compliant (each non-compliant device needs remediation) | Same as Non-Compliant | +| Current % | `(Compliant / In-Scope) * 100`, rounded to whole number | Computed from the counts above | +| Target % | Organization-defined compliance target (default 95%) | Set via `VCL_TARGET_PCT` environment variable on the backend | + +### Status of Non-Compliant Assets (Donut Chart) + +| Segment | What It Means | What Feeds It | +|---|---|---| +| Blocked | Non-compliant devices with NO resolution date set — the team has not committed to a remediation timeline | Devices without a `resolution_date` value | +| In-Progress | Non-compliant devices WITH a resolution date set — the team has a target fix date | Devices with a `resolution_date` value | + +**How to move devices from Blocked to In-Progress:** Set a resolution date on the device, either by clicking into it on the Compliance page and entering a date, or by using the Bulk Upload with a "Resolution Date" column. + +### Heavy Hitters Table + +| Column | What It Means | What Feeds It | +|---|---|---| +| Vertical / Team | The team responsible for the non-compliant devices | `team` field on compliance items (set during xlsx upload) | +| Non-Compliant | Count of unique hostnames with active findings for that team | Computed from compliance_items | +| Compliance Date | The team's stated target for full remediation (e.g., "Q3 2026") | Manually entered on this page (click to edit) | +| Notes | Team-level summary of their remediation approach | Manually entered on this page (click to edit) | + +### Vertical Breakdown Table + +| Column | What It Means | What Feeds It | +|---|---|---| +| Vertical | Team name | `team` field on compliance items | +| Compliance % | `(Compliant devices in team / Total devices in team) * 100` | Computed from compliance_items | +| Team | Same as Vertical | Same | +| Non-Compliant | Count of non-compliant devices for that team | Computed from compliance_items | +| Forecast Burndown (monthly columns) | How many devices are expected to be remediated each month | Grouped by the `resolution_date` month on individual devices | +| Blockers | Non-compliant devices with NO resolution date (no committed timeline) | Count of devices where `resolution_date` is NULL | +| RAs | Risk Acceptances — count of approved exceptions for that team | Manually entered on this page (click to edit) | +| Notes | Team-level remediation narrative | Manually entered on this page (click to edit) | + +### Compliance Overview Trend Chart + +| Element | What It Means | What Feeds It | +|---|---|---| +| Green bars | Count of compliant devices for each month | Monthly snapshots (created automatically on each compliance upload) | +| Solid teal line | Actual compliance percentage for each month | Monthly snapshots | +| Dashed teal line | Forecasted compliance percentage (projected forward) | Linear regression on the last 3+ months of actual data | +| Amber horizontal line | Target compliance threshold | `VCL_TARGET_PCT` environment variable | + +> The trend chart requires at least one compliance upload to create the first snapshot. After 3+ monthly uploads, the forecast line appears. + +--- + +## What Feeds the Data + +### Automatic (from compliance uploads) + +These values update automatically when a new weekly compliance xlsx is uploaded: + +- Total Devices, In-Scope, Compliant, Non-Compliant counts +- Current Compliance % +- Per-team compliance percentages +- Monthly trend snapshots (one snapshot per upload) +- Devices moving between active/resolved status + +### Manual (entered by engineers or BIs) + +These values are entered by users and persist until changed: + +| Field | Where to Enter It | Scope | +|---|---|---| +| Resolution Date | Compliance page → click device → Resolution Date field | Per device | +| Remediation Plan | Compliance page → click device → Remediation Plan field | Per device | +| Compliance Date | VCL Report → Heavy Hitters table → click the cell | Per team | +| Notes | VCL Report → Heavy Hitters or Vertical Breakdown → click the cell | Per team | +| RAs (Risk Acceptances) | VCL Report → Vertical Breakdown → click the cell | Per team | + +### Bulk Upload + +For updating many devices at once (e.g., 1000 devices), use the **Bulk Upload** button on the VCL Report page: + +1. Prepare an xlsx file with columns: `Hostname`, `Resolution Date`, `Remediation Plan`, `Notes` +2. Click Bulk Upload and select the file +3. Review the diff preview (shows matched/unmatched/changed/invalid counts) +4. Confirm to commit changes + +--- + +## How Metrics Adjust Over Time + +### Weekly Compliance Upload Cycle + +Each weekly xlsx upload triggers these changes: + +1. **New findings** appear as active items → Non-Compliant count increases +2. **Resolved findings** (devices no longer on the report) get marked resolved → Compliant count increases +3. **A monthly snapshot** is created/updated in `compliance_snapshots` → feeds the trend chart +4. **Stats bar** reflects the new totals immediately + +### As Teams Set Resolution Dates + +When resolution dates are added to devices: + +1. **Donut chart shifts** — devices move from "Blocked" (red) to "In-Progress" (amber) +2. **Forecast burndown columns populate** — showing expected remediations per month per team +3. **Blockers count decreases** — fewer devices without a committed timeline + +### As Devices Get Remediated + +When a device drops off the weekly compliance report (finding resolved): + +1. **Non-Compliant count decreases** +2. **Compliant count increases** +3. **Current % improves** +4. **Team compliance % improves** +5. **The device's resolution_date no longer contributes to forecast** (it's done) + +### Trend Chart Over Months + +After 3+ monthly compliance uploads: + +1. The trend chart shows actual compliance % per month (solid line) +2. A linear regression projects the trend forward 3 months (dashed line) +3. You can see whether the organization is on track to hit the target % (amber line) + +--- + +## Summary: Data Flow + +``` +Weekly xlsx upload + → compliance_items (active/resolved findings per device) + → compliance_snapshots (monthly aggregate for trend chart) + → Stats bar, donut, heavy hitters, vertical breakdown auto-update + +Engineers set resolution_date on devices (manual or bulk upload) + → Donut shifts from Blocked to In-Progress + → Forecast burndown columns populate + → Blockers count decreases + +BIs edit team-level fields on VCL Report page + → Compliance Date, Notes, RAs saved per team + → Displayed in Heavy Hitters and Vertical Breakdown tables + +Devices remediated (drop off next weekly upload) + → Compliance % improves + → Trend chart shows upward movement + → Forecast adjusts based on new regression +```