Add a GraphQL mutation to set vulnerability findings due dates

What does this MR do and why?

Adds a GraphQL mutation bulkSetVulnerabilityFindingsDueDates to bulk create, update, or remove remediation due dates for vulnerability findings within a project.

This improves API usability and performance by allowing clients to manage due dates for multiple findings in a single request instead of issuing multiple mutations.

  • Bulk create, update, and delete of due dates

  • Supports mixed operations in a single request:

    • Assign due dates
    • Update existing due dates
    • Remove due dates (dueDate: null)
  • Returns aggregated results:

    • assigned — number of due dates created or updated
    • removed — number of due dates deleted
    • skipped — number of due dates skipped because invalid
    • errors — list of errors encountered
  • Enforces limits:

    • Maximum 1000 findings per request
  • Authorization:

    • Requires admin_vulnerability permission on the target project

GraphQL example

mutation {
  bulkSetVulnerabilityFindingsDueDates(
    input: {
      projectFullPath: "group/project"
      updates: [
        {
          findingUuid: "uuid-1"
          dueDate: "2026-04-01"
        }
        {
          findingUuid: "uuid-2"
          dueDate: null
        }
      ]
    }
  ) {
    assigned
    removed
    skipped
    errors {
      findingUuid
      code
      message
    }
  }
}

References

Issue: https://gitlab.com/gitlab-org/gitlab/-/work_items/592225+

Screenshots or screen recordings

Update Delete
Screenshot_2026-04-07_at_16.35.47 Screenshot_2026-04-07_at_16.36.07

How to validate locally

  1. Get a project and finding UUIDs

Rails console:

project = Project.find(
  Vulnerabilities::Finding.distinct.pick(:project_id)
)

uuids = Vulnerabilities::Finding
  .where(project_id: project.id)
  .limit(5)
  .pluck(:uuid)

project.full_path
uuids

  1. Enable feature flag
Feature.enable(:vulnerability_finding_set_due_dates_api, project)
  1. Set due dates (create)
mutation {
  bulkSetVulnerabilityFindingsDueDates(
    input: {
      projectFullPath: "toolbox/gitlab-smoke-tests"
      updates: [
        {
          findingUuid: "0af5209e-8833-58df-9eec-9f7bc8fc4b9a"
          dueDate: "2026-05-01"
        }
        {
          findingUuid: "c3d9db57-7557-5d3c-af2a-99cec6797ae8"
          dueDate: "2026-06-01"
        }
      ]
    }
  ) {
    assigned
    removed
    skipped
    errors {
      findingUuid
      code
      message
    }
  }
}

  1. Verify created
Vulnerabilities::FindingDueDate
  .joins("INNER JOIN vulnerability_occurrences ON vulnerability_occurrences.id = vulnerability_finding_due_dates.vulnerability_occurrence_id")
  .where(vulnerability_occurrences: {
    uuid: [
      "0af5209e-8833-58df-9eec-9f7bc8fc4b9a",
      "c3d9db57-7557-5d3c-af2a-99cec6797ae8"
    ]
  })
  .pluck(:due_date)

  1. Remove due dates (delete)
mutation {
  bulkSetVulnerabilityFindingsDueDates(
    input: {
      projectFullPath: "toolbox/gitlab-smoke-tests"
      updates: [
        {
          findingUuid: "0af5209e-8833-58df-9eec-9f7bc8fc4b9a"
          dueDate: null
        }
        {
          findingUuid: "c3d9db57-7557-5d3c-af2a-99cec6797ae8"
          dueDate: null
        }
      ]
    }
  ) {
    assigned
    removed
    skipped
    errors {
      findingUuid
      code
      message
    }
  }
}

  1. Verify deleted
Vulnerabilities::FindingDueDate
  .joins("INNER JOIN vulnerability_occurrences ON vulnerability_occurrences.id = vulnerability_finding_due_dates.vulnerability_occurrence_id")
  .where(vulnerability_occurrences: {
    uuid: [
      "0af5209e-8833-58df-9eec-9f7bc8fc4b9a",
      "c3d9db57-7557-5d3c-af2a-99cec6797ae8"
    ]
  })

Expected behavior

  • Step 1 → assigned increases
  • Step 3 → removed increases
  • Final query → returns empty (records deleted)
  • No errors for valid UUIDs

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Ugo Nnanna Okeadu

Merge request reports

Loading