Add artifact registry organization to namespace mapping table

What does this MR do and why?

Implements monolith/S10 Step 1: the organization → Artifact Registry namespace mapping table and model (gitlab#603023).

The monolith owns and persists a one-row-per-organization mapping from an organization to its Artifact Registry namespace UUID, written at provisioning. Rails stores only the UUID and resolves the handle and service status from Artifact Registry by that UUID from then on (ADR-022, ADR-014). This keeps Artifact Registry's API free of Organization concepts and removes per-request round-trips to resolve an organization to its namespace.

This is the foundation the later S10 steps (provisioning service, resolution + caching, activate/disable/enable mutations) build on; the table is inert until those writers land.

What's included

  • Migration create_artifact_registry_namespace_mappings: organization_id (FK, on_delete: :cascade) with a unique index (one mapping per organization — the concurrency guard the provisioning sequence relies on), and ar_namespace_id (uuid, not null).
  • Model ArtifactRegistry::NamespaceMapping: belongs_to :organization, presence + uniqueness validations mirroring the DB constraints. Named NamespaceMapping (not Namespace) to avoid a Zeitwerk collision with the monolith/S02 client's ArtifactRegistry::Namespace value object.
  • Organization has_one :artifact_registry_namespace_mapping inverse.
  • db/docs, a development fixture, and the organization-transfer registry entry.

Naming: ar_namespace_id, not namespace_id

The UUID column is deliberately named ar_namespace_id, matching gitlab#603023 ((organization_id, ar_namespace_id)). It is the Artifact Registry service's namespace UUID, not a GitLab namespaces (group/project) reference — there is no FK to GitLab's namespaces, by ADR-022 design. namespace_id would have collided with the monolith's usual meaning for that column.

Organization transfer: no_work_needed (deviation from the plan — flagged)

The S10 plan (!1303) suggested organization_transfer_support: supported. I've set it to no_work_needed instead, because the generic transfer machinery (update_organization_id_for) does not apply here:

  • The mapping is org-owned, not group/user-owned, so nothing "carries" the row to another org during a group/user transfer.
  • The one case that does eventually touch this row — an organization merge — is explicitly out of scope and handled by a bespoke future monolith change (relax the one-per-org constraint / repoint the UUID), per ADR-022 §Organization Merges and the S10 spec's out-of-scope list — not by the transfer service.
  • Marking it supported would require wiring a transfer call that is either a no-op or an index-violating bug against the unique constraint.

The tooling sanctions this: organization_transfer_support resolves from config/organizations/transfer_support.yml (not db/docs), and spec/lib/gitlab/organizations/organization_transfer_support_spec.rb explicitly allows no_work_needed for a table that needs no transfer work — so the schema/transfer specs pass without an organization_transfer_support key in db/docs. (The transfer_support.yml header comment's "new tables MUST use supported" is the general rule; the spec is the authority that carves out no_work_needed.) This matches the precedent set by the recently-added org-sharded iam_outbox table (also no_work_needed). @rchanila — flagging this as a considered deviation from the plan; happy to revisit if you'd prefer to raise it against the S10 spec.

Testing

Verified locally:

  • Migration applies cleanly; the table has exactly id, organization_id, ar_namespace_id, created_at, updated_at, a unique index on organization_id, and a cascading FK to organizations.
  • Model spec (8 examples) and organization spec (29 examples) pass: association, presence/uniqueness validations, the DB-level uniqueness guard, the column set, and cascade-on-organization-delete.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist.

Edited by Narendran

Merge request reports

Loading
Loading