Duo Chat panel: disambiguate why Duo is unavailable in the Dedicated empty state

Summary

On Dedicated, the Duo Chat panel renders a single "Turn on GitLab Duo Agent Platform" empty state whenever the viewer has no Duo access, regardless of why. The copy is accurate for only one of three distinct causes.

Background

Three separate conditions can put a Dedicated viewer into the no-Duo-access state, and the panel currently cannot tell them apart:

  1. duo_features_enabled is false on the namespace. "Turn on GitLab Duo Agent Platform" is correct and actionable here — the viewer, an Owner, can flip the setting.
  2. The Duo add-on has not been purchased. The setting is already on; the real action is a purchase, not a toggle.
  3. The add-on is purchased and the container's Duo toggle is on, but the individual viewer has no Duo seat assigned. The real action is seat assignment, not a purchase or a toggle. This is probably the most common of the three on real Dedicated instances, since Dedicated customers are on Ultimate and typically hold the add-on already.

!250479 (merged) deliberately collapsed all three into one state, because no better empty state existed yet and all three are still an improvement over the "Start a Free Trial" CTA that was there before — Dedicated customers are on Ultimate and never trial-eligible.

The instance-wide duo_availability = never_on case is out of scope for this issue. It was a regression introduced and then fixed within that same MR: showing the panel in that case is pointless, because the settings page it links to cannot turn Duo back on instance-wide, so a duo_never_on? guard now suppresses the panel entirely.

Proposal

Design and implement empty states that distinguish the three causes above, each with an action suited to it: turn on the setting, purchase the add-on, or assign a seat — or a contact path for viewers who cannot self-serve.

Also in scope (per @anasshahid's review)

  • On scope-less pages (personal dashboard, todos, search) the container falls back to the user's default Duo namespace, so a Dedicated admin can land on the access-denied state. An instance-level admin Duo settings page exists and could serve as a fallback destination here.
  • On Dedicated with a locked Duo toggle (subgroup lock or ancestor group lock), an Owner sees "Turn on GitLab Duo Agent Platform" pointing at a control they cannot change. A lock-aware check covering both subgroup and ancestor locks is needed.
  • chat_disabled_reason currently doubles as a "show the turn-on-Duo state" signal in the panel component, separate from its canonical use in Gitlab::Llm::DuoChat, where it is emitted only after ChatAuthorizer denies. This work should move the panel component to an explicit state flag so chat_disabled_reason has a single authorizer-gated producer again.

This scope has grown past the original title. Splitting is reasonable if the empty states and the plumbing work above are picked up separately.

References

Edited by Paul Gascou-Vaillancourt