Rate limit the bulk AI tool rules mutation per user
What does this MR do and why?
One group Owner can call bulkUpdateAiToolRules as often as the generic GraphQL throttle allows, about 2,000 times a minute, and every call writes up to 100 rule rows plus one audit event with its streaming job. This MR adds a per-user limit of 10 calls a minute, behind the ai_tool_rules_bulk_update_rate_limit feature flag: the same number as the AI Catalog bulk enable mutation, and the same shape as the model selection update mutation (the throttled call raises, so the response is a 429 and nothing is written or audited).
- Registry entry
ai_tool_rules_bulk_update(10 a minute, per user) in the EE rate limit registry. check_rate_limit!right after the namespace lookup and authorization, the order the sibling mutations use: flag on and over the limit raises the standard "requested too many times" error; nothing is written or audited.- Feature flag
ai_tool_rules_bulk_update_rate_limit(gitlab_com_derisk, disabled by default, actor is the user). - Docs row in the non-configurable rate limits page.
Review notes
- Alternatives considered: no flag (the Bulkhead sibling limits all shipped flagged, so the limit can be turned off per user if a scripted caller is hit); an admin setting for the limit (not asked for; the issue records 60 a minute as the ceiling such a setting could expose).
- Not done, tracked at https://gitlab.com/gitlab-org/gitlab/-/work_items/636289: the two no-op write skips from the same issue follow in separate MRs.
- Approvals: backend maintainer (
ee/config/feature_flags/is owned by rails-backend maintainers); technical writer for the docs row; no database review (no query change). - No UI calls this mutation; the limit touches API and scripted callers only.
- No changelog entry: the change sits behind a flag that is disabled by default.
- A request that aliases the mutation more than ten times gets a 429 after the first ten writes committed, the same as the model selection mutation; the per-call limit is the point.
- The single-rule mutation
updateAiToolRuleis not limited here; it writes one row and one audit event per call. - Specs run locally:
ee/spec/graphql/mutations/ai/bulk_update_ai_tool_rules_spec.rb(33 examples),ee/spec/requests/api/graphql/mutations/ai/bulk_update_ai_tool_rules_spec.rb(17),ee/spec/lib/ee/gitlab/application_rate_limiter/labkit_adapter/supported_rate_limits_spec.rb(16). Negative controls, one line each: removing thecheck_rate_limit!call, the feature flag check, or the per-user scope each fails at least two examples. - Verified on a GDK over HTTP with the flag on for one user: calls 1 to 10 succeed, calls 11 and 12 return 429 with no rule write and no audit event, the flag off lets the same user through, and the next minute resets the count.
Manual verification (GDK, SaaS mode, flag enabled per user)
Results, mutation driven through POST /api/graphql
| Case | Expected | Result |
|---|---|---|
| Flag off, 12 calls in a minute | all succeed, 12 audit events | pass |
| Flag on, calls 1 to 10 | succeed | pass |
| Flag on, call 11 | 429 with the standard message, nothing written, no audit event, one auth_json.log line |
pass |
| Second Owner right after the 429 | succeeds | pass |
| User without access, 11 calls | same not-available error every time, never a 429 | pass |
| Project-scoped payload, 11 calls | call 11 is a 429 | pass |
| After the one-minute window | succeeds | pass |
| 11 aliased fields in one request | 429 after the first ten writes committed | pass, documented above |
References
- Related to https://gitlab.com/gitlab-org/gitlab/-/work_items/636289 (one of three MRs; the issue closes with the last one)
- Rollout: https://gitlab.com/gitlab-org/gitlab/-/work_items/637741
How to set up and validate locally
bin/rspec ee/spec/requests/api/graphql/mutations/ai/bulk_update_ai_tool_rules_spec.rb -e 'rate limiting'With the flag enabled for a user (Feature.enable(:ai_tool_rules_bulk_update_rate_limit, user)), the eleventh bulkUpdateAiToolRules call within a minute returns the error "This endpoint has been requested too many times. Try again later." and writes no rule.
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
- I have evaluated the MR acceptance checklist for this MR.