feat: add Labkit::RateLimit identifier and rules API (Stage 1a)

Summary

  • Adds Labkit::RateLimit.check(call_site:, identifier:, rules:) — the foundational rate limiting interface for Phase 2 of GitLab's unified rate limiting architecture
  • Identifier value object carrying request context as key-value pairs (user, ip, namespace, plan, endpoint) with endpoint normalization
  • Rule value object with match conditions, limit, period, action, and characteristics
  • Per-rule independent Redis counters keyed as labkit:rl:{call_site}:{rule_index}:{char_key}:{char_value}
  • SHA-256 hashing for char_value > 200 chars to prevent prefix-collision quota theft
  • Fail-open on Redis errors with structured WARN logging
  • Characteristic and call_site validation (raises in dev/test, sanitizes + WARNs in prod)
  • Structured per-rule JSON logging with redis_key field for on-call triage

Test plan

  • bundle exec rspec spec/labkit/rate_limit_spec.rb spec/labkit/rate_limit/identifier_spec.rb spec/labkit/rate_limit/evaluator_spec.rb --format documentation → 39 examples, 0 failures
  • Fail-open scenario verified (Redis unavailable → :allow, no exception, WARN log)
  • Characteristic validation: ArgumentError in test, sentinel in production
  • call_site validation: ArgumentError in test, sanitized in production
  • SHA-256 hashing: two distinct 300-char values with shared prefix → different Redis keys

Spec: gitlab-com/gl-infra/production-engineering#28784 (closed)
Epic: gitlab-com/gl-infra#2021

🤖 Generated with Claude Code

Merge request reports

Loading