Skip to content

FEAT: Searchable multi-select filters for Attack History (ADO 7834)#1643

Open
adrian-gavrila wants to merge 7 commits intomicrosoft:mainfrom
adrian-gavrila:adrian-gavrila/attack-history-comboboxes
Open

FEAT: Searchable multi-select filters for Attack History (ADO 7834)#1643
adrian-gavrila wants to merge 7 commits intomicrosoft:mainfrom
adrian-gavrila:adrian-gavrila/attack-history-comboboxes

Conversation

@adrian-gavrila
Copy link
Copy Markdown
Contributor

@adrian-gavrila adrian-gavrila commented Apr 22, 2026

Migrates the Attack History view's Fluent UI Dropdowns to searchable multi-select Comboboxes and expands backend filter semantics to support the new UX. Resolves ADO 7834.

User-visible changes

  • Attack type, converter, operator, and operation filters are now searchable multi-select Comboboxes (was: single-select Dropdowns). Selected-value display shows the first pick with a (+N) suffix when more than one is selected.
  • The converter filter has a new (No converters) option, mutually exclusive with picking specific converters.
  • When 2+ converters are selected, a Match any | Match all Switch controls whether an attack must use any or all of them.
image

REST contract change

  • GET /attacks query param attack_class is renamed to attack_types (repeated, list-valued) to align with the multi-select UI and the already-existing GET /attack-options response field. The only in-tree consumer is the frontend, updated in this PR.

Memory layer additions (non-breaking)

  • MemoryInterface.get_attack_results gains a new attack_classes: Sequence[str] param for OR-matched multi-filtering, plus has_converters: bool | None for explicit presence/absence filtering. The old attack_class: str param is preserved as a deprecated forwarder, and converter_classes=[] keeps its original "no converters" semantic.

Tests and Documentation

Tests added

  • Memory: new tests for attack_classes multi-match, has_converters=True/False, back-compat of singular attack_class, and the ValueError when both singular and plural are passed.
  • Service: has_converters forwarding, match-mode combinations, attack_types list handling.
  • Route: query param rename, repeated attack_types, converter_types_match any/all, has_converters wiring.
  • Frontend: sentinel option, sentinel/converter mutual exclusion, match-mode Switch visibility + emission, multi-select attack type, has_converters API forwarding, conditional converter_types_match emission, multi-select display formatting, outcome filter label persistence.

Documentation: updated relevant docstrings, but no changes to other documentation

Adrian Gavrila and others added 6 commits April 22, 2026 16:12
…ilter"

Add a tri-state has_converters param to get_attack_results. Previously
converter_classes=[] meant "attacks with no converters"; it now means
"no filter". Use has_converters=False for the old behavior.

BREAKING CHANGE: converter_classes=[] no longer filters to zero-converter
attacks. No in-repo callers relied on this.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update the AttackService and REST route to forward the new has_converters
param to memory, and rename the route query param from attack_class (scalar)
to attack_types (repeated) for consistency with the other list-valued
filters.

BREAKING CHANGE: REST query param attack_class renamed to attack_types.
Only in-tree consumer is the frontend, updated in the next commit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace Dropdowns with searchable multi-select Comboboxes for attack
class, converter, operator, and operation filters. The converter
Combobox includes a "(No converters)" sentinel option that maps to
has_converters=false. A match-mode Switch (ANY|ALL) appears when two
or more converters are selected.

Adapts AttackHistory.fetchAttacks to send attack_types (repeated),
converter_types_match, and has_converters to the API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…] semantic)

Restores the deprecated singular `attack_class` parameter as a forwarder to `attack_classes` and reverts `converter_classes=[]` to its original "no converters" meaning. Library callers see no behavior change; the new `attack_classes`/`has_converters` params remain available for explicit multi/presence filtering.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Multi-select Comboboxes now display "<first> (+N)" instead of always showing the placeholder. Swaps the outcome filter from Dropdown to single-select Combobox so its visible label persists across re-renders triggered by sibling filter changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ce label keys

- Service layer coerces converter_types=[] to 'no filter'; the 'no converters'
  intent is expressed via has_converters=False. Keeps route/service/memory
  semantics consistent.
- memory_interface.get_attack_results strips label keys whose value is an
  empty sequence before emitting the label condition (previously produced a
  strictly-more-restrictive EXISTS predicate).
- Skip the redundant has_converters=True predicate when converter_classes is
  already non-empty.
- Adds unit tests for the empty-sequence/no-identifier branches in the memory
  and backend service layers.
- Fixes two Attack History e2e specs to click the Combobox input (Fluent v9
  multiselect doesn't open the listbox on wrapper click).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rlundeen2 rlundeen2 self-requested a review April 22, 2026 22:58
- Fluent v9 multiselect Combobox renders items as role=menuitemcheckbox,
  not role=option. Update attack-class and operator filter tests to
  query the correct role.
- Update the mockHistoryAPIs handler to read the renamed attack_types
  (plural, repeatable) query param and to group repeated label keys
  into OR-sets (matches the route's real semantic).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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