Prevent cross-organization work item links and moves (Cells guardrail)
What does this MR do and why?
With Cells, an organization is isolated to a single cell: its database rows and its Gitaly repositories (including Design Management repos) live only on that cell, and cross-cell access is unsupported. Several work-item operations let a user reference or relocate an item across projects/groups without checking the organization — harmless in a single cell today, but broken under Cells:
- Cross-org links / hierarchy would need a foreign key into another cell's database.
- Cross-org move/clone/promote would write into another cell's database and copy repository-backed data (notably designs) across Gitaly fleets.
This MR adds organization-equality guards, gated by the prevent_cross_organization_work_item_actions feature flag (gitlab_com_derisk, default disabled), so rollout is controlled and the change is a no-op within a single organization.
Design
A single reusable abstraction is applied at both the model and service layers:
Issuable#same_organization_as?(other)— the one comparison (resource_parent.organization_id), shared by issues, work items, and epics.SameOrganizationValidator— anActiveModelvalidator (FF-gated) added to the sharedIssuableLinkconcern, so it coversIssueLink,WorkItems::RelatedWorkItemLink, andEpic::RelatedEpicLinkat once; also used byEpicIssueandWorkItems::ParentLink.- Services (
IssuableLinks::CreateService,WorkItems::DataSync::BaseService) and the designs widget delegate tosame_organization_as?and gate the flag consistently onresource_parent.
Coverage
| Vector | Where | Layer |
|---|---|---|
| Issue / work item links | IssuableLinks::CreateService + IssuableLink |
service + model |
| Related epic links | IssuableLink concern |
model |
| Epic |
EpicIssue |
model |
| Work item hierarchy (parent links) | WorkItems::ParentLink |
model (new guard) |
| Move / clone / promote | WorkItems::DataSync::BaseService |
service |
| Design copy on move/clone | WorkItems::DataSync::Widgets::Designs |
service |
WorkItems::ParentLink and Epic::RelatedEpicLink were previously unguarded at the model level; this closes both.
Feature flag
prevent_cross_organization_work_item_actions—gitlab_com_derisk,default_enabled: false.- Disabled: behavior unchanged. Enabled: cross-organization links/hierarchy/moves are rejected with a clear error.
Test plan
- Specs cover both flag states for the link service, the move service, the designs widget, the shared validator, and each guarded model.
- Within a single organization (the common case in existing specs) all guards are no-ops.
Rollout note
Before enabling, audit work_item_parent_links and related_epic_links for any pre-Cells legacy data whose endpoints resolve to different organizations, since enabling will start rejecting such relationships.
Closes #603656