Migrate policy store createPolicy to the GraphQL mutation

What does this MR do and why?

Summary

Policy creation has been migrated from a direct REST API call to a GraphQL mutation (governPolicyCreate). Previously, creating a policy sent an HTTP POST request to the organization's policy store endpoint; now it sends a GraphQL mutation instead, which is more consistent with how the rest of the application communicates with the backend.

As part of this change, a new custom error class (PolicyStoreMutationError) was introduced to cleanly represent validation failures returned by the GraphQL mutation (e.g., duplicate names or invalid rules). This allows the error-handling logic to treat GraphQL validation errors the same way it previously treated REST API 400 errors, so users still see meaningful error messages when something goes wrong.

The old REST-based createPolicyStorePolicy method has been removed from the API layer since it is no longer needed. Tests have been updated throughout to reflect the new GraphQL-based flow and the new error type.

Closes https://gitlab.com/gitlab-org/gitlab/-/issues/617791

References

Screenshots or screen recordings

No UI changes — behavior-preserving transport migration.

How to set up and validate locally

The feature is an experiment, gated by the security_policies_v2 feature flag (instance-level), the policy_store_experiment_enabled application setting, and an Ultimate license.

  1. In rails console: Feature.enable(:security_policies_v2) and ApplicationSetting.current.update!(policy_store_experiment_enabled: true) (Ultimate license required).
  2. Visit a group's Secure > Policies policy store list and create a new policy through the wizard (name, trigger, at least one rule), then Save.
  3. Expected: the browser's network tab shows a governPolicyCreate request to /api/graphql (no POST to /api/v4/organizations/.../security/policy_store), and the editor returns to the list with a "Policy ... was created." confirmation.
  4. Create another policy with the same name. Expected: an inline "A policy with this name already exists." error on the name field, no page alert.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist.

Verification

Jest: Test Suites: 30 passed, 30 total · Tests: 494 passed, 494 total (full policy_store + api_spec run).

Adversarial review verdict: pass with findings (all findings addressed or recorded as follow-ups):

  • Post-create redirect to the new policy's detail view is a possible follow-up now that the mutation returns the id.
  • The wizard's canSave gating is what keeps the mutation's non-null arguments satisfied.
  • The REST create endpoint now has no frontend caller and is removed with the update/delete migrations.
Edited by Artur Fedorov

Merge request reports

Loading
Loading