Frontend: Switch FP badge visibility to status-based gating

What does this MR do and why?

Frontend changes for Show FP badge for AI-detected flags regardless of confidence score, gated behind vulnerability_flag_status_based_gating feature flag.

Depends on !226166 (merged) (backend + feature flag introduction).

Key changes

Constants:

  • Add FLAG_STATUSES, COMPLETED_DETECTION_STATUSES, PENDING_DETECTION_STATUSES, MANUAL_ORIGIN_PREFIX constants

GraphQL:

  • Add status and origin fields to latestFlag fragment; remove unused description
  • Add status field to dismiss false positive mutation response

Vulnerability detail page (header.vue):

  • Switch detectedAsFalsePositive from confidence-score to status-based check (behind FF)
  • Add hasActiveFpDetection computed to gate AI FP scan re-run buttons

Vulnerability report (vulnerability_list.vue):

  • Switch hasAiExperimentSastFpDetection and shouldShowFalsePositiveBadge to status-based logic (behind FF)
  • Use FLAG_STATUSES and MANUAL_ORIGIN_PREFIX constants

FP badge (ai_possible_fp_badge.vue):

  • Add pending (info) and failed (danger) badge variants
  • Hide confidence details for pending/failed states

FP details (false_positive_details.vue):

  • Add pending and failed state rendering
  • Gate dismiss button on completed detection status (behind FF)

Vulnerability details (vulnerability_details.vue):

  • Switch shouldShowFalsePositiveDuoWorkflowDetails to status-based logic (behind FF)

How to set up and validate locally

  1. Enable feature flags:

    Feature.enable(:ai_experiment_sast_fp_detection)
    Feature.enable(:vulnerability_flag_status_based_gating)
  2. Create test data with various statuses:

    project = Project.find_by_full_path('YOUR_PROJECT_PATH')
    finding = project.vulnerabilities.first.finding
    
    # Pending scan
    finding.vulnerability_flags.create!(
      flag_type: :false_positive, origin: 'ai_sast_fp_detection',
      confidence_score: 0.0, status: :not_started,
      description: 'Scan not started', project_id: project.id
    )
    
    # Completed scan with 0.0 confidence (the bug this fixes)
    finding.vulnerability_flags.create!(
      flag_type: :false_positive, origin: 'ai_sast_fp_detection',
      confidence_score: 0.0, status: :detected_as_not_fp,
      description: 'Not a false positive', project_id: project.id
    )
  3. Verify:

    • Pending flags show blue "FP Scanning" badge
    • Failed flags show red "FP Scan Failed" badge
    • Completed flags with confidence 0.0 show "Not an FP" badge (previously hidden)
    • Dismissed/manual-origin flags show no AI badge
    • Old behavior preserved when vulnerability_flag_status_based_gating is disabled

Screenshots / screen recordings

https://www.youtube.com/watch?v=0ZJsr00pLXs

MR acceptance checklist

  • This MR does not add a migration
  • Frontend changes have Jest spec coverage
  • Changes are behind a feature flag
  • GraphQL query complexity stays within budget
Edited by Illya Klymov

Merge request reports

Loading