Add GraphQL create mutation for the Anthropic Compliance credential

What does this MR do and why?

Part of https://gitlab.com/gitlab-org/gitlab/-/work_items/628487: the GraphQL mutation the Claude Compliance settings page needs to save a Compliance Access Key. Behind the claude_code_compliance_api_ingestion flag.

Includes the read field from !264354 (closed) until it merges; review only the create mutation commit.

  • Mutation anthropicComplianceIntegrationCreate(groupPath, apiKey): verifies and stores the key with SetAccessKeyService. Returns errorReason: INVALID_KEY, RATE_LIMITED, VERIFICATION_FAILED, BLANK_KEY, INVALID_INTEGRATION. Rate limited per group and per user, and records an audit event.
  • New permission create_anthropic_compliance_integration for Owners, with granular token support.

Update (replace key, enable or disable) and delete mutations come in a follow-up MR.

Decisions to confirm

  1. Gated on claude_code_compliance_api_ingestion, the same flag as the read field.
  2. One permission per action (read, create; update and delete later) instead of a single ability.
  3. Rate limits: 10 attempts per hour per group and 10 per hour per user.
  4. No licence check, matching the rest of the feature.
  5. Create on a group that already has an integration returns INVALID_INTEGRATION; replacing a key is the update mutation's job.

Database

Ai::Compliance::Anthropic::Integration.for_namespaces (used by the Group.anthropicComplianceIntegration batch loader). The batch holds one id per group loaded in the request.

SELECT "ai_compliance_anthropic_integrations".*
FROM "ai_compliance_anthropic_integrations"
WHERE "ai_compliance_anthropic_integrations"."namespace_id" IN (<namespace ids of the groups in the request>)

Plan (Database Lab thin clone of gitlab-production-main, 20 ids): https://console.postgres.ai/gitlab/projects/gitlab-production-main/sessions/73058/commands/177054

Seq Scan on public.ai_compliance_anthropic_integrations  (cost=0.05..0.05 rows=1 width=173) (actual time=0.007..0.008 rows=0 loops=1)
  Filter: (namespace_id = ANY ('{...}'::bigint[]))
Time: 0.453 ms (planning 0.425 ms, execution 0.028 ms), 0 buffers

The table is empty in production today, so the planner picks a sequential scan. It holds at most one row per top-level group (index_ai_compliance_anthropic_integrations_on_namespace_id, unique), so as rows are added the lookup is served by that index.

How to set up and validate locally

bundle exec rspec ee/spec/requests/api/graphql/mutations/ai/compliance/anthropic ee/spec/policies/ee/group_policy_spec.rb -e create_anthropic_compliance_integration

In GraphiQL, as a top-level group Owner with the flag on, run anthropicComplianceIntegrationCreate with any key. Without a real Compliance Access Key it returns errorReason: INVALID_KEY.

References

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist.

Edited by Hitesh Raghuvanshi

Merge request reports

Loading
Loading