Skip to content

feat: Phase 3C.2 — per-engagement attack chain graph view#10

Merged
Emperiusm merged 18 commits intomainfrom
feature/phase3c2-clean
Apr 13, 2026
Merged

feat: Phase 3C.2 — per-engagement attack chain graph view#10
Emperiusm merged 18 commits intomainfrom
feature/phase3c2-clean

Conversation

@Emperiusm
Copy link
Copy Markdown
Owner

Summary

  • Interactive force-graph visualization at /engagements/:id/chain for exploring attack chain relationships between findings
  • GET /api/chain/subgraph endpoint with severity/status filtering, max_nodes cap, and neighborhood expansion
  • PATCH /api/chain/relations/:id for edge curation (confirm/reject) with drift detection
  • 6 new Vue components: ForceGraphCanvas, ChainDetailPanel, ChainFilterToolbar, ChainLegend, ChainEmptyState, ChainGraphView
  • 13 new backend tests (80 total, all passing)

Test plan

  • Backend: 80/80 tests passing (13 new: 6 subgraph + 7 curation)
  • Frontend: TypeScript type check clean (0 errors)
  • Frontend: Vite production build successful
  • Manual: login → engagement → "Attack Chain" button → verify graph renders
  • Manual: click node → detail panel → expand neighbors
  • Manual: click edge → detail panel → confirm/reject → verify optimistic update

🤖 Generated with Claude Code

Emperiusm and others added 18 commits April 13, 2026 03:10
Per-engagement interactive graph visualization using force-graph (vasturiano),
edge curation UI, MITRE ATT&CK phase coloring, server-side filtering for scale.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
15 tasks covering backend (subgraph endpoint, curation PATCH, drift DTO),
frontend (force-graph canvas, detail panel, filters, legend, empty state),
and browser verification.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a new method to ChainService that builds a filtered subgraph for
a single engagement. Queries Finding + ChainFindingRelation ORM models
directly (web-specific aggregation concern), applies severity/status
filters with max_nodes cap, and returns force-graph or canonical shape
with meta (total_findings, rendered_findings, filtered, generation).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ndering

Custom node rendering (severity colors, MITRE pills, selection rings),
custom edge rendering (status-based styles, drift badges, arrowheads),
position-preserving data updates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…uration, expansion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use `new ForceGraph()` constructor (matches type defs), `undefined`
instead of `null` for fx/fy (matches NodeObject interface).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Emperiusm Emperiusm merged commit 9104a72 into main Apr 13, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant