Move organization owner role sync to CE

What does this MR do and why?

This is a pure relocation with no behaviour change. It moves the organization owner role sync workers, and the helpers they depend on, from EE into CE. It is split out of !255373 (merged) at reviewers' request: @skundapur asked for the CE move to land first, and @dlrussel pointed out that the organization_admin tuple is organization lifecycle data, not Artifact Registry data, so it does not belong under ee/. The follow-up fix MR (255373) will be rebased on top of this one once it merges.

What moves:

  • Authz::Organizations::GrantOwnerRoleWorker, RevokeOwnerRoleWorker, and the OwnerRoleSync concern move from ee/app/workers to app/workers, with their specs moving to spec/workers and their queue entries moving from ee/app/workers/all_queues.yml to app/workers/all_queues.yml. Queue names are unchanged, so there is no Sidekiq compatibility concern.
  • The promotion and removal hooks that enqueue these workers are inlined from the EE overrides EE::Organizations::OrganizationUsers::UpdateService and DestroyService into the CE services. The EE override files, their prepend_mod lines, and their EE specs are removed, with the examples merged into the CE specs.
  • Authn::TokenExchange::TokenIssuer moves from ee/lib to lib. Its signing key comes from CloudConnector::CachingKeyLoader, which is EE-only, so the CE class raises Gitlab::AbstractMethodError from signing_jwk. A new EE::Authn::TokenExchange::TokenIssuer module supplies the key via prepend_mod. TokenIssuer.available? is false in CE and true in EE; a missing Cloud Connector key keeps failing loudly in the worker, as on master. Its spec moves to ee/spec/lib/ee/authn/token_exchange/ because the key factory is EE, and a small CE spec, guarded to the FOSS run, asserts the CE defaults.
  • A new CE Authz::Organizations::Roles.organization_admin_uuid resolves the Organization Administrator role id from the glaz roles catalogue. organization_admin is removed from Authz::ArtifactRegistry::Roles, which now holds only the four Artifact Registry roles, and Types::Authz::ArtifactRegistry::RoleAssignmentType no longer special-cases it, so a platform role now resolves to nil without a drift warning.
  • A single enqueue gate, Authz::Organizations::OwnerRoleSync.enabled?, checks Authn::IamDataAccessService.configured? and TokenIssuer.available?, replacing the per-site configured? checks. This means CE never enqueues jobs it cannot sign, while EE keeps the same enqueue conditions as master. A table-driven spec was added for this gate.

Worker names are unchanged, since renaming a Sidekiq worker needs a multi-release migration; that naming change has its own follow-up. Making owner-tuple propagation work on CE (a CE signing key, or the STS target state) is a separate follow-up.

References

Screenshots or screen recordings

Not applicable. This is a backend-only relocation with no UI changes.

How to set up and validate locally

Behaviour is unchanged. These steps confirm the same workers still fire from the same triggers, now defined in CE:

  1. With IAM data access configured (iam_data_access_service.secret_file in gitlab.yml) and a Cloud Connector signing key present, promote an existing organization member to Owner using the organizationUserUpdate GraphQL mutation. Confirm Authz::Organizations::GrantOwnerRoleWorker is enqueued.
  2. Remove an organization Owner, or demote them from Owner, using the corresponding mutation. Confirm Authz::Organizations::RevokeOwnerRoleWorker is enqueued.
  3. On CE, repeat the same promotion or removal. Confirm neither worker is enqueued, since Authz::Organizations::OwnerRoleSync.enabled? returns false.

RuboCop is clean on all changed files. RSpec was not run locally because the test database cluster was unavailable in this environment; the MR pipeline runs the specs.

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

Edited by Bojan Marjanovic

Merge request reports

Loading
Loading