FEAT Wire frontend attack view to backend APIs#1371
Merged
romanlutz merged 139 commits intoAzure:mainfrom Mar 13, 2026
Merged
Conversation
Contributor
|
Can you add screenshots for the frontend |
ValbuenaVC
reviewed
Feb 17, 2026
romanlutz
added a commit
to romanlutz/PyRIT
that referenced
this pull request
Feb 23, 2026
Backend:
- Replace private CentralMemory._memory_instance access with try/except
around the public get_memory_instance() API in the lifespan handler.
Initialization:
- Extract run_initializers_async() as a public function in
pyrit.setup.initialization so initializer execution can be invoked
without redundantly re-loading env files, resetting defaults, and
re-creating the memory instance.
- FrontendCore.run_initializers_async() now calls the new function
directly instead of re-invoking initialize_pyrit_async.
- Export run_initializers_async from pyrit.setup.
Frontend:
- Extract TargetTable into its own component (TargetTable.tsx).
- Move makeStyles definitions to co-located .styles.ts files for
TargetConfig, TargetTable, and CreateTargetDialog.
- Remove redundant explicit generic in useState<string>('') calls.
- Use FluentUI Field validationMessage/validationState props for
inline field-level validation in CreateTargetDialog.
Tests:
- Update TestRunScenarioAsync patches to mock run_initializers_async
instead of initialize_pyrit_async.
c799aa4 to
7e30544
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Wires the PyRIT frontend attack experience to live backend APIs, including target management, attack execution, conversation branching, and richer message rendering.
Changes:
- Added/updated backend attack + target endpoints and DTOs (including conversation summaries and target metadata).
- Refactored initialization flow to shift lifespan init into CLI and consolidate initializer execution.
- Expanded frontend UI (config/history/chat) and added extensive unit + E2E coverage.
Reviewed changes
Copilot reviewed 84 out of 88 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/registry/test_converter_registry.py | Adds unit tests for converter registry singleton/metadata behavior. |
| tests/unit/memory/test_sqlite_memory.py | Adds tests for new conversation stats aggregation in SQLite memory. |
| tests/unit/cli/test_pyrit_backend.py | Adds tests for CLI config-file forwarding and server startup flow. |
| tests/unit/cli/test_frontend_core.py | Updates patch targets and initializer execution expectations after refactor. |
| tests/unit/backend/test_target_service.py | Updates tests for target registry naming changes. |
| tests/unit/backend/test_main.py | Updates lifespan expectations to “warn only” behavior. |
| pyrit/setup/initializers/airt_targets.py | Adds extra kwargs support and new/renamed target presets. |
| pyrit/setup/initializers/airt.py | Switches auth approach to Entra token providers and updates required vars. |
| pyrit/setup/initialization.py | Extracts run_initializers_async to separate initializer execution from memory init. |
| pyrit/setup/init.py | Exposes run_initializers_async as part of setup public API. |
| pyrit/prompt_target/openai/openai_video_target.py | Enforces single-turn conversation constraint for video target. |
| pyrit/prompt_target/openai/openai_target.py | Refactors OpenAI base target inheritance/init to align with PromptTarget. |
| pyrit/prompt_target/openai/openai_response_target.py | Includes target-specific params in identifiers (e.g., extra body params). |
| pyrit/prompt_target/openai/openai_realtime_target.py | Adjusts inheritance to keep chat-target semantics for realtime target. |
| pyrit/prompt_target/openai/openai_image_target.py | Enforces single-turn conversation constraint for image target. |
| pyrit/models/conversation_stats.py | Introduces ConversationStats aggregate model. |
| pyrit/models/attack_result.py | Adds attack_result_id onto domain AttackResult. |
| pyrit/models/init.py | Exports ConversationStats from models package. |
| pyrit/memory/sqlite_memory.py | Adds conversation stats query and refactors some filtering helpers/update behavior. |
| pyrit/memory/memory_models.py | Maps DB primary key into AttackResult.attack_result_id. |
| pyrit/memory/memory_interface.py | Adds conversation stats API and updates attack result insert/update semantics. |
| pyrit/memory/azure_sql_memory.py | Adds Azure SQL implementation for conversation stats and safer update behavior. |
| pyrit/cli/pyrit_backend.py | Refactors CLI to use FrontendCore two-step init and adds --config-file. |
| pyrit/cli/frontend_core.py | Moves deferred imports to module-level and adds run_initializers_async method. |
| pyrit/backend/services/target_service.py | Renames target id field to registry name and updates pagination cursor. |
| pyrit/backend/routes/version.py | Adds database backend info to version response payload. |
| pyrit/backend/routes/targets.py | Renames path params and docs to registry naming scheme. |
| pyrit/backend/routes/attacks.py | Expands attack routes to support conversations and changes identifiers to attack_result_id. |
| pyrit/backend/models/targets.py | DTO rename + adds supports_multiturn_chat. |
| pyrit/backend/models/attacks.py | Adds target metadata nesting, conversation endpoints, and new message request fields. |
| pyrit/backend/models/init.py | Updates exports for renamed message response DTO. |
| pyrit/backend/mappers/target_mappers.py | Maps multiturn capability and renames target id field in DTO mapping. |
| pyrit/backend/mappers/init.py | Renames exported async mapper function. |
| pyrit/backend/main.py | Removes standalone uvicorn runner and changes lifespan to warn when uninitialized. |
| frontend/src/utils/messageMapper.ts | Adds backend DTO ↔ UI Message mapping (attachments, reasoning, errors). |
| frontend/src/types/index.ts | Adds backend DTO type mirrors and expands UI message model. |
| frontend/src/services/api.ts | Adds targets/attacks/labels API clients and query serialization. |
| frontend/src/services/api.test.ts | Expands mocked API service tests for new endpoints. |
| frontend/src/components/Sidebar/Navigation.tsx | Adds navigation views (chat/history/config) and active styling. |
| frontend/src/components/Sidebar/Navigation.test.tsx | Updates navigation tests for new view switching behavior. |
| frontend/src/components/Layout/MainLayout.tsx | Shows DB info in version tooltip and wires navigation callbacks. |
| frontend/src/components/Layout/MainLayout.test.tsx | Updates layout tests for new navigation props and DB tooltip behavior. |
| frontend/src/components/Labels/LabelsBar.test.tsx | Adds unit tests for labels UI behavior and label fetching. |
| frontend/src/components/Config/TargetTable.tsx | Adds target list table UI with active-target selection controls. |
| frontend/src/components/Config/TargetTable.styles.ts | Adds styling for target table and active row highlighting. |
| frontend/src/components/Config/TargetConfig.tsx | Implements target config page with fetch/retry, refresh, and create dialog. |
| frontend/src/components/Config/TargetConfig.test.tsx | Adds tests for config page states and interactions. |
| frontend/src/components/Config/TargetConfig.styles.ts | Adds styling for config page layout and states. |
| frontend/src/components/Config/CreateTargetDialog.tsx | Adds create-target dialog and validation + submit flow. |
| frontend/src/components/Config/CreateTargetDialog.test.tsx | Adds tests for create-target dialog validation and submission. |
| frontend/src/components/Config/CreateTargetDialog.styles.ts | Adds styling for create-target dialog layout. |
| frontend/src/components/Chat/InputBox.tsx | Adds banners/locking states, ref API, and multiturn warnings for active target. |
| frontend/src/components/Chat/InputBox.test.tsx | Adds tests for new input-box behaviors (single-turn, ref attachments, banners). |
| frontend/src/components/Chat/ConversationPanel.tsx | Adds conversation list panel for attacks with promote-to-main and new conversation actions. |
| frontend/src/components/Chat/ConversationPanel.test.tsx | Adds tests for conversation panel rendering and interactions. |
| frontend/src/App.tsx | Introduces multi-view app shell, target selection, attack loading, and global labels. |
| frontend/src/App.test.tsx | Expands app tests for navigation, target selection, and opening historical attacks. |
| frontend/playwright.config.ts | Splits Playwright projects into seeded vs live modes. |
| frontend/package.json | Adds e2e scripts for seeded and live test projects. |
| frontend/eslint.config.js | Adds Node globals for Playwright e2e files. |
| frontend/e2e/config.spec.ts | Adds e2e coverage for config page and config↔chat flow. |
| frontend/e2e/api.spec.ts | Adds e2e API smoke tests (targets/attacks) and improves slow-backend handling. |
| frontend/e2e/accessibility.spec.ts | Updates a11y coverage for new navigation and config table; adjusts expected header text. |
| frontend/dev.py | Improves dev runner process management, adds detach/logs/config-file support. |
| frontend/README.md | Documents seeded vs live e2e modes. |
| .github/workflows/frontend_tests.yml | Runs seeded-only e2e in GitHub Actions. |
| .gitattributes | Adds union merge strategy for squad log/state files. |
| .devcontainer/devcontainer_setup.sh | Makes Playwright install failures non-blocking with clearer messaging. |
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 84 out of 88 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
pyrit/memory/sqlite_memory.py:1
- This function used to return the
exists().where(...)condition, but now assigns it tolabels_subqueryand never returns it. That will cause callers to appendNoneto SQLAlchemy conditions and break attack filtering by labels. Returnlabels_subquery(or inline it back into a return statement).
# Copyright (c) Microsoft Corporation.
- Add run_initializers_async to pyrit.setup for programmatic initialization - Switch AIRTInitializer to Entra (Azure AD) auth, removing API key requirements - Add --config-file flag to pyrit_backend CLI - Use PyRIT configuration loader in FrontendCore and pyrit_backend - Update AIRTTargetInitializer with new target types Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add conversation_stats model and attack_result extensions - Add get_attack_results with filtering by harm categories, labels, attack type, and converter types to memory interface - Implement SQLite-specific JSON filtering for attack results - Add memory_models field for targeted_harm_categories - Add prompt_metadata support to openai image/video/response targets - Fix missing return statements in SQLite harm_category and label filters Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add attack CRUD routes with conversation management - Add message sending with target dispatch and response handling - Add attack mappers for domain-to-DTO conversion with signed blob URLs - Add attack service with video remix support and piece persistence - Expand target service and routes with registry-based target management - Add version endpoint with database info Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add attack-centric chat UI with multi-conversation support - Add conversation panel with branching and message actions - Add attack history view with filtering - Add labels bar for attack metadata - Add target configuration with create dialog - Add message mapper utilities for backend/frontend translation - Add video playback support with signed blob URLs - Add InputBox with attachment support and auto-expand - Update dev.py with --detach, logs, and process management - Add e2e tests for chat, config, and flow scenarios Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
8f1a532 to
65a4182
Compare
Previously _sign_blob_url_async returned URLs unchanged if they already had a query string. This meant stored blob URLs with expired SAS tokens (e.g. video input pieces carried over from prior conversations) would never get fresh tokens. Now the old query string is stripped and a fresh SAS is always generated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1. Add activateTarget() helper that navigates to Config, sets a target active by type, and returns to Chat. Called in beforeEach so all seeded tests have an unlocked UI (fixes 'no active target' issue). 2. Fix video/audio assertions in assertSeededAssistant() to use data-testid='video-error'/'audio-error' fallback elements instead of looking for <video>/<audio> tags that fail to render with invalid test base64 data. 3. Fix branch button test ID from 'branch-btn-1' to 'branch-conv-btn-1' to match the actual data-testid in MessageList. Also scope 'new-conversation-btn' click to the conversation-panel to avoid strict mode violation with duplicate testids. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Address all 17 PR review comments from hannahwestra25 - Rename InputBox to ChatInputArea, extract banner sub-components - Extract AttackHistory sub-components (FiltersBar, Table, Pagination) - Extract styles to separate .styles.ts files - Make ConnectionBanner presentational, move logic to App.tsx - Merge Navigation button styles with data-active attribute - Simplify role mapping, add clearAttackState helper - Wrap CreateTargetDialog in <form> element - Add braces to all braceless if-returns in ChatWindow - Expand GUI documentation with full feature coverage and screenshots - Fix all mock e2e tests (button names, strict mode, no-target state) - Fix all seeded e2e tests (target activation, panel idempotency, media assertions) - Add history filtering e2e tests (type, outcome, operator, reset, pagination) - Add create target dialog e2e tests (full flow, validation) - Add theme toggle e2e test - Add unit tests to meet all coverage thresholds (93.5% stmts, 85.7% branches, 90.7% functions, 96.4% lines) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rror-boundary Addresses PR review comment — replaces the class-based ErrorBoundary with a functional component using the react-error-boundary library. The library uses a class internally but exposes a functional API. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
hannahwestra25
approved these changes
Mar 12, 2026
Seeded/live e2e tests require a backend with Azure credentials which aren't available in CI. Mock tests intercept all API calls at the browser level via Playwright page.route() and don't need a backend. - CI now starts only Vite (not dev.py) for mock e2e tests - Removes Python/uv setup from e2e job (no longer needed) - Seeded/live tests run locally with 'python dev.py' + az login Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tract styles - Task 1: Consolidate 4 banner components (NoTargetBanner, OperatorLockedBanner, CrossTargetBanner, SingleTurnBanner) into a single reusable StatusBanner component in ChatInputArea.tsx. All test IDs preserved. - Task 2: Rename hasMore to isLastPage (inverted logic) in AttackHistory.tsx and HistoryPagination.tsx. - Task 3: Add test files for HistoryFiltersBar and AttackTable with comprehensive coverage for rendering, callbacks, and edge cases. - Task 4: Extract inline makeStyles to .styles.ts files for 7 components: ChatInputArea, MainLayout, Navigation, ChatWindow, LabelsBar, ConversationPanel, MessageList. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per reviewer feedback, useLayoutEffect fires synchronously before paint, preventing the visible flicker that useEffect can cause when resizing the textarea height based on scrollHeight. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The user-attachments URLs are ephemeral and fail the pre-commit link checker. Screenshots are available in the PR description. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…I docs" This reverts commit 1398256.
Downloads the 5 PR screenshots into doc/code/gui/images/ and updates 0_gui.md to reference them locally, fixing the pre-commit link checker. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add internal messages state to ChatWindow with useState - Remove messages, onSendMessage, onReceiveMessage, onSetMessages props - Inline send/receive logic: setMessages replaces prop callbacks - Add useEffect to clear messages when attackResultId becomes null - Update viewedConvRef after conversation creation in handleSend - Remove messages state and handler functions from App.tsx - Update tests to assert on DOM content instead of callback props Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds test_remix_with_text_and_video_path_pieces which covers the full send_prompt_async flow when the frontend sends both a text piece and a video_path piece with matching video_id metadata (the UI remix flow). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep Python and uv installed so seeded tests can be re-enabled once CI secrets are configured. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
These tests call real backend endpoints (/api/health, /api/targets, /api/attacks) and timeout in CI where only Vite runs. Tagging them @seeded excludes them from the mock project. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add target management and real attack execution to the PyRIT frontend, replacing the echo stub with live backend communication.
Backend:
CLI:
Frontend:
Tests:
Screenshots:
Landing page

History view

Target config view

Text-to-text


Branching into new conversation after first turn
Text-to-image



Reusing the same image for text+image-to-image
Text-to-video


Text+video-to-video