Skip to content

feat: Compare threat models in Studio - #117

Merged
Hacks4Snacks merged 2 commits into
mainfrom
hacks4snacks/comparesupport
Sep 20, 2026
Merged

Hacks4Snacks merged 2 commits into
mainfrom
hacks4snacks/comparesupport

Conversation

@Hacks4Snacks

Copy link
Copy Markdown
Owner

Why

Make model revisions reviewable in Studio without merging files or modifying
the working canvas. Show structural changes, changed trust-boundary crossings,
and their effect on analysis findings in one place.

What changed

  • Add a Compare workspace for a baseline file versus a current-canvas snapshot
    or proposed file, with independent read-only diagrams and page-aware highlighting.
  • Add category/text filtering, change navigation, 100-row pagination, and
    before/after property details.
  • Compose the existing structural, boundary-crossing, and findings diff engines
    behind a shared comparison operation exposed through HTTP and WASM.
  • Preserve stable object/finding identities; classify severity and disposition
    changes separately from introduced or resolved findings.
  • Run import preflight, require confirmation for known losses, and retain warnings.
    Unavailable analysis is explicitly reported, never presented as resolved findings.
  • Protect editor state, triage, file bindings, dirty status, and undo history.
    Opening Compare invalidates pending Tidy/import operations, including responses
    arriving after Review closes.
  • Update API/Studio documentation and generated contracts.

Scope

Both snapshots are analyzed with the current engine and active rule bundle;
this is not historical analysis replay or a merge operation.

Visual-only changes and full metadata/threat-register content are not compared
field by field. Metadata and author-owned threat-record differences produce
scope warnings. Input and change limits refuse oversized comparisons rather
than silently truncating results.

Comment on lines +77 to +85
foreach (ElementDescriptor previous in baseline.Elements.Values.OrderBy(element => element.Id))
{
if (!changed.Contains(previous.Id) && proposed.Elements.TryGetValue(previous.Id, out ElementDescriptor? current) && previous.DiagramId != current.DiagramId)
{
List<PropertyChange> properties = new List<PropertyChange>();
AddPageMove(previous.Id, baseline, proposed, properties);
changes.Add(ElementChange(previous.Id, "structure", "modified", current.Name, baseline, proposed, properties));
}
}
Comment on lines +277 to +283
foreach (string endpoint in new[] { "source", "target" })
{
if (element.Attributes.TryGetValue(endpoint, out string? value) && Guid.TryParse(value, out Guid parsed))
{
targets.Add(parsed);
}
}
@Hacks4Snacks
Hacks4Snacks merged commit 8a420d2 into main Sep 20, 2026
11 checks passed
@Hacks4Snacks
Hacks4Snacks deleted the hacks4snacks/comparesupport branch September 20, 2026 21:16
This was referenced Sep 20, 2026
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.

2 participants