Add budget caps GraphQL query types and PORO layer
What does this MR do and why?
Adds the GraphQL query layer for reading budget cap controls via subscriptionUsage { budgetCaps { ... } }. This proxies budget cap data from the Customer Portal (CDot) through GitLab's public GraphQL API.
Users (namespace owners on SaaS, instance admins on SM) can now query:
- Subscription-level cap and flat per-user cap
- Per-user budget cap overrides with resolved GitLab
Userobjects - Relay-style pagination and
userIdsfiltering on overrides
Gated behind the budget_caps_graphql_api feature flag (disabled by default, introduced in MR1).
Related to https://gitlab.com/gitlab-org/gitlab/-/issues/595490
Stacked MR
| # | MR | Description | Status |
|---|---|---|---|
| 1 | !230214 (merged) | Foundation — feature flag + client + shared concern | Merged |
| 2 | This MR | Query — budget caps read API (BudgetCapsType, UserOverrideType, PORO) |
Merged |
| 3 | !230224 (merged) | Mutation — upsert flat user cap | In review |
| 4 | !230222 (merged) | Mutation — upsert user budget cap overrides | In review |
| 5 | !230226 (closed) | Enable feature flag by default (draft, blocked by 3-4) | Draft |
How to set up and validate locally
Prerequisites: GDK running with CDot on localhost:5000 (CUSTOMER_PORTAL_URL=http://localhost:5000 in gdk.yml). Use an existing group/subscription that has budget cap data seeded in CDot.
1. Enable the feature flag
# Rails console
Feature.enable(:budget_caps_graphql_api)2. SaaS — Root namespace owner gets budget caps
Log in as the owner of an existing root group (e.g., saastestgroup). Open GraphiQL at http://localhost:3000/-/graphql-explorer and run:
{
subscriptionUsage(namespacePath: "saastestgroup") {
budgetCaps {
subscriptionCap
subscriptionCapEnabled
flatUserCap
flatUserCapEnabled
userOverrides(first: 2) {
nodes {
user {
id
username
name
}
cap
capEnabled
createdAt
updatedAt
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}Expected: budgetCaps returns subscription-level cap fields and paginated userOverrides with resolved User objects.
3. SaaS — Pagination
Use the endCursor from step 2:
{
subscriptionUsage(namespacePath: "saastestgroup") {
budgetCaps {
userOverrides(first: 2, after: "<endCursor from step 2>") {
nodes {
user {
id
username
}
cap
capEnabled
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}Expected: Next page of overrides, hasNextPage reflects remaining data.
4. SaaS — Filter by userIds
{
subscriptionUsage(namespacePath: "saastestgroup") {
budgetCaps {
userOverrides(userIds: ["gid://gitlab/User/1"]) {
nodes {
user {
id
username
}
cap
capEnabled
}
}
}
}
}Expected: Only the override for the specified user is returned.
5. Self-Managed — Instance admin gets budget caps
Log in as an instance admin. Admin mode must be enabled — toggle admin mode from user settings (click avatar → Preferences → enable Admin Mode), or use a Personal Access Token (PAT) with api scope
which bypasses admin mode automatically via sessionless_bypass_admin_mode!.
Omit namespacePath:
{
subscriptionUsage {
budgetCaps {
subscriptionCap
subscriptionCapEnabled
flatUserCap
flatUserCapEnabled
userOverrides(first: 2) {
nodes {
user {
id
username
name
}
cap
capEnabled
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}Expected: Budget caps returned using License.current.
Note: On Self-Managed, the
adminpolicy condition inBasePolicyrequires bothuser.admin?and an active admin mode session (Gitlab::Auth::CurrentUserMode#admin_mode?). Without admin mode enabled, the query returns a permission error. API requests authenticated with a PAT bypass this requirement automatically.
6. Unauthorized — Non-owner (SaaS)
Log in as a user who is not an owner of the group and run the query from step 2.
Expected: subscriptionUsage returns null with permission error.
7. Unauthorized — Non-admin (SM)
Log in as a non-admin user and run the query from step 5.
Expected: subscriptionUsage returns null with permission error.
8. Feature flag disabled
Feature.disable(:budget_caps_graphql_api)Re-run any query above. Expected: budgetCaps returns null, other subscriptionUsage fields still work.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.