Draft: Add opt-in setting for guest package pulls

What does this MR do and why?

This is MR 1 of 3. It adds an opt-in setting next to the allow_guest_plus_roles_to_pull_packages feature flag, so we can delete the flag later without breaking anyone.

The flag lets Guest (and Planner) users pull packages from private projects. It's on for only one root group on GitLab.com. The authorization team needs the flag out of policy files for their role YAML refactor.

Why a setting instead of a flag

Feature flags aren't meant to be permanent. The authorization team is refactoring policy files and can't have a flag check baked into them. Moving to a setting lets us keep the current behavior for the one group that uses it, while giving the authorization team a clean path forward.

Changes in this MR:

Area Change
Migration Adds guest_package_pull_enabled boolean DEFAULT false NOT NULL to namespace_package_settings.
Model Namespace::PackageSetting.guest_package_pull_allowed?(namespace) returns true if the flag is on for the root namespace, or the root namespace's setting is on. Only the root namespace's setting counts. A subgroup setting has no effect.
Wiring ProjectPolicy and GroupPolicy (condition renamed to guest_package_pull_allowed), and three finders (Packages::FinderHelper#projects_visible_to_reporters, Packages::Npm::PackagesForUserFinder, Packages::ProjectsFinder#access) now call the helper instead of Feature.enabled?.
Specs Model spec covers flag on, setting on, both off, and subgroup-only setting. Policy and finder specs cover "flag off, setting on".

Behavior change: none by default. The setting defaults to false, and there's no API or UI to set it yet. Existing flag behavior is unchanged.

Not in this MR:

  • MR 2 exposes the setting in GraphQL, the group Packages and registries settings page, and docs.
  • MR 3 deletes the flag once the one group using it is moved to the setting.
  • How the setting maps to config/authz/roles/*.yml is still open, pending an answer from the authorization team.

References

How to set up and validate locally

  1. Run bin/rails db:migrate.
  2. In a Rails console, run Feature.disable(:allow_guest_plus_roles_to_pull_packages).
  3. Pick a private group with a project that has a package, and a user who is a Guest in that group.
  4. Check user.can?(:read_package, project). It should be false.
  5. Run group.root_ancestor.package_settings.update!(guest_package_pull_enabled: true).
  6. Check user.can?(:read_package, project.reload). It should be true.
  7. Optionally, pull the package as that guest using a personal access token with the read_api scope.

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.

🤖 Generated with Claude Code

Merge request reports

Loading
Loading