Remove secrets_manager_paid_experience flag

What does this MR do and why?

Related: MR 6 of 6 removing Secrets Manager feature flags for GA. Targets master. All earlier MRs in the series are merged. Related to https://gitlab.com/groups/gitlab-org/-/work_items/21755 and !239358 (merged). Replaces the exploratory all-flags MR !254806 (closed), which will be closed once this one is up.

All MRs in this series
  1. secrets_manager, group_secrets_manager: !259222 (merged) (merged)
  2. Enrollment flags (secrets_manager_namespace_enrollment, secrets_manager_instance_enrollment): !260090 (merged) (merged)
  3. secrets_manager_async_audit_logs: !260091 (merged) (merged)
  4. Billing event flags (secrets_manager_emit_secret_read_events, secrets_manager_emit_secret_stored_events): !260092 (merged) (merged)
  5. secrets_manager_denial_telemetry: !260094 (merged) (merged)
  6. secrets_manager_paid_experience: !260110 (merged) (this MR)

secrets_manager_api_access stays in beta and default disabled for GA, so it is not part of this series.

Problem

With secrets_manager_paid_experience off (the default, so all of Self-Managed), every entitlement check is skipped. This covers policies, the GraphQL write concern, the service gate, the CI runner payload, job scheduling, trial and add-on mutations, the entitlement GraphQL field, the sidebar, and the nav badge. Self-Managed still behaves like the free beta.

Solution

Backend

  • Remove every flag check. Entitlement checks always run now.
  • EE::ProjectPolicy and EE::GroupPolicy drop the secrets_manager_entitlement_aware condition from their rules.
  • EntitlementGate, EE::Ci::RegisterJobService, and EffectiveCapabilitiesService drop the flag guard.
  • NamespaceEnrollmentService: enroll always writes beta: false. Unenroll always soft-disables the record. There is no more destroy path or "Enrollment not found." response.
  • InstanceEnrollmentService: enroll always writes secrets_manager_instance_beta_enrolled: false.
  • SaaS top-level groups keep the implicit grant before enrollment unless opted out. The SaaS guard stays, only the flag check is dropped.
  • NavBadge.visible? no longer takes root_namespace.
  • Controllers drop push_frontend_feature_flag calls. The secrets controllers lose check_secrets_enabled!, since it became a no-op. Two helper methods that became unused are removed: secrets_manager_available_and_active_for_group? and secrets_manager_available_and_active_for_project?.
  • Mutations start_trial, enable_add_on, and refresh_entitlement no longer raise when the flag is off.

Frontend

  • glFeatures.secretsManagerPaidExperience checks removed from 7 Vue components.
  • The beta provisioning toggle in secrets_manager_settings.vue is removed, since it only existed in the beta experience. Its now-unused enable/disable config entries, constants, and the billing alert in the settings components go with it.
  • 7 POT strings removed.

CI

  • Remove secrets_manager_paid_experience from QA_FEATURE_FLAGS in cng-secrets-manager. secrets_manager_api_access=enabled stays, because that flag stays in beta and default disabled.

Docs

  • The developer docs (enrollment.md, fulfillment.md, services.md) no longer describe the flag or the beta behavior when it was off.
  • The experimental GraphQL reference (doc/api/graphql/reference/experimental/objects.md) is regenerated for the three Secrets Manager rows only. Other rows that are already out of date on master belong to other teams and are left alone.

Specs

  • Flag stubs removed and flag-off cases deleted.
  • Where a false stub was only a shortcut to skip the entitlement gate, it is now a paid entitlement stub. This covers provision and initialize services and workers, effective capabilities, and project and group policy baselines.
  • Jest: added polling transition tests to replace the coverage lost with the toggle tests.

GraphQL: experiment markers stay on Group.secretsManagerEntitlement and writeDenialReason, since they are shared with sibling fields and not flag-specific. Descriptions lost the "or when the flag is disabled" wording. The GraphQL reference doc and introspection JSON are regenerated for 3 field descriptions.

Views: the CI/CD variables nudge shows for trial_eligible. Group Secure settings always show the SaaS description.

Left in place on purpose: the policy condition name instance_secrets_manager_paid_experience_allowed and InstanceEnrollment.paid_experience_allowed?. No renames in this MR.

Behavior changes

This MR is the one that ends the Self-Managed beta.

  1. Entitlement now runs everywhere, including Self-Managed. Instances without the secrets_manager add-on (offline) or without CustomersDot access resolve through the offline path or to ineligible or blocked. This is the intended GA behavior. The SaaS beta already ended on 2026-09-21.
  2. The beta cohort is frozen. Nothing writes beta: true or secrets_manager_instance_beta_enrolled: true anymore. Existing records keep their value.
  3. Unenroll on GitLab.com always soft-disables the enrollment record instead of deleting it.
  4. Off SaaS, a project whose secrets manager is deprovisioning now shows the Secrets manager sidebar item to an Owner who can provision. It was hidden before.
  5. On a Self-Managed instance that is not enrolled, CI jobs that request GitLab Secrets Manager secrets are now dropped with secrets_manager_access_denied, instead of getting an empty secrets payload.

Open question

ee/app/assets/javascripts/ci/secrets/components/secrets_manager_billing_alert.vue and the two disable_*secret_manager.mutation.graphql files are now unused. Should we remove them here, or leave that for a follow-up?

Before merge

  • cng-secrets-manager e2e job is green on this MR.
  • Re-run the group feature_provision QA spec locally.

Reviewed in parallel: !260806 (merged) is the fix for the bug in #631312. It does not block this MR, but it is best if it merges before or together with this one.

Why it matters for this MR

During a CustomersDot outage, the resolver only reused a saved answer that allows direct reads. So a trial_eligible namespace lost even its read-only access during an outage. GitLab.com already has this today. This MR turns on the same path for Self-Managed instances with an online license, where the saved answer is shared by the whole instance.

After merge

  • Run /chatops gitlab run feature delete secrets_manager_paid_experience --dev --pre --staging --staging-ref --production.
  • Close !254806 (closed).

Impact

  • Self-Managed instances, where this flag was off by default, now get the real entitlement checks that GitLab.com already has. This ends the free beta on Self-Managed.
  • Billing delivery is already handled on master: !260610 (merged) removed billing_event_tracking, and local_billing_persistence is on by default. This MR does not change either.
  • No database changes.
  • Changelog: commit trailer Changelog: changed and EE: true. The commit message says this is the change that ends the Self-Managed beta.

References

Screenshots or screen recordings

Not applicable yet. The UI changes are removals: the beta provisioning toggle in project and group settings, and the billing alert in the settings components.

How to set up and validate locally

  1. Get a license with the Secrets Manager add-on. Use an offline license from CustomersDot staging, or seed an AddOnPurchase in the console for spec work.

  2. Run the key specs:

    bundle exec rspec ee/spec/lib/secrets_management/availability_spec.rb ee/spec/lib/secrets_management/entitlement/resolver_spec.rb ee/spec/services/secrets_management/namespace_enrollment_service_spec.rb ee/spec/requests/api/ci/runner
  3. Run the Jest specs:

    yarn jest ee/spec/frontend/ci/secrets

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 Erick Bajao

Merge request reports

Loading
Loading