Sign in or sign up before continuing. Don't have an account yet? Register now to get started.
BE: Filter projects for agent/flow association to Premium+ projects (with Duo Features enabled if possible)
## Problem
[As discussed in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/572017), there is currently no way to filter the list of projects available for agent/flow association by the required eligibility criteria:
- Project belongs to a **Premium+ licensing tier** namespace
- Project has **Duo Features enabled** (`ProjectSetting.duo_features_enabled`)
- On SaaS, **Free tier projects** are also eligible if they have an active `gitlab_credits` add-on purchase
- Project has opted in to **Experimental/Beta features** (differs between SaaS and Self-Managed) — applicable to Custom Flows only, as Agents are now GA
## Implementation Plan
Add a new `duoLicensedFeature` filter to the projects GraphQL query that returns only projects eligible for a specific GitLab Duo AI feature.
The filter should handle two deployment types:
- **Self-Managed**: Check if the requested feature is available through the instance license. If licensed, return all projects with Duo features enabled.
- **SaaS (GitLab.com)**: Check the namespace's subscription plan (Premium+) or active `gitlab_credits` add-on to determine eligibility, then return matching projects with Duo features enabled.
**Important note**: When `duoLicensedFeature` is used, the system internally enforces that only projects where the current user has **maintainer+ role** are returned. This ensures that the GraphQL field does not expose licensing information about projects the user is not a maintainer+ of.
`duoLicensedFeature` is an **ENUM** type (`DuoLicensedFeature`) with three possible values:
* `AGENTIC_CHAT`
* `AI_CATALOG`
* `AI_FEATURES`
The filter should be marked as **Experimental** and target GitLab **18.11**.
## Example Usage
```graphql
query fetch_projects {
projects(
duoLicensedFeature: AI_CATALOG
) {
nodes {
fullPath
name
}
count
}
}
```
The above query returns all projects for which the `ai_catalog` feature is available. Internally, the system filters projects based on the following criteria:
1. **Duo platform availability**: GitLab Duo is available at the top-level namespace (SaaS) or instance level (Self-Managed).
2. **Project-level setting**: The `duo_features_enabled` setting is enabled for the project.
3. **Tier eligibility**: The top-level namespace or instance has a matching subscription tier for the requested AI feature. Tier requirements vary by feature:
* `AI_CATALOG` and `AGENTIC_CHAT`: Available for **Premium+** tiers.
* `AI_FEATURES`: Available for **Ultimate** tier only.
* **Free tier** projects are also eligible if they have an active add-on credits purchase (`gitlab_credits`), as Duo AI Platform (DAP) has been available for Free tier with add-on credits since **18.10**.
**NOTE:** Changes on the scope `Namespace.with_ai_supported_plan` is behind the feature flag `filter_projects_by_duo_licensed_feature`, here is the FF roll out issue - https://gitlab.com/gitlab-org/gitlab/-/work_items/595308
<details>
<summary>Previous description</summary>
## Currently
[As discussed in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/572017), there is no way to filter the list of projects available for agent/flow association by the criteria required:
- Project has Premium+ licensing tier
- Project has Duo Features enabled (`ProjectSetting.duo_features_enabled`)
- Project has opted-in to Experimenta/Beta features ([different for SaaS vs Self-Managed](https://gitlab.com/gitlab-org/gitlab/-/blob/de32881a9c452e36de9eedad1e61825c1ffc15bb/ee/lib/gitlab/llm/stage_check.rb#L77-94))
Ideally, we would filter on both dimensions so that only projects eligible for agent/flow attachment are shown.
## For this iteration
Expose the existing `by_plans` filter from `ProjectsFinder` in GraphQL.
**Important note**: As we don't want to allow the GraphQL field to expose this information for projects the user is not a maintainer of, `ProjectsFinder` should only allow scoping by the new arguments if the set of projects being returned are ones that the user is maintainer+ of - this is because we don't want to expose this information about projects the user is not maintainer+ of. Therefore, the [`min_access_level` arg](https://gitlab.com/gitlab-org/gitlab/-/blob/cfd39e86e064e3c43a9bd9e3c797f594c57324eb/app/graphql/resolvers/projects_resolver.rb#L111) must be either `[Gitlab::Access::MAINTAINER, Gitlab::Access::OWNER]` in order for the new GraphQL argument to be used, otherwise GraphQL should return an error.
The backend engineer could also do the corresponding ~frontend issue also if they feel comfortable https://gitlab.com/gitlab-org/gitlab/-/issues/572017. The frontend changes would need to be deployed after the backend change to avoid multi-version compatibility problems.
Or if the backend engineer is not comfortable with the frontend change, update https://gitlab.com/gitlab-org/gitlab/-/issues/572017 with the new GraphQL arguments added on the ~backend.
</details>
issue