Step 4: Enforce read-only mode for GraphQL mutations
## Summary Block GraphQL mutations that target namespaces in `maintenance` state. Rack middleware alone is insufficient for GraphQL because the namespace is embedded in the request body (all GraphQL requests are POST to `/api/graphql`). > **POC approach:** This will be part of a single POC MR (does not need to merge to master). Maintenance mode will be toggled via Rails console. ## Dependencies - **Depends on**: Step 1 (#591688) — state machine transitions - **Parallel with**: Step 2 (#591689) and Step 3 (#591690) ## Context Parent issue: https://gitlab.com/gitlab-org/gitlab/-/issues/590009 GraphQL mutations are all POST requests to a single endpoint, so the namespace-scoped middleware (Step 2) cannot determine the target namespace from the URL path alone. Enforcement must happen at the GraphQL layer. ## Tasks - [ ] Investigate enforcement approaches: - **Option A**: Custom `GraphQL::Analysis::AST::Analyzer` that inspects mutation arguments for namespace/group/project references and checks maintenance state - **Option B**: Override in `Mutations::BaseMutation` to check namespace state before executing - **Option C**: Add a shared concern to resolvers/mutations that checks the namespace of the resolved object - [ ] Implement chosen approach - [ ] Ensure GraphQL **queries** (reads) still work — only mutations should be blocked - [ ] Return a structured GraphQL error with appropriate message and extensions (e.g., `{ "extensions": { "code": "NAMESPACE_MAINTENANCE" } }`) - [ ] Add specs covering: mutation blocking, query passthrough, nested namespace resolution ## Key Files - `app/graphql/mutations/base_mutation.rb` - `app/controllers/graphql_controller.rb` - `app/graphql/types/mutation_type.rb` ## Effort Estimate Medium (2-3 days)
task