# Vulnerability Filtering Design for getAllVulnerabilities

## Executive Summary

Design specification for adding AI-friendly filtering to `getAllVulnerabilities` in `AssessService.java:414`. The current implementation returns ALL vulnerabilities across all applications, which can easily exceed AI context windows. This design provides a clean, intuitive filtering interface that helps AI agents retrieve only relevant vulnerabilities.

## Current State Analysis

### Existing Implementation
- Method: `getAllVulnerabilities(Integer page, Integer pageSize)` at line 414
- Current behavior: Returns ALL vulnerabilities with only pagination support
- Problem: Large organizations can have thousands of vulnerabilities, overwhelming AI context windows
- Pagination alone is insufficient - AI needs semantic filtering

### Existing Patterns in Codebase

**Pattern 1: Multiple Optional Parameters** (ADRService)
```java
public List<AttackSummary> getAttacksFiltered(
    String quickFilter,
    String keyword,
    Boolean includeSuppressed,
    Boolean includeBotBlockers,
    Boolean includeIpBlacklist,
    Integer limit,
    Integer offset,
    String sort
)
```
**Pros**: Simple, each parameter is obvious
**Cons**: Long parameter list, unclear which combinations are valid

**Pattern 2: Filter Object** (AttacksFilterBody)
```java
public class AttacksFilterBody {
    private String quickFilter = "ALL";
    private List<String> severities;
    private List<String> statusFilter;
    // ... many more fields
}
```
**Pros**: Extensible, clean method signature
**Cons**: AI needs to know object structure, more verbose in tool descriptions

## Design Decision: Hybrid Approach

**Use optional parameters** for the most common, AI-friendly filters. This balances simplicity with power.

### Rationale
1. **AI Discoverability**: Parameters appear directly in tool description
2. **Type Safety**: Java types guide AI to provide correct values
3. **Natural Language Mapping**: Parameter names map naturally to AI queries like "show me critical vulnerabilities"
4. **Backward Compatible**: Existing pagination parameters remain unchanged

## Proposed Method Signature

```java
@Tool(name = "list_all_vulnerabilities", description = """
    Gets vulnerabilities across all applications with optional filtering.

    Filters (all optional):
    - severities: Filter by severity level(s). Options: CRITICAL, HIGH, MEDIUM, LOW, NOTE.
                  Comma-separated for multiple (e.g., "CRITICAL,HIGH").
                  Default: Returns all severities.
    - statuses: Filter by vulnerability status(es). Options: Reported, Suspicious, Confirmed, Remediated, Fixed.
                Comma-separated for multiple (e.g., "Reported,Confirmed").
                Default: Returns Reported, Suspicious, and Confirmed (excludes Fixed and Remediated - focus on actionable items).
    - appId: Filter to a specific application ID.
    - vulnTypes: Filter by vulnerability type/rule name(s) (e.g., "sql-injection", "xss-reflected", "path-traversal").
                 Comma-separated for multiple (e.g., "sql-injection,xss-reflected").
                 Default: Returns all vulnerability types.
    - environments: Filter by server environment(s). Options: DEVELOPMENT, QA, PRODUCTION.
                    Comma-separated for multiple (e.g., "PRODUCTION,QA").
                    Default: Returns all environments.
    - lastSeenAfter: Only include vulnerabilities with activity after this date (ISO format: YYYY-MM-DD or epoch timestamp).
                     IMPORTANT: Filters on LAST ACTIVITY DATE (lastTimeSeen), not discovery date.
    - lastSeenBefore: Only include vulnerabilities with activity before this date (ISO format: YYYY-MM-DD or epoch timestamp).
                      IMPORTANT: Filters on LAST ACTIVITY DATE (lastTimeSeen), not discovery date.
    - vulnTags: Filter by vulnerability-level tag(s). Comma-separated for multiple (e.g., "SmartFix Remediated,reviewed").
                IMPORTANT: Filters on VULNERABILITY TAGS, not application tags.
                Use case: Query vulnerabilities with specific tags like "SmartFix Remediated" to find SmartFix-remediated issues.
                Default: Returns all vulnerability tags.

    Pagination: page (1-based, default: 1), pageSize (default: 50, max: 100)

    Examples:
    - Critical vulnerabilities only: severities="CRITICAL"
    - High-priority open issues: severities="CRITICAL,HIGH", statuses="Reported,Confirmed"
    - Production vulnerabilities: environments="PRODUCTION"
    - Recent activity: lastSeenAfter="2025-01-01"
    - Production critical issues with recent activity: environments="PRODUCTION", severities="CRITICAL", lastSeenAfter="2025-01-01"
    - Specific app's SQL injection issues: appId="abc123", vulnTypes="sql-injection"
    - SmartFix remediated vulnerabilities: vulnTags="SmartFix Remediated", statuses="Remediated"
    - Reviewed critical vulnerabilities: vulnTags="reviewed", severities="CRITICAL"

    Returns pagination metadata including totalItems (when available) and hasMorePages.
    Check 'message' field for validation warnings or empty result info.
    """
)
public PaginatedResponse<VulnLight> getAllVulnerabilities(
    Integer page,
    Integer pageSize,
    String severities,
    String statuses,
    String appId,
    String vulnTypes,
    String environments,
    String lastSeenAfter,
    String lastSeenBefore,
    String vulnTags
) throws IOException
```

## Pagination Specification Adherence

The implementation must strictly follow the `PaginatedResponse` contract:

```java
/**
 * @param items The data for the current page (never null, empty list if no results)
 * @param page The page number returned (1-based, always ≥ 1)
 * @param pageSize Items per page used for this response (1-100)
 * @param totalItems Total count across all pages (null if unavailable or expensive to compute)
 * @param hasMorePages true if additional pages exist beyond this page
 * @param message Optional informational message for the AI (validation warnings, empty result explanations, etc.)
 */
```

**Key Requirements**:
- **Page numbers**: 1-based (not 0-based), minimum value is 1
- **Page size**: Range 1-100, default 50, clamp invalid values with warning in message
- **Items**: Never null, return empty list if no results
- **totalItems**: Can be null if not available from SDK, otherwise provide accurate count
- **hasMorePages**: Calculate based on totalItems if available, otherwise use heuristic (full page = more likely)
- **message**: Use for filter info, validation warnings, empty results explanation

**Pagination with Filters**:
- Filters apply before pagination
- totalItems reflects filtered count, not total vulnerabilities
- hasMorePages indicates more filtered results exist
- message should note when filters significantly reduce results

## Filter Specifications

### 1. Severity Filter (`severities`)

**Type**: `String` (comma-separated list)

**Valid Values**:
- `CRITICAL` - Most severe vulnerabilities
- `HIGH` - High severity issues
- `MEDIUM` - Medium severity issues
- `LOW` - Low severity issues
- `NOTE` - Informational findings

**Default Behavior**: No filtering (returns all severities)

**AI Guidance in Description**:
- Examples showing single and multiple values
- Clear mapping to security priority
- Suggest starting with CRITICAL,HIGH for first-time users

**Implementation Notes**:
- Split comma-separated string into list
- Case-insensitive matching
- Invalid values should log warning and be ignored (don't fail the entire request)
- Pass to SDK's TraceFilterForm if supported, otherwise filter in-memory

### 2. Status Filter (`statuses`)

**Type**: `String` (comma-separated list)

**Valid Values**:
- `Reported` - Newly discovered, not yet triaged
- `Suspicious` - Flagged for review
- `Confirmed` - Verified as real vulnerability
- `Remediated` - Fix has been deployed
- `Fixed` - Vulnerability no longer detected

**Default Behavior**: Return `Reported`, `Suspicious`, and `Confirmed` (exclude `Remediated` and `Fixed`)

**Rationale for Default**:
- Most AI use cases focus on actionable vulnerabilities
- Including fixed/remediated issues adds noise
- Users can explicitly request them if needed
- Default behavior helps reduce context window usage

**AI Guidance in Description**:
- Explain default excludes fixed items
- Show examples of single and multiple status filtering
- Suggest "Reported,Confirmed" for open verified issues
- Note that combining with severity is common

**Implementation Notes** (APPROVED):
- Split comma-separated string into list
- Case-insensitive matching
- **No `statuses` parameter provided** → Use smart defaults (exclude Fixed, Remediated)
- **`statuses` parameter provided** → Use exactly what's specified
- When smart defaults are used, add message: "Showing actionable vulnerabilities only (excluding Fixed and Remediated). To see all statuses, specify statuses parameter explicitly."
- Map to SDK's status filter if available
- Note: Removes null vs empty string ambiguity - if parameter is provided, use it exactly as specified

### 3. Application ID Filter (`appId`)

**Type**: `String`

**Valid Values**: Any valid Contrast application ID

**Default Behavior**: No filtering (all applications)

**AI Guidance in Description**:
- Reference other tools like `list_applications_with_name` to get IDs
- Useful for scoping to a single app
- Combines well with severity/status filters

**Implementation Notes**:
- When appId is provided, use app-specific API (`listVulnsByAppId`) instead of org-level API
- More efficient than fetching all and filtering
- Better session metadata support at app level

### 4. Vulnerability Type Filter (`vulnTypes`)

**Type**: `String` (comma-separated list)

**Valid Values**: Any vulnerability type/rule name (e.g., "sql-injection", "xss-reflected", "path-traversal", "crypto-bad-mac", "cmd-injection")

**Default Behavior**: No filtering (all vulnerability types)

**Common Vulnerability Types**:
- `sql-injection` - SQL Injection vulnerabilities
- `xss-reflected` - Reflected Cross-Site Scripting
- `xss-stored` - Stored Cross-Site Scripting
- `path-traversal` - Path Traversal vulnerabilities
- `cmd-injection` - Command Injection
- `crypto-bad-mac` - Cryptography issues
- `trust-boundary-violation` - Trust boundary violations
- And many more based on Contrast rule catalog

**Naming Decision** (APPROVED):
- Keep `vulnTypes` name - more AI-friendly than `ruleNames`
- Tool description clarifies it maps to rule names
- Examples show clear usage patterns

**AI Guidance in Description**:
- List top 10-15 common vulnerability type examples in tool description for quick reference
- Useful for focusing on specific vulnerability classes
- Comma-separated for multiple types
- Matches against the `type` field in VulnLight
- Note: "For a complete list of all available vulnerability types, use the list_vulnerability_types tool"
- **Common types to include in description**:
  - sql-injection, xss-reflected, xss-stored, path-traversal, cmd-injection
  - crypto-bad-mac, crypto-bad-ciphers, trust-boundary-violation, xxe
  - untrusted-deserialization, csrf, ssrf, ldap-injection, xpath-injection

**Implementation Notes** (APPROVED):
- Split comma-separated string into list with **robust parsing**:
  ```java
  // Trim whitespace and filter out empty strings
  List<String> types = Arrays.stream(vulnTypesParam.split(","))
      .map(String::trim)
      .filter(s -> !s.isEmpty())
      .collect(Collectors.toList());
  ```
- **Exact matching (not partial)** for predictability and performance
- Case-insensitive matching
- Filter VulnLight results where `type` field matches any value in list
- **SDK support research required** - see mcp-21 for investigation
- Log when no matches found for any type

### 5. Environment Filter (`environments`) ⭐ USER EXPLICITLY REQUESTED

**Type**: `String` (comma-separated list)

**Valid Values**:
- `DEVELOPMENT` - Development environment
- `QA` - QA/Testing environment
- `PRODUCTION` - Production environment

**Default Behavior**: No filtering (all environments)

**Rationale**: User explicitly requested this filter. Critical for focusing on production vulnerabilities vs dev/test issues. Can reduce result sets by 70%+ in multi-environment organizations.

**AI Guidance in Description**:
- Clear examples: "Show me production critical vulnerabilities"
- Common use case: Focus on production-only issues
- Combines well with severity filters for "production critical" queries
- Note that environment is determined by server configuration

**Implementation Notes** (APPROVED):
- Split comma-separated string into list with **robust parsing**:
  ```java
  // Trim whitespace and filter out empty strings
  List<String> envs = Arrays.stream(environmentsParam.split(","))
      .map(String::trim)
      .filter(s -> !s.isEmpty())
      .collect(Collectors.toList());
  ```
- Map to SDK's `ServerEnvironment` enum
- Use SDK's native support: `TraceFilterForm.setEnvironments(EnumSet<ServerEnvironment>)`
- Case-insensitive matching, convert to uppercase before valueOf()
- Invalid values should log warning and be ignored (don't fail entire request)
- EnumSet conversion pattern:
  ```java
  EnumSet<ServerEnvironment> envSet = EnumSet.noneOf(ServerEnvironment.class);
  envs.forEach(e -> {
      try {
          envSet.add(ServerEnvironment.valueOf(e.toUpperCase()));
      } catch (IllegalArgumentException ex) {
          logger.warn("Invalid environment: {}", e);
      }
  });
  if (!envSet.isEmpty()) {
      filterForm.setEnvironments(envSet);
  }
  ```

### 6. Time-Based Filter (`lastSeenAfter`, `lastSeenBefore`)

**Type**: `String` (ISO date format YYYY-MM-DD or epoch timestamp in milliseconds)

**Valid Values**: Any valid ISO 8601 date string or epoch timestamp

**Default Behavior**: No filtering (all time ranges)

**IMPORTANT**: These filters operate on **LAST ACTIVITY DATE** (`lastTimeSeen`), **NOT discovered date** (`firstTimeSeen`).

**Rationale**: Time-based filtering is essential for "recent vulnerabilities" queries and focusing on active issues. High impact on context window reduction.

**AI Guidance in Description**:
- **CRITICAL**: Explicitly state these filter on LAST ACTIVITY, not discovery date
- Examples: "Show vulnerabilities with activity in the last 30 days"
- Useful for: Recent activity, active vulnerabilities, time-windowed analysis
- Accepts both ISO dates (YYYY-MM-DD) and epoch timestamps
- `lastSeenAfter` = vulnerabilities with activity AFTER this date
- `lastSeenBefore` = vulnerabilities with activity BEFORE this date

**Implementation Notes** (APPROVED):
- Parse date string to Date object:
  ```java
  private Date parseDate(String dateStr) {
      if (dateStr == null || dateStr.isEmpty()) return null;
      try {
          // Try parsing as epoch timestamp first
          return new Date(Long.parseLong(dateStr));
      } catch (NumberFormatException e) {
          // Try ISO date format
          try {
              return Date.from(LocalDate.parse(dateStr).atStartOfDay(ZoneId.systemDefault()).toInstant());
          } catch (DateTimeParseException ex) {
              logger.warn("Invalid date format: {}", dateStr);
              return null;
          }
      }
  }
  ```
- Map to SDK's startDate/endDate: `TraceFilterForm.setStartDate(Date)`, `setEndDate(Date)`
- **SDK limitation**: `TraceFilterForm` does NOT expose `timestampFilter` field
- Without `timestampFilter` control, defaults to `TraceTimestampField.LAST` (filters on lastTimeSeen)
- Add message to PaginatedResponse: "Time filters apply to LAST ACTIVITY DATE (lastTimeSeen), not discovery date"
- **Future enhancement**: If SDK adds `timestampFilter` support, expose both discovered date and last seen date filtering

### 7. Vulnerability Tags Filter (`vulnTags`)

**Type**: `String` (comma-separated list)

**Valid Values**: Any vulnerability-level tag strings (e.g., "SmartFix Remediated", "reviewed", "false-positive")

**Default Behavior**: No filtering (all vulnerability tags)

**IMPORTANT**: This filters on **VULNERABILITY TAGS** (tags applied to individual vulnerabilities), NOT application tags. For application-level filtering, use the `appId` parameter to target specific applications.

**Rationale**: Vulnerability-level tagging enables tracking of remediation workflows, review status, and special categorizations. Key use case is identifying SmartFix-remediated vulnerabilities.

**Primary Use Cases**:
1. **SmartFix Remediation Tracking**: Query all vulnerabilities remediated by SmartFix
   - Example: `vulnTags="SmartFix Remediated"`, `statuses="Remediated"`
2. **Review Workflow**: Track vulnerabilities that have been reviewed
   - Example: `vulnTags="reviewed"`, `statuses="Confirmed"`
3. **False Positive Management**: Find vulnerabilities tagged as false positives
   - Example: `vulnTags="false-positive"`

**AI Guidance in Description**:
- **CRITICAL**: Explicitly state these are vulnerability tags, not application tags
- Examples:
  - "Show me SmartFix remediated vulnerabilities"
  - "Find reviewed critical vulnerabilities"
- Useful for: Remediation tracking, review workflows, special categorizations
- Comma-separated for multiple tags
- Tags are applied at the vulnerability level in Contrast

**Implementation Notes** (APPROVED):
- Split comma-separated string into list with **robust parsing**:
  ```java
  // Trim whitespace and filter out empty strings
  List<String> tags = Arrays.stream(vulnTagsParam.split(","))
      .map(String::trim)
      .filter(s -> !s.isEmpty())
      .collect(Collectors.toList());
  ```
- Use SDK's native support: `TraceFilterForm.setFilterTags(List<String>)`
- Case-sensitive matching (vulnerability tags are case-sensitive in Contrast)
- Pass directly to SDK - no enum conversion needed
- SDK maps to: `vulnerabilityTagDao.findVulnerabilityIDsByApplicationAndFreeFormTag()`
- **Works identically for both per-application and org-level queries**:
  - Per-application: Calls DAO method once for that application
  - Org-level (all apps): Loops through all allowed applications, calls same DAO method for each, merges results
  - Both filter on FREE_FORM tags only, same behavior
- Log when tags filter produces no results
- **Common tag values:**

  **System-Generated Tags:**
  - **"SmartFix Remediated"** - Applied by SmartFix service after a SmartFix-generated PR is merged
    - When applied: After successful merge of SmartFix pull request that fixes the vulnerability
    - Common query: `vulnTags="SmartFix Remediated"` + `statuses="Remediated"`
    - Use case: Track SmartFix remediation effectiveness and outcomes

  **User-Defined Tags:**
  - Tags are free-form strings created by users for workflow management
  - No predefined constants or required values in TeamServer
  - Organizations define their own tagging taxonomies based on their workflows
  - Common use cases include: review status tracking, team assignment, false positive marking, risk acceptance

  **Tag Architecture Notes:**
  - **Case-sensitive**: Tags are case-sensitive in Contrast
  - **Max length**: 255 characters per tag (truncated automatically)
  - **Tag type**: Only filters FREE_FORM tags (user-defined and system-generated like "SmartFix Remediated")
  - **Note**: TeamServer also has APPLICATION_VERSION tags (e.g., "1.2.3"), but these are NOT filterable via vulnTags

## Default Behavior Philosophy

### When No Filters Provided
Return all vulnerabilities with pagination - **same as current behavior** for backward compatibility.

### Recommended AI Defaults (in tool description)
Suggest in examples that AI agents typically want:
- `severities="CRITICAL,HIGH"` - Focus on important issues
- Default status filtering automatically applied (excludes Fixed and Remediated) - Focus on actionable items
- Can override with explicit `statuses` parameter (e.g., "Reported,Suspicious,Confirmed,Fixed,Remediated" for all)
- Reasonable page size (25-50) - Avoid context overload
- Combine filters for precision (e.g., high severity + specific vuln types)

### Empty Results Handling
- Clear message when filters produce no results
- Suggest broadening filters if appropriate
- Distinguish between "no vulnerabilities exist" vs "no vulnerabilities match filters"

## Implementation Plan

### Phase 1: Core Filtering
1. Add four new optional parameters to method signature
2. Update @Tool description with comprehensive guidance
3. Implement parameter parsing and validation
4. Add filter logic using SDK capabilities where possible
5. Add in-memory filtering for unsupported SDK filters

### Phase 2: SDK Integration
1. Check TraceFilterForm capabilities in Contrast SDK
2. Map filters to SDK where supported:
   - Severity mapping to SDK severity filter
   - Status mapping to SDK status filter
   - Application ID optimization (use app-specific API)
3. Use SDK filtering to reduce data transfer and improve performance

### Phase 3: Testing & Validation
1. Test with real Contrast instance
2. Verify filter combinations work correctly
3. Test edge cases (invalid values, empty results, etc.)
4. Measure performance improvement with filters
5. Validate AI agents can successfully use the filters

## Example AI Interactions

### Example 1: Security Audit
**AI Query**: "Show me all critical and high severity vulnerabilities that are confirmed"

**Tool Call**:
```json
{
  "severities": "CRITICAL,HIGH",
  "statuses": "Confirmed",
  "page": 1,
  "pageSize": 50
}
```

### Example 2: Application Focus
**AI Query**: "What are the open security issues in the payment-service app?"

**Tool Call Sequence**:
1. `list_applications_with_name(app_name="payment-service")` → get appId
2. `getAllVulnerabilities(appId="xyz", statuses="Reported,Suspicious", page=1, pageSize=50)`

### Example 3: Vulnerability Class Research
**AI Query**: "Show me all SQL injection and XSS vulnerabilities"

**Tool Call**:
```json
{
  "vulnTypes": "sql-injection,xss-reflected,xss-stored",
  "page": 1,
  "pageSize": 100
}
```

### Example 4: Combined Filtering
**AI Query**: "Show me critical command injection and path traversal issues that need attention"

**Tool Call**:
```json
{
  "severities": "CRITICAL",
  "vulnTypes": "cmd-injection,path-traversal",
  "statuses": "Reported,Confirmed",
  "page": 1,
  "pageSize": 50
}
```

## Migration & Backward Compatibility

### Existing Callers
- All new parameters are optional
- Existing calls with just pagination work unchanged
- No breaking changes

### Documentation Updates
- Update CLAUDE.md with filter examples
- Add filter guidance to README
- Include examples in tool description

## Success Metrics

1. **Reduced Context Usage**: Filtered queries return 50-90% fewer results
2. **AI Effectiveness**: AI can retrieve relevant vulnerabilities in 1-2 queries instead of multiple pages
3. **Discoverability**: AI agents successfully use filters without explicit instruction
4. **Performance**: Filtered queries execute in <2 seconds for typical organizations

## Open Questions & Future Enhancements

### Additional Filters - DECISIONS MADE (mcp-22)

**APPROVED for Initial Implementation:**
1. ✅ **environments** - Filter by server environment (DEVELOPMENT, QA, PRODUCTION) - USER EXPLICITLY REQUESTED
   - **Rationale**: User request + high value for production-focused queries
2. ✅ **lastSeenAfter / lastSeenBefore** - Time-based filtering on last activity date
   - **Rationale**: Essential for "recent vulnerabilities" use cases
   - **Note**: Filters on lastTimeSeen, not firstTimeSeen (discovered date) due to SDK limitations
   - **Future enhancement**: Add discoveredAfter/Before when SDK exposes timestampFilter field
3. ✅ **vulnTags** - Vulnerability-level tag filtering (renamed from filterTags)
   - **Rationale**: Enables SmartFix remediation tracking and review workflows
   - **Key Use Case**: Query "SmartFix Remediated" tagged vulnerabilities
   - **IMPORTANT**: Filters on VULNERABILITY tags, not application tags

**DEFERRED for Future Iterations:**
- **License**: Filter SCA vulnerabilities by license type - Niche use case, SCA-specific
- **Language**: Filter by application language - Not available in SDK, would require in-memory filtering
- **Servers** (`serverIds`): Filter by server/host - Too specific, users typically filter by app or environment

### Design Questions - RESOLVED
1. Should we add a "preset" filter (e.g., "critical_open", "recent_high")?
   - **Decision**: Not in initial design, evaluate after usage data

2. Should empty `statuses` filter mean "all" or "smart defaults"?
   - **Decision APPROVED**:
     - No parameter provided → smart defaults (exclude Fixed, Remediated)
     - Parameter provided → use exactly as specified
     - Removes null vs empty string ambiguity

3. Should vulnTypes use partial matching or exact matching?
   - **Decision APPROVED**: Exact matching for predictability and performance

4. Is `vulnTypes` the right parameter name?
   - **Decision APPROVED**: Yes, more AI-friendly than alternatives like `ruleNames`

5. How should AI discover available vulnerability types?
   - **Decision APPROVED**: Hybrid approach (Option 3)
   - **Rationale**: Balances discoverability with completeness
   - **Implementation**:
     1. Add top 10-15 common types to getAllVulnerabilities tool description
     2. Create new tool: list_vulnerability_types
     3. Use SDK's getRules(organizationId) API (endpoint: /ng/{orgId}/rules)
     4. Extract and return sorted list of rule names
   - **Benefits**:
     - Zero latency for common cases (AI sees popular types immediately)
     - Always current (dynamic API provides complete, up-to-date list)
     - AI-friendly (clear separation between "quick reference" and "complete catalog")
     - Minimal overhead (only 1 extra tool, called rarely)
     - Leverages existing SDK (no custom endpoint needed)

## Appendix: Contrast API Capabilities

### SDK TraceFilterForm Fields (from Contrast SDK)
- `offset`, `limit` - Pagination (already implemented)
- `severities` - Severity filter (to be implemented)
- `status` - Status filter (to be implemented)
- `appId` - Handled via different API endpoint
- `filterText` - Text search (could map to `rule` filter)

### VulnLight Model Fields (data available for filtering)
```java
record VulnLight(
    String title,
    String type,           // Rule name
    String vulnID,
    String severity,       // CRITICAL, HIGH, MEDIUM, LOW, NOTE
    List<SessionMetadata> sessionMetadata,
    String lastSeenDate,
    long lastSeenTime,
    String status,         // Reported, Suspicious, Confirmed, etc.
    Long firstTimeSeen,
    Long closedTime
)
```

## Implementation Checklist

### Prerequisites (Blocking Dependencies)
- [ ] **mcp-21**: Verify SDK support for rule/vulnType filtering in TraceFilterForm
- [ ] **mcp-22**: Determine additional filters to add (environment, etc.)
- [x] **mcp-23**: Add ability to discover available vulnerability types
  - Decision: Hybrid approach with new list_vulnerability_types tool
  - Uses SDK's getRules(organizationId) method
  - Returns sorted list of rule names

### Core Implementation (mcp-2)
- [ ] Add optional parameters to method signature (based on mcp-22 decisions)
  - [ ] severities (comma-separated)
  - [ ] statuses (comma-separated, smart defaults)
  - [ ] appId (single value)
  - [ ] vulnTypes (comma-separated, exact matching)
  - [ ] environments (comma-separated, EnumSet conversion)
  - [ ] lastSeenAfter (ISO date or epoch timestamp)
  - [ ] lastSeenBefore (ISO date or epoch timestamp)
  - [ ] vulnTags (comma-separated, VULNERABILITY tags not application tags)
- [ ] Update @Tool description with comprehensive examples and guidance
- [ ] Implement **robust comma-separated parsing** with whitespace trimming:
  ```java
  Arrays.stream(param.split(","))
      .map(String::trim)
      .filter(s -> !s.isEmpty())
      .collect(Collectors.toList());
  ```
- [ ] Add parameter validation with helpful error messages
- [ ] Implement severity filtering (SDK and/or in-memory) - comma-separated list
- [ ] Implement status filtering with **approved smart defaults**:
  - [ ] No parameter provided → exclude Fixed and Remediated
  - [ ] Parameter provided → use exactly as specified
  - [ ] Add message when smart defaults used: "Showing actionable vulnerabilities only (excluding Fixed and Remediated). To see all statuses, specify statuses parameter explicitly."
- [ ] Implement appId routing to app-specific API
- [ ] Implement vulnerability type filtering:
  - [ ] Comma-separated list, **exact matching** (case-insensitive)
  - [ ] Use SDK filtering if supported (per mcp-21), otherwise in-memory
- [x] Implement vulnerability type discovery tool (mcp-23):
  - [x] Create list_vulnerability_types tool in AssessService
  - [x] Call SDK's getRules(organizationId) method
  - [x] Extract rule names and return sorted list
  - [x] Add common vulnerability types to getAllVulnerabilities tool description
  - [x] Build and test implementation - all tests passing
- [ ] Implement environment filtering:
  - [ ] Comma-separated list parsing with robust whitespace handling
  - [ ] Map to EnumSet<ServerEnvironment> with case-insensitive conversion
  - [ ] Use SDK native support: TraceFilterForm.setEnvironments()
  - [ ] Log warnings for invalid environment values
- [ ] Implement time-based filtering (lastSeenAfter/lastSeenBefore):
  - [ ] Parse ISO date strings (YYYY-MM-DD) and epoch timestamps
  - [ ] Map to SDK's setStartDate()/setEndDate()
  - [ ] Add PaginatedResponse message: "Time filters apply to LAST ACTIVITY DATE (lastTimeSeen), not discovery date"
  - [ ] Log warnings for invalid date formats
- [ ] Implement vulnerability tags filtering (vulnTags):
  - [ ] Comma-separated list parsing with robust whitespace handling
  - [ ] Use SDK native support: TraceFilterForm.setFilterTags()
  - [ ] Case-sensitive matching (vulnerability tags are case-sensitive in Contrast)
  - [ ] Maps to vulnerabilityTagDao.findVulnerabilityIDsByApplicationAndFreeFormTag()
  - [ ] Add message clarifying these are VULNERABILITY tags, not application tags
  - [ ] Log when tags filter produces no results
- [ ] Add logging for filter usage and results
- [ ] Update PaginatedResponse message with filter info (which filters applied, counts)
- [ ] Ensure pagination spec compliance (1-based pages, 1-100 pageSize, proper hasMorePages)
- [ ] Test all filter combinations
- [ ] Test edge cases:
  - [ ] Invalid input, no results
  - [ ] Whitespace in comma-separated values: "CRITICAL, HIGH" vs "CRITICAL,HIGH"
  - [ ] Invalid values mixed with valid: "CRITICAL,INVALID,HIGH"
  - [ ] Empty strings in lists: "CRITICAL,,HIGH"
- [ ] Test smart defaults behavior for statuses (no param vs param provided)
- [ ] Test comma-separated parsing for all list filters
- [ ] Test new filters specifically:
  - [ ] Environment filter with valid values (PRODUCTION, QA, DEVELOPMENT)
  - [ ] Environment filter with invalid values (should log warning, not fail)
  - [ ] Time filter with ISO dates (2025-01-01)
  - [ ] Time filter with epoch timestamps
  - [ ] Time filter with invalid formats (should log warning, return null)
  - [ ] vulnTags with case-sensitive matching (test "SmartFix Remediated" tag)
  - [ ] vulnTags combined with statuses (e.g., "SmartFix Remediated" + "Remediated")
  - [ ] Combined filters: environments + lastSeenAfter + severities
  - [ ] SmartFix use case: vulnTags="SmartFix Remediated" + statuses="Remediated"
- [ ] Test performance with real Contrast data
- [ ] Update CLAUDE.md with examples
- [ ] Get feedback from AI testing

## Conclusion

This design provides a clean, intuitive filtering interface that:
1. **AI agents can discover and use naturally** through clear parameter names
2. **Reduces context window pressure** by returning only relevant vulnerabilities
3. **Maintains backward compatibility** with existing code
4. **Follows existing codebase patterns** for consistency
5. **Provides sensible defaults** while remaining flexible

The hybrid approach of optional parameters strikes the right balance between simplicity (for AI) and power (for advanced filtering).
