Enable status on epics behind a feature flag

What does this MR do and why?

Second of three backend MRs bringing status to Epics. This one enables status on the Epic type behind a feature flag and makes reads correct in every namespace, without touching any admin lifecycle configuration. It builds directly on the lifecycle provider that landed in !245353 (merged).

Part of #606012 (closed), under epic gitlab-org#17709. No issue-closing footer is set on purpose: the issue and epic stay open until the whole thing ships.

The problem

Status ships on Issue and Task today. Epics are group-level and resolve nothing: epic is not in the system-defined lifecycle base types and has no status widget. In a namespace that uses custom lifecycles, an epic would fall back to the system-defined lifecycle while issues use the custom one, which breaks the invariant that a namespace uses either system-defined or custom statuses, never both.

What this MR does (all behind work_item_status_for_epics, default off)

  • Adds :epic to the system-defined lifecycle base types and the status widget to the Epic type definition.
  • Adds the work_item_status_for_epics feature flag (wip, root-ancestor scoped) and rejects the status widget for Epic when the flag is off, so the type is fully dormant until rollout.
  • Teaches the lifecycle provider to mask: a status-supporting type with no direct custom-lifecycle connection resolves to the Issue lifecycle (or the first available). Epic mirrors Issue, so there is no system-vs-custom divergence and no backfill is needed. The mask is capability-driven (does the type expose the status widget), so it is not epic-specific.
  • Makes supports_status? widget-aware, so the webhook / hook-data capability sites honor the same gate.
  • Persists the real type-to-lifecycle connection on the first status write to an epic, so the masked state converges to a real row without a backfill and without writing on reads.
  • Closes the validation-layer airtightness gap so that with the flag off, a system-defined status is not considered valid for epic.

What this MR deliberately does NOT do (that is MR 3)

  • Nothing that only matters when an admin changes the lifecycle afterward: mapping generation when a status is removed, pinning epics when the Issue type is reassigned to another lifecycle, delete protection, and the admin lifecycles-view projection.

Verification

Model and service specs cover the flag on and off, the mask (custom hit and fallback), persist-on-write, and supports_status?. Manual validation on both a system-defined and a custom-lifecycle group.

Merge request reports

Loading
Loading