Exempt any non-guest paid-namespace membership from IV

What does this MR do and why?

Exempt any non-guest paid-namespace membership from IV

Add an all-memberships tier to User#belongs_to_paid_namespace? behind the identity_verification_paid_membership flag. When enabled, any non-guest membership (project or group, resolved to its root ancestor) in a paid namespace exempts the user from identity verification, extending the existing subgroup Reporter+ resolution to project memberships.

Related to: https://gitlab.com/gitlab-org/gitlab/-/work_items/605202

EE: true

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Database review

Behind feature flag identity_verification_paid_membership (gitlab_com_derisk, default off). No migration — read-query change only on the existing members / namespaces tables, on the GitLab.com identity-verification path (User#belongs_to_paid_namespace?), executed with .any? (LIMIT 1).

When the flag is enabled, membership resolution changes from "Reporter+ group memberships" to "any non-guest membership (project or group), resolved to its root ancestor" — the UNION's second arm switches from a GroupMember join on members.source_id to a join on members.member_namespace_id, drops the type = 'GroupMember' restriction, and replaces the access-level list with access_level > 10.

Before (Reporter+ group memberships):
SELECT namespaces.id
FROM (
  (SELECT namespaces.id FROM namespaces
     WHERE namespaces.type = 'User' AND namespaces.owner_id = 1614863)
  UNION
  (SELECT namespaces.traversal_ids[1] FROM namespaces
     INNER JOIN members ON namespaces.id = members.source_id
     WHERE members.type = 'GroupMember'
       AND members.source_type = 'Namespace'
       AND namespaces.type = 'Group'
       AND members.user_id = 1614863
       AND members.requested_at IS NULL
       AND access_level >= 10
       AND members.access_level IN (20, 30, 40, 50))
) namespaces
LEFT OUTER JOIN gitlab_subscriptions ON gitlab_subscripts.id
WHERE gitlab_subscriptions.hosted_plan_id IN (
        SELECT plans.id FROM plans WHERE plans.name IN
          ('bronze','silver','premium','gold','ultimate','ultimate_trial',
           'ultimate_trial_paid_customer','premium_trial
  AND (gitlab_subscriptions.trial = FALSE
       OR gitlab_subscriptions.trial IS NULL
       OR gitlab_subscriptions.trial_ends_on <= (CURRENT_DATE - 1))
LIMIT 1

Query plan: https://console.postgres.aiundefined/shared/975f15a2-46cc-41f8-8c17-96cf849acfd3

After (any non-guest membership, project or group):
SELECT namespaces.id
FROM (
  (SELECT namespaces.id FROM namespaces
     WHERE namespaces.type = 'User' AND namespaces.owner_id = 1614863)
  UNION ALL
  (SELECT namespaces.traversal_ids[1] FROM namespaces
     INNER JOIN members ON namespaces.id = members.member_namespace_id
     WHERE members.user_id = 1614863
       AND members.state = 0
       AND members.requested_at IS NULL
       AND members.access_level > 10)
) namespaces
LEFT OUTER JOIN gitlab_subscriptions ON g_id = namespaces.id
WHERE gitlab_subscriptions.hosted_plan_id IN (
        SELECT plans.id FROM plans WHERE
          ('bronze','silver','premium','gold','ultimate','ultimate_trial',
           'ultimate_trial_paid_customer'))
  AND (gitlab_subscriptions.trial = FALSE
       OR gitlab_subscriptions.trial IS N
       OR gitlab_subscriptions.trial_ends_on <= (CURRENT_DATE - 1))
LIMIT 1

Query plan: https://console.postgres.aiundefined/shared/d07945d4-1afd-40fc-95f4-4e58390cd3e6

References

Screenshots or screen recordings

Before After

How to set up and validate locally

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 Jay

Merge request reports

Loading