feat(vulnerabilities): filter to entries with AI assessment available#91
Merged
Merged
Conversation
Adds a HasAssessmentOnly filter to the vulnerabilities list so analysts can narrow the workbench to entries that already have an AI-generated VulnerabilityPatchAssessment row. Backend extends VulnerabilityFilterQuery and applies the filter via a VulnerabilityPatchAssessments lookup in VulnerabilitiesController. Frontend wires the field through the route search schema, list-state request builder and query key, the table props, and the filter drawer. A new "AI Assessment" section in the drawer exposes the toggle; an "AI assessment available" chip appears in the active-filter row when it is on, and the structured-filter count and clear-filters handler both account for it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new “AI assessment available” filter to the vulnerabilities workbench, enabling analysts to restrict the list to vulnerabilities that already have a generated VulnerabilityPatchAssessment.
Changes:
- Backend:
VulnerabilityFilterQuerygainsHasAssessmentOnly;VulnerabilitiesControllerapplies anEXISTS-style filter againstVulnerabilityPatchAssessments. - Frontend: wires
hasAssessmentOnlythrough route search schema, API request builder, query keys, andVulnerabilityTableUI (drawer section + active-filter chip). - Updates related fixtures/usages (e.g., dashboard workbench link and list-state tests).
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/PatchHound.Api/Models/Vulnerabilities/VulnerabilityFilterQuery.cs | Adds HasAssessmentOnly query parameter to the filter model. |
| src/PatchHound.Api/Controllers/VulnerabilitiesController.cs | Filters vulnerabilities to those with a patch assessment when requested. |
| frontend/src/routes/_authed/vulnerabilities/index.tsx | Adds hasAssessmentOnly to route search schema and wires it into the table + clear/apply behavior. |
| frontend/src/features/vulnerabilities/list-state.ts | Includes hasAssessmentOnly in request building and React Query keys. |
| frontend/src/features/vulnerabilities/list-state.test.ts | Updates fixtures to include hasAssessmentOnly in test inputs/expected keys. |
| frontend/src/components/features/vulnerabilities/VulnerabilityTable.tsx | Adds filter drawer section + chip + structured-filter count support for the new filter. |
| frontend/src/components/features/dashboard/AnalystTriageWorkbench.tsx | Updates link search payload to include hasAssessmentOnly. |
| frontend/src/api/vulnerabilities.functions.ts | Extends API function input schema with hasAssessmentOnly. |
Comments suppressed due to low confidence (1)
frontend/src/features/vulnerabilities/list-state.test.ts:28
- The tests only cover
hasAssessmentOnly: false. Add a case that setshasAssessmentOnly: trueand assertsbuildVulnerabilitiesListRequestincludes{ hasAssessmentOnly: true }and thatvulnerabilityQueryKeys.list(...)changes accordingly, so regressions in this new filter wiring are caught.
describe('buildVulnerabilitiesListRequest', () => {
it('drops empty filters while preserving explicit booleans and paging', () => {
expect(
buildVulnerabilitiesListRequest({
search: '',
severity: '',
status: 'Open',
source: '',
ageOperator: '',
ageHours: '',
publicExploitOnly: true,
knownExploitedOnly: false,
activeAlertOnly: true,
presentOnly: false,
hasAssessmentOnly: false,
page: 2,
pageSize: 50,
}),
).toEqual({
status: 'Open',
publicExploitOnly: true,
activeAlertOnly: true,
page: 2,
pageSize: 50,
})
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…eset Addresses PR #91 review feedback: - Adds a VulnerabilitiesController test seeding both an assessed and unassessed vulnerability, verifying HasAssessmentOnly=true returns only the assessed one and the unfiltered call returns both. - Adds a positive list-state test confirming buildVulnerabilitiesListRequest emits hasAssessmentOnly when enabled. - Aligns the filter drawer's "Reset draft" to set presentOnly: true, matching the page-level clear and the route default (searchBooleanTrueSchema). Drawer reset and page-level clear now produce the same applied state. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.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.
Summary
Adds an AI assessment available filter to the vulnerabilities workbench so analysts can narrow the list to entries that already have a generated
VulnerabilityPatchAssessment. Pairs naturally with the in-flight worker — once the timeout fix in #90 lands and the backlog is requeued, this filter lets users zero in on the vulnerabilities that have completed analysis.Backend
VulnerabilityFilterQuerygainsHasAssessmentOnly.VulnerabilitiesControllerfilters viaVulnerabilityPatchAssessments.Any(a => a.VulnerabilityId == v.Id).Frontend
list-state(search type + request builder + query key),VulnerabilityTableprops.AnalystTriageWorkbenchinlinesearch={...}andlist-state.test.tsfixtures updated.Test plan
dotnet test— 866/866 passingnpm run typecheck,npm run lint,npm test— all cleanVulnerabilityPatchAssessments🤖 Generated with Claude Code