Skip to content

refactor(store): wave B.8 — identity_provider repo (read side) (#259)#260

Merged
PaulDotterer merged 2 commits into
mainfrom
feat/259-identityprovider-repo
May 15, 2026
Merged

refactor(store): wave B.8 — identity_provider repo (read side) (#259)#260
PaulDotterer merged 2 commits into
mainfrom
feat/259-identityprovider-repo

Conversation

@PaulDotterer

@PaulDotterer PaulDotterer commented May 15, 2026

Copy link
Copy Markdown
Contributor

Summary

`IdentityProviderRepo` — read side of the identity-providers projection. All 17 handler/scim/idp-internal read sites migrated.

Branches off main directly.

Methods

`Get`, `GetBySlug`, `GetBySlugForSCIM`, `List(filter)`, `Count`, `ListEnabled`.

`ClientSecretEncrypted` stays encrypted at the boundary — handler decrypts via `internal/crypto` when initiating the OIDC dance. `ScimTokenHash` surfaced because the SCIM auth handler validates incoming bearer tokens against this column.

Field renames follow Go convention: `IssuerUrl` → `IssuerURL` etc.

Call sites migrated (17)

  • `internal/api/idp_handler.go` — 13 sites + `idpToProto` signature
  • `internal/api/sso_handler.go` — 3 sites + URL field renames
  • `internal/scim/auth.go` — 1 site (`GetBySlugForSCIM`)
  • `internal/idp/linker.go` — `LinkOrCreate` signature shifted from `db.IdentityProvidersProjection` → `store.IdentityProvider`
  • `internal/idp/linker_test.go` — test fixtures

Non-goals

  • Write-side projector queries (Insert/Update/SetSCIMEnabled/RotateSCIMToken) — pure projector internals in `internal/projectors/identity_provider_listener.go`, stay on `Queries()` per the established pattern.
  • SCIM user/group mapping queries — separate SCIM-domain sub-wave.

Acceptance

  • Build / vet / staticcheck / gofmt: clean.
  • Tests pass: `TestIdp*`, `TestSSO*`, `TestLinkOrCreate`, `TestSCIMAuth` (93s of coverage).

Part of #242. Closes #259.

Summary by CodeRabbit

  • Refactor
    • Identity-provider access moved to a repository-backed implementation for consistent data handling.
    • SSO flows (login URL, callback, provider listing) and SCIM bearer auth now use the new provider layer for improved reliability.
    • SCIM operations (enable/disable, token rotation, group/user sync) reflect consistent provider fields and behavior.
    • Paginated identity-provider listings now include total counts and consistent provider field mappings.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ae827d27-2384-4bad-8e50-3d1d45412bdd

📥 Commits

Reviewing files that changed from the base of the PR and between 0903950 and ff6a5f1.

📒 Files selected for processing (7)
  • internal/scim/auth.go
  • internal/scim/groups.go
  • internal/scim/groups_helpers.go
  • internal/scim/groups_mutate.go
  • internal/scim/users.go
  • internal/scim/users_helpers.go
  • internal/scim/users_mutate.go

📝 Walkthrough

Walkthrough

Migrates identity-provider read access to a new store.Repos().IdentityProvider: adds domain types and repo interface, implements a Postgres repo, wires it into Repos, and updates handler, SSO, SCIM, and linker call sites to use the new repo and struct types.

Changes

Identity Provider Repository Migration

Layer / File(s) Summary
Domain contracts: IdentityProvider model and repository interface
internal/store/identity_provider.go
IdentityProvider struct models OIDC/SSO and SCIM configuration; ListIdentityProvidersFilter adds pagination; IdentityProviderRepo interface defines Get, GetBySlug, GetBySlugForSCIM, List, Count, and ListEnabled.
Postgres repository implementation with domain mapping
internal/store/postgres/identity_provider.go
Implements IdentityProviderRepo using sqlc queries, translates not-found errors where appropriate, and maps generated.IdentityProvidersProjection to store.IdentityProvider (casting attribute/group mappings to json.RawMessage).
Repository wiring into Repos infrastructure
internal/store/repos.go, internal/store/postgres/wire.go
Adds IdentityProvider IdentityProviderRepo to Repos and initializes it in NewRepos with NewIdentityProvider(q).
IDP handler call-site migration (CRUD, validation, SCIM prefetch, and proto conversion)
internal/api/idp_handler.go
Replaces h.store.Queries() lookups with h.store.Repos().IdentityProvider calls across duplicate-slug checks, create/get/update read-backs, paginated listing/count, SCIM enable/disable, token rotation preloads; updates idpToProto to accept store.IdentityProvider and use corrected URL field names.
SSO handler call-site migration (login flow and URL field mapping)
internal/api/sso_handler.go
ListAuthMethods uses ListEnabled; GetSSOLoginURL and SSOCallback use GetBySlug/Get from Repos; OIDC provider URL fields use IssuerURL, AuthorizationURL, TokenURL, UserinfoURL.
IDP internal call-site migration (SCIM bearer auth and linker signature)
internal/scim/auth.go, internal/idp/linker.go, internal/idp/linker_test.go
SCIM withAuth now uses GetBySlugForSCIM from Repos; Linker.LinkOrCreate signature updated to accept store.IdentityProvider; tests adjusted to pass the new type.
SCIM handlers and helpers provider-type updates
internal/scim/groups.go, internal/scim/groups_helpers.go, internal/scim/groups_mutate.go, internal/scim/users.go, internal/scim/users_helpers.go, internal/scim/users_mutate.go
Various SCIM group/user handlers and helpers now accept store.IdentityProvider instead of the generated projection type; internal logic continues to reference provider.ID.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I swapped old queries for tidy repos,
Fields with URLs in neat little rows.
Secrets stay locked, SCIM tokens still gleam,
Seventeen paths now follow one streamlined scheme.
🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main change: implementing the read-side IdentityProviderRepo as part of wave B.8 of a store refactoring effort.
Linked Issues check ✅ Passed All code changes meet the linked issue requirements: IdentityProviderRepo interface implemented with Get/GetBySlug/GetBySlugForSCIM/List/Count/ListEnabled methods, all 17 call sites migrated, ClientSecretEncrypted kept encrypted, ScimTokenHash surfaced, field names updated to Go conventions, and write-side operations correctly excluded.
Out of Scope Changes check ✅ Passed All changes are directly scoped to read-side identity provider repository implementation and migration of call sites; no out-of-scope modifications to write-side projector queries or SCIM user/group mapping queries detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/259-identityprovider-repo

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/scim/auth.go`:
- Line 59: The code stores a store.IdentityProvider into context but later
asserts it as db.IdentityProvidersProjection, causing the retrieval to fail;
update the type assertions where the context value is read (references around
the IdentityProvider storage and retrieval, e.g., the code that calls
GetBySlugForSCIM and the context get at lines noted) to use the
store.IdentityProvider type instead of db.IdentityProvidersProjection so the
authenticated provider is correctly read from context (ensure both the store
assignment and the subsequent assertions use the same store.IdentityProvider
type).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4ed6254e-7c64-4fe8-a91e-2dc3f883ade6

📥 Commits

Reviewing files that changed from the base of the PR and between 8e6bf70 and aadbede.

📒 Files selected for processing (9)
  • internal/api/idp_handler.go
  • internal/api/sso_handler.go
  • internal/idp/linker.go
  • internal/idp/linker_test.go
  • internal/scim/auth.go
  • internal/store/identity_provider.go
  • internal/store/postgres/identity_provider.go
  • internal/store/postgres/wire.go
  • internal/store/repos.go

Comment thread internal/scim/auth.go
IdentityProviderRepo covers the read side of the identity-providers
projection: Get / GetBySlug / GetBySlugForSCIM / List / Count /
ListEnabled. All 17 handler/scim/idp-internal read sites migrated.

ClientSecretEncrypted stays encrypted at the boundary; the handler
decrypts via internal/crypto when initiating the OIDC dance.
ScimTokenHash is surfaced because the SCIM auth handler validates
incoming bearer tokens against this column.

Field renames at the type boundary follow Go convention:
IssuerUrl → IssuerURL, AuthorizationUrl → AuthorizationURL, etc.
Propagated to all consumers including sso_handler's OIDC provider
config and idpToProto.

Call sites migrated (17):
- internal/api/idp_handler.go (13) + idpToProto signature
- internal/api/sso_handler.go (3) + URL field renames
- internal/scim/auth.go (1)
- internal/idp/linker.go — LinkOrCreate signature shifted to
  store.IdentityProvider (callers in api/sso updated accordingly)
- internal/idp/linker_test.go — test fixtures use store.IdentityProvider

Non-goals:
- Write-side projector queries (Insert/Update/SetSCIMEnabled/
  RotateSCIMToken) stay on Queries() per the established pattern;
  pure projector internals migrate in a later wave.
- SCIM user/group mapping queries — separate SCIM-domain sub-wave.

Closes #259.
@PaulDotterer PaulDotterer force-pushed the feat/259-identityprovider-repo branch from aadbede to 0903950 Compare May 15, 2026 20:38
The withAuth middleware now stores store.IdentityProvider in context
but providerFromContext was still asserting db.IdentityProvidersProjection,
so every authenticated SCIM request failed the type assertion and the
handlers downstream returned 401.

Swap the context cast and every downstream helper that takes the
provider to use store.IdentityProvider. Field accesses (ID, Slug, Name,
DefaultRoleID, AutoLinkByEmail, ScimTokenHash) are identical between
the two types so no further site changes are needed.
@PaulDotterer PaulDotterer merged commit d4c72f1 into main May 15, 2026
5 checks passed
@PaulDotterer PaulDotterer deleted the feat/259-identityprovider-repo branch May 15, 2026 21:14
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.

wave B.8: identity_provider repo (read side)

1 participant