Remove end_secrets_manager_beta_program feature flag

What does this MR do and why?

This MR removes the end_secrets_manager_beta_program feature flag. It does not change behavior on its own.

On GitLab.com, the flag is already enabled in production and the free beta already ended there, on 2026-09-21. This MR makes that already-live behavior permanent in code.

On self-managed, secrets_manager_paid_experience is still off by default (type: wip, default_enabled: false). While it is off, the entitlement resolver returns before it sets any beta fields, and every enforcement point skips the entitlement check. So on a default self-managed install, this MR changes nothing.

The self-managed beta actually ends once secrets_manager_paid_experience is on by default, which comes with !254806 (closed) (!254806 (closed)).

Changes:

  • Removes the end_secrets_manager_beta_program flag (type beta, was default_enabled: false). Deletes ee/config/feature_flags/beta/end_secrets_manager_beta_program.yml.
  • In SecretsManagement::Entitlement::Resolver#with_beta_attributes, beta_program_ended is now always true on every online-resolved entitlement, instead of reading the flag.
  • Updates code comments that mentioned the flag. No UI or behavior change from these.

What happens when the paid experience is on, for namespaces or instances that never converted (entitlement state trial_eligible). This is already true on GitLab.com, and it will also be true on self-managed once !254806 (closed) turns on secrets_manager_paid_experience by default:

  • They lose direct secret reads. CI pipeline JWTs and the REST access-token endpoint stop working. CI jobs that request secrets get dropped with secrets_manager_access_denied.
  • They keep read-only access through the web UI and GraphQL. Listing and metadata still show, but writes are denied.
  • On GitLab.com, the UI shows the "beta ended" banner with trial and add-on actions. On self-managed, there is no banner yet. The banner check (isSaas in secrets_beta_transition_alert.vue) is SaaS-only, so self-managed users only see the read-only view with no banner and no trial or add-on actions. !258310 (merged) removes that isSaas check, so self-managed will get the banner too.
  • Namespaces that already started a trial or enabled the add-on keep full access. Nothing is deleted. Starting a trial or enabling the add-on restores access right away.
Namespaces not affected by this change

Namespaces where secrets_manager_paid_experience is disabled are not affected. This includes default self-managed installs, since the flag is off by default there. The resolver returns :ineligible before it sets any beta fields, and every enforcement point checks secrets_manager_paid_experience first and skips the entitlement check when it is off:

  • Project and group policies (secrets_manager_entitlement_aware condition), which cover the web UI, GraphQL, and the REST access-token JWT
  • CI job scheduling (EE::Ci::RegisterJobService)
  • CI runner payload (EE::Ci::BuildRunnerPresenter)
  • Service write gate (SecretsManagement::EntitlementGate)
  • GraphQL write gate (SecretsManagement::EnforcesWriteEntitlement)
  • UI capabilities (SecretsManagement::UserPermissions::EffectiveCapabilitiesService)

Offline (air-gapped) self-managed instances are also not affected. That path never sets beta fields and cannot reach trial_eligible.

Kept on purpose, follow-up work

The beta_program_ended attribute on SecretsManagement::Entitlement, the betaProgramEnded GraphQL field, and the frontend code that reads it stay in place for now. Removing them needs a GraphQL change and frontend work, so we keep this MR small.

After this MR, some code paths can no longer be reached: the beta window logic (Entitlement#beta_window?), the open-beta warning variant of the transition alert, and the isBetaUser && !betaProgramEnded branch in secret_form_wrapper.vue. These can be cleaned up in a follow-up.

Spec changes
  • resolver_spec.rb: removed the flag-off contexts and the per-namespace flag tests, since they can no longer happen. Self-managed :ineligible and fail-closed cases now check that access is denied. A stored beta trial_eligible answer is not replayed during a CustomersDot outage.
  • New cases: a beta group that started a trial keeps writes and direct reads, an add-on :paid group keeps direct reads, and with secrets_manager_paid_experience off the beta fields stay nil.
  • secrets_manager_entitlement_spec.rb (GraphQL): removed the flag stub, now expects betaProgramEnded: true.
Rollback and database notes

No migrations, no database changes.

This MR and !254806 (closed) both touch ee/config/feature_flags/beta/end_secrets_manager_beta_program.yml (!254806 (closed) sets default_enabled: true). Whichever merges second will need a rebase, and !254806 (closed) should drop its change to this YAML file.

There is no flag left to toggle after this merges, so rollback means reverting this MR. Since the behavior is already live on GitLab.com and unchanged on default self-managed installs, a mixed-version deploy gives the same answers on old and new nodes.

References

Screenshots or screen recordings

No UI changes. Only code comments changed in frontend files.

How to set up and validate locally

Run:

bin/rspec ee/spec/lib/secrets_management/entitlement/resolver_spec.rb ee/spec/lib/secrets_management/entitlement_spec.rb ee/spec/requests/api/graphql/group/secrets_manager_entitlement_spec.rb ee/spec/services/ci/register_job_service_spec.rb

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