diff --git a/web/public/app.js b/web/public/app.js index 16a8534..a816780 100644 --- a/web/public/app.js +++ b/web/public/app.js @@ -3147,7 +3147,11 @@ function renderGraphFindingList(x) { const findings = (data.nodes || []).filter(n => n.label === 'Finding'); findings.sort((a, b) => sevRank(a.props?.local_severity) - sevRank(b.props?.local_severity)); const sel = x.view.filterFinding || 'overview'; + const runIds = new Set(); + for (const f of findings) for (const part of (f.key || '').split(':')) { if (part.startsWith('ns-')) runIds.add(part); } + const cumulative = runIds.size > 1; list.innerHTML = `
Attack Paths
+ ${cumulative ? '
Cumulative — includes findings from previous runs of this target.
' : ''} ${findings.map(f => { const sev = f.props?.local_severity || 'info'; diff --git a/web/public/style.css b/web/public/style.css index dfbd103..061cc22 100644 --- a/web/public/style.css +++ b/web/public/style.css @@ -1158,6 +1158,7 @@ a.deliv-card:hover { border-color: var(--accent); } .graph-split { display: flex; gap: 0; height: 100%; min-height: 540px; } .graph-finding-list { width: 220px; min-width: 180px; flex: none; border-right: 1px solid var(--border); overflow-y: auto; background: var(--surface); padding: 0; } .gfl-header { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text-dim); padding: var(--sp-3) var(--sp-3) var(--sp-2); } +.gfl-note { font-size: var(--fs-2xs); color: var(--text-dim); padding: 0 var(--sp-3) var(--sp-2); line-height: 1.4; font-style: italic; } .gfl-item { display: flex; align-items: center; gap: var(--sp-2); width: 100%; text-align: left; background: none; border: none; border-bottom: 1px solid var(--border); padding: var(--sp-2) var(--sp-3); font-size: var(--fs-xs); color: var(--text); cursor: pointer; line-height: 1.3; } .gfl-item:hover { background: var(--surface-3); } .gfl-item.active { background: var(--accent-soft, rgba(181,89,10,.08)); color: var(--accent); font-weight: 600; border-left: 3px solid var(--accent); }