Add resolver for listing group secrets needing rotation

Dependent on !225562 (merged) being merged first. Will rebase on master once ready.

What does this MR do and why?

Adds rotation info loading to group secret list/read services, a rotation_info field to GroupSecretType, and a new groupSecretsNeedingRotation GraphQL query, as part of #577344 (closed).

With GroupSecretRotationInfo records now being created via the services in !225562 (merged), this MR surfaces that data through the read/list path and exposes a dedicated query for fetching group secrets that are overdue or approaching their rotation deadline — mirroring the existing project secrets equivalent.

Implementation details

Services:

  • GroupSecrets::ListService — adds include_rotation_info: param; when true, batch-loads GroupSecretRotationInfo records by ID from OpenBao custom metadata and assigns them to each secret (avoids N+1)
  • GroupSecrets::ReadMetadataService — adds include_rotation_info: param; when true, looks up the rotation info for the current or previous metadata version
  • GroupSecrets::ListNeedingRotationService — new service extending ListService; calls super(include_rotation_info: true), filters to secrets where rotation_info.needs_attention?, and sorts by urgency (OVERDUE oldest-first, then APPROACHING earliest-first)

GraphQL:

  • GroupSecretType — adds rotation_info field (type SecretRotationInfo, nullable), reusing the existing generic type that already works for both project and group
  • ListNeedingRotationResolver — new resolver for groupSecretsNeedingRotation; uses ResolvesGroup + authorize :read_secret, delegates to ListNeedingRotationService
  • QueryType — registers group_secrets_needing_rotation field (milestone 18.10, experiment)

Specs:

  • secret_list_needing_rotation_service_examples.rb — new shared examples ('a service for listing secrets needing rotation') covering: empty list, no secrets needing rotation, and correct priority ordering (OVERDUE oldest-first, then APPROACHING)
  • project_secrets/list_needing_rotation_service_spec.rb — refactored to use shared examples
  • group_secrets/list_needing_rotation_service_spec.rb — new spec using shared examples + group-specific permission tests
  • group_secrets/list_service_spec.rb — adds rotation info loading tests and include_rotation_info: false test
  • group_secrets/read_metadata_service_spec.rb — adds rotation info loading test and include_rotation_info: false test
  • group_secrets/list_needing_rotation_spec.rb — new GraphQL request spec covering access control, ordering, N+1, and error handling

Series overview

Part of a series for #577344 (closed):

# MR Description
1 !225247 (merged) DB migration + GroupSecretRotationInfo model + BaseSecretRotationInfo base class
2 !225338 (merged) Rename SecretRotationInfoProjectSecretRotationInfo for naming consistency
3 !225562 (merged) CreateService + UpdateService + GraphQL mutations (add rotation_interval_days param)
4 👉 You are here List/Read services + GroupSecretType GraphQL type (add rotation info loading/field)
5 !226133 (merged) Background jobs for group and project secret rotation reminders

References

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.

Edited by Erick Bajao

Merge request reports

Loading