Skip to content

feat(scim): replace brute-force member sync with members.value pagination#534

Merged
christiangda merged 3 commits into
mainfrom
feat/scim-listgroups-membersvalue
May 24, 2026
Merged

feat(scim): replace brute-force member sync with members.value pagination#534
christiangda merged 3 commits into
mainfrom
feat/scim-listgroups-membersvalue

Conversation

@christiangda
Copy link
Copy Markdown
Contributor

@christiangda christiangda commented May 23, 2026

Closes

Milestone: v0.45.0.

Summary

  • internal/scim.GetGroupsMembers(ctx, groups, users) now runs one cursor-paginated ListGroups?filter=members.value eq "<user-id>" request per user and inverts the response into the existing group → members map. The previous brute-force O(N_groups × N_users) loop and its 10–150ms random sleep throttle are gone.
  • pkg/aws.SCIMService gains ListGroupsWithCursor(ctx, filter, cursor); pkg/aws.ListResponse gains NextCursor. ListGroups is unchanged for its remaining single-page callers.
  • internal/core.SCIMService.GetGroupsMembers signature updated to accept users; GetGroupsMembersBruteForce and the broken GetGroupsMembers(ctx, gr) are deleted with no compatibility shim. Mocks regenerated via go generate ./....
  • Concurrency cap is now exercised under Go 1.26's testing/synctest — virtual clock + bubble lets the test assert the true peak in-flight count deterministically.

For an org with 200 groups and 500 users this drops the per-sync call count from ~100,000 to ~500 (roughly two orders of magnitude lighter on the AWS SCIM endpoint). Enabled by two AWS features documented in the SCIM ListGroups reference: the members.value filter and cursor-based pagination (page cap raised from 50 to 100).

Docs:

  • docs/Whats-New.md — Unreleased entry leads with the perf delta, lists the internal API breaks.
  • README.md — Limitations section updated (page cap is now 100, throttling note reflects the lighter call profile).

Test plan

  • go build ./...
  • go vet ./...
  • go test ./... (full suite green; new tests under pkg/aws and internal/scim, integration mock in internal/core/sync_test.go rewired to the new query shape)
  • make go-fmt + make go-betteralign
  • golangci-lint run ./... — no new findings (remaining 15 errcheck warnings are all pre-existing in untouched files)
  • Manual sanity run against a real IAM Identity Center tenant before tagging v0.45.0

🤖 Generated with Claude Code

…tion

Closes #520.

The AWS IAM Identity Center SCIM ListGroups endpoint now supports the
`members.value eq "<user-id>"` filter together with cursor-based
pagination, so a sync run no longer needs to issue one ListGroups call
per (group, user) pair to reconstruct group membership.

`internal/scim.GetGroupsMembers(ctx, groups, users)` now runs one
paginated query per user (~O(users) calls) and inverts the result into
the existing group → members map, replacing the previous O(groups ×
users) brute-force loop and its 10-150ms random sleep throttle.

The concurrency cap is now exercised under Go 1.26's `testing/synctest`
so the test asserts the true peak in-flight count using a virtual
clock instead of waiting on a wall-clock sleep race.

The legacy `GetGroupsMembers(ctx, gr)` and `GetGroupsMembersBruteForce`
methods are removed without a compatibility shim.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@christiangda christiangda self-assigned this May 23, 2026
christiangda and others added 2 commits May 24, 2026 10:20
Restructures the Unreleased entry for the SCIM members sync change to
lead with an IMPORTANT callout and dedicated Security / Performance
subsections, making the impact of closing #520 explicit for readers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@christiangda christiangda added this pull request to the merge queue May 24, 2026
Merged via the queue into main with commit 64cef29 May 24, 2026
6 checks passed
@christiangda christiangda added this to the v0.45.0 milestone May 24, 2026
@christiangda christiangda deleted the feat/scim-listgroups-membersvalue branch May 24, 2026 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: use ListGroups with members.value to avoid bruteforce algorithm to retrieve members

1 participant