Skip to content

SDKS-5067: Standardize SDK Configuration#684

Open
SteinGabriel wants to merge 1 commit into
mainfrom
SDKS-5067
Open

SDKS-5067: Standardize SDK Configuration#684
SteinGabriel wants to merge 1 commit into
mainfrom
SDKS-5067

Conversation

@SteinGabriel

@SteinGabriel SteinGabriel commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

https://pingidentity.atlassian.net/browse/SDKS-5067

Implements a unified cross-platform JSON configuration schema for the JS SDK. A new sdk-utilities config
module validates and maps the unified JSON shape to each factory's native config type. All three factories
(oidc, journey, davinci) retain their existing typed config parameter — callers convert unified JSON via
makeOidcConfig / makeJourneyConfig / makeDavinciConfig before passing it in. Non-breaking: existing
native config objects continue to work unchanged.

Changes

packages/sdk-types

  • config.types.tsOidcConfig, JourneyClientConfig, JourneyServerConfig, DaVinciConfig moved here as
    canonical definitions; extended with signOutRedirectUri, loginHint, state, nonce, display, prompt,
    uiLocales, acrValues, query, log on OidcConfig
  • authorize.types.tsGetAuthorizationUrlOptions extended with loginHint, nonce, display,
    uiLocales, acrValues; prompt widened to include 'select_account'; AuthDisplayValue and
    AuthPromptValue defined here

packages/sdk-utilities

  • New src/lib/config/ module:
    • config.types.tsUnifiedSdkConfig, UnifiedOidcConfig, LogLevelString, re-exports
      AuthDisplayValue, AuthPromptValue from sdk-types; no enums, type/interface only
    • config.utils.ts — pure validation and mapping; uses effect Either.Either<T, ConfigValidationError[]>
      for results:
      • validateUnifiedOidcConfig / validateUnifiedSdkConfig — required-field and type checks; strict mode for
        oidc/davinci, lenient (only discoveryEndpoint required) for journey
      • isUnifiedSdkConfig — discriminator: 'oidc' in input || 'journey' in input
      • unifiedToOidcConfig / unifiedToJourneyConfig / unifiedToDavinciConfig — pure mappers: scopes[]
        scope string, refreshThreshold (sec) → oauthThreshold (ms), loglogLevel, discoveryEndpoint
        serverConfig.wellknown
      • makeOidcConfig(json) / makeJourneyConfig(json) / makeDavinciConfig(json) — public entry points;
        validate + map + throw on invalid; return the native typed config
    • config/index.ts — barrel export
  • src/index.ts — exports config module

packages/oidc-client

  • config.types.ts — re-export shim; canonical types now in sdk-types
  • oidc.api.ts — appends post_logout_redirect_uri to end-session URL when config.signOutRedirectUri is set
  • authorize.request.utils.ts / authorize.request.micros.ts — use AuthPromptValue from sdk-utilities (was
    duplicate local PromptValue)
  • client.store.tsauthorize.url() forwards new OIDC params (loginHint, state, nonce, display,
    prompt, uiLocales, acrValues, query) from config into createAuthorizeUrl

packages/journey-client

  • config.types.ts — re-export shim; canonical types now in sdk-types

packages/davinci-client

  • config.types.ts — re-export shim; canonical types now in sdk-types

packages/sdk-effects/oidc

  • authorize.utils.tsbuildAuthorizeParams wires loginHint, nonce, display, uiLocales, acrValues
    into the authorize URL

Tests

  • 586-line config.test.ts in sdk-utilities: valid mapping for all three factories, each
    required-field-missing error, type-mismatch errors, unknown-field-ignored, refreshThresholdoauthThreshold
    conversion, scopes join, log field mapping, cookieName non-mapping
  • client.store.test.ts in oidc-client, journey-client, davinci-client: success path + two throw cases
    each (validation failure, mapping failure) via make*Config
  • authorize.test.ts in sdk-effects/oidc: 6 tests covering each new OIDC param individually and all together
  • Updated authorize.request.micros.test.ts, authorize.request.utils.test.ts, logout.request.test.ts in
    oidc-client for new config shape

How to test

1. Unit tests

pnpm --filter @forgerock/sdk-utilities test
pnpm --filter @forgerock/oidc-client test
pnpm --filter @forgerock/journey-client test
pnpm --filter @forgerock/davinci-client test

All suites should pass.

2. Unified JSON config — factory entry

import { makeOidcConfig } from '@forgerock/sdk-utilities';
import { oidc } from '@forgerock/oidc-client';

const client = await oidc({
  config: makeOidcConfig({
    oidc: {
      clientId: 'my-client',
      discoveryEndpoint: 'https://example.com/.well-known/openid-configuration',
      scopes: ['openid', 'profile', 'email'],
      redirectUri: 'https://localhost:3000/callback',
    },
  }),
});

Factory should initialize successfully. Remove clientId → makeOidcConfig should throw Invalid unified SDK
config: oidc.clientId: ....

3. Legacy config — backward compat

Pass an existing OidcConfig / JourneyClientConfig / DaVinciConfig object directly as config. Factory should
initialize without change.

4. Verify OIDC authorize params

Call authorize.url() with loginHint, nonce, display, uiLocales, acrValues set on the config. Inspect the
returned URL — each param should appear as a query string key.

Call user.logout() with signOutRedirectUri set on the config — verify post_logout_redirect_uri appears in the
end-session URL.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
* Added unified JSON configuration support with `makeOidcConfig`, `makeJourneyConfig`, and `makeDavinciConfig` utilities for seamless config conversion across platforms.
* Extended authorization parameters: `loginHint`, `nonce`, `display`, `uiLocales`, and `acrValues` for enhanced OIDC flows.
* Added `signOutRedirectUri` support for post-logout redirect configuration.

* **Improvements**
* Enhanced logger level fallback handling with nullish coalescing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

@changeset-bot

changeset-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 23202ab

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
@forgerock/sdk-utilities Minor
@forgerock/sdk-types Minor
@forgerock/sdk-logger Minor
@forgerock/sdk-oidc Minor
@forgerock/oidc-client Minor
@forgerock/journey-client Minor
@forgerock/davinci-client Minor
@forgerock/storage Minor
@forgerock/device-client Minor
@forgerock/protect Minor
@forgerock/iframe-manager Minor
@forgerock/sdk-request-middleware Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@nx-cloud

nx-cloud Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 23202ab

Command Status Duration Result
nx run-many -t build --no-agents ✅ Succeeded <1s View ↗
nx affected -t build lint test typecheck e2e-ci ✅ Succeeded 2m 15s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-06-16 23:10:42 UTC

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds unified cross-platform SDK configuration support: @forgerock/sdk-types gains canonical OidcConfig, JourneyClientConfig, DaVinciConfig, LogLevel, AuthDisplayValue, and AuthPromptValue types; @forgerock/sdk-utilities gains Either-based validators/mappers and makeOidcConfig/makeJourneyConfig/makeDavinciConfig factories; OIDC authorize URL construction gains login_hint/nonce/display/ui_locales/acr_values forwarding; endSession gains post_logout_redirect_uri support; all three client packages re-export config types from sdk-types.

Changes

Unified SDK config adoption across clients

Layer / File(s) Summary
Shared config and authorize type contracts in sdk-types
packages/sdk-types/src/lib/config.types.ts, packages/sdk-types/src/lib/authorize.types.ts
LogLevel, OidcConfig, JourneyServerConfig, JourneyClientConfig, DaVinciConfig, AuthDisplayValue, and AuthPromptValue added; GetAuthorizationUrlOptions extended with loginHint, nonce, display, uiLocales, acrValues and prompt widened to AuthPromptValue.
Unified config types, validators, mappers, and factory functions in sdk-utilities
packages/sdk-utilities/src/lib/config/config.types.ts, packages/sdk-utilities/src/lib/config/config.utils.ts, packages/sdk-utilities/src/lib/config/index.ts, packages/sdk-utilities/src/index.ts, packages/sdk-utilities/package.json, packages/sdk-utilities/src/lib/config/config.test.ts
New config module defines UnifiedOidcConfig/UnifiedJourneyConfig/UnifiedSdkConfig interfaces and ConfigValidationError; exports Either-based validateUnifiedOidcConfig/validateUnifiedSdkConfig; adds unifiedToOidcConfig/unifiedToJourneyConfig/unifiedToDavinciConfig mappers; makeOidcConfig/makeJourneyConfig/makeDavinciConfig throwing factories wired through fromJson; effect dependency added; 562-line test suite covers all validators, mappers, and factory functions.
LogLevel centralization in sdk-effects logger
packages/sdk-effects/logger/src/lib/logger.types.ts, packages/sdk-effects/logger/package.json, packages/sdk-effects/logger/tsconfig.lib.json
LogLevel re-exported from @forgerock/sdk-types replacing local union; @forgerock/sdk-types workspace dependency and tsconfig project reference added.
OIDC authorize parameter expansion in sdk-effects and PAR micros
packages/sdk-effects/oidc/src/lib/authorize.utils.ts, packages/sdk-effects/oidc/src/lib/authorize.test.ts, packages/oidc-client/src/lib/authorize.request.utils.ts, packages/oidc-client/src/lib/authorize.request.micros.ts, packages/oidc-client/src/lib/authorize.request.micros.test.ts, packages/oidc-client/src/lib/authorize.request.utils.test.ts
buildAuthorizeParams conditionally emits login_hint, nonce, display, ui_locales, acr_values; PAR micros buildParBodyµ/buildParSlimUrlµ and ParUrlParams.prompt migrate from local PromptValue to AuthPromptValue; test imports adjusted and new per-parameter and combined tests added.
OIDC client: config type re-sourcing, unified config entry, and authorize option wiring
packages/oidc-client/src/lib/config.types.ts, packages/oidc-client/src/lib/client.store.ts, packages/oidc-client/src/lib/client.store.test.ts, packages/oidc-client/api-report/oidc-client.api.md, packages/oidc-client/api-report/oidc-client.types.api.md
OidcConfig re-exported from sdk-types; oidc() logger uses nullish-coalescing fallback logger?.level ?? config.log ?? 'error'; authorize.url() defaults conditionally spread loginHint, nonce, acrValues, etc. from config; unified config test suite added; API reports updated.
OIDC end-session signOutRedirectUri propagation
packages/oidc-client/src/lib/oidc.api.ts, packages/oidc-client/src/lib/logout.request.ts, packages/oidc-client/src/lib/logout.request.test.ts, packages/oidc-client/api-report/oidc-client.api.md
endSession mutation input gains signOutRedirectUri?: string; URL builder appends post_logout_redirect_uri when set; logoutµ wires config.signOutRedirectUri through; tests add signOutRedirectUri present/absent MSW assertions and refactor to Micro.runPromise style; EnhancedStore API reports updated.
Journey client: config type re-sourcing and unified config entry
packages/journey-client/src/lib/config.types.ts, packages/journey-client/src/lib/client.store.ts, packages/journey-client/src/lib/client.store.test.ts, packages/journey-client/api-report/journey-client.api.md, packages/journey-client/api-report/journey-client.types.api.md
JourneyServerConfig/JourneyClientConfig re-exported from sdk-types; journey() logger uses nullish-coalescing fallback; unified config test suite added; API reports updated.
DaVinci client: config type re-sourcing and unified config entry
packages/davinci-client/src/lib/config.types.ts, packages/davinci-client/src/lib/client.store.ts, packages/davinci-client/src/lib/client.store.test.ts, packages/davinci-client/api-report/davinci-client.api.md, packages/davinci-client/api-report/davinci-client.types.api.md
DaVinciConfig re-exported from sdk-types; davinci() logger uses nullish-coalescing fallback; unified config test suite added; API reports updated.
Changeset documentation and copyright updates
.changeset/sdks-5067-unified-config.md
Records minor/patch version bumps and documents unified config feature, OIDC param additions, endSession behavior, and call-site usage for all affected packages.

Sequence Diagrams

sequenceDiagram
  participant App
  participant makeOidcConfig
  participant validateUnifiedSdkConfig
  participant unifiedToOidcConfig
  participant oidc as oidc() client

  App->>makeOidcConfig: makeOidcConfig(unifiedJson)
  makeOidcConfig->>validateUnifiedSdkConfig: validate(unifiedJson)
  validateUnifiedSdkConfig-->>makeOidcConfig: Either.right(UnifiedSdkConfig) or throws
  makeOidcConfig->>unifiedToOidcConfig: map(UnifiedSdkConfig)
  unifiedToOidcConfig-->>makeOidcConfig: Either.right(OidcConfig) or throws
  makeOidcConfig-->>App: OidcConfig
  App->>oidc: oidc({ config: OidcConfig })
  oidc-->>App: { authorize, token, ... }
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • ForgeRock/ping-javascript-sdk#557: Both PRs touch JourneyClientConfig in @forgerock/journey-client#557 extends it from AsyncLegacyConfigOptions handling legacy props, while this PR aligns exported config types by re-exporting the canonical shape from @forgerock/sdk-types.
  • ForgeRock/ping-javascript-sdk#417: Both PRs modify logoutµ in packages/oidc-client/src/lib/logout.request.ts#417 adjusts storage-client propagation during logout while this PR adds signOutRedirectUripost_logout_redirect_uri to the end-session payload.
  • ForgeRock/ping-javascript-sdk#631: Both PRs modify PAR authorization helpers in packages/oidc-client/src/lib/authorize.request.micros.ts#631 implements PAR support while this PR retyped the prompt parameter from local PromptValue to canonical AuthPromptValue.

Suggested reviewers

  • cerebrl
  • ryanbas21
  • ancheetah

Poem

🐇 Hop, hop, a config so fine,
One JSON to rule every client's line!
makeOidcConfig, makeJourneyConfig too,
makeDavinciConfig — the whole SDK crew.
Validators guard with an Either so bright,
The bunny says: unified config feels right! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% 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
Title check ✅ Passed The PR title 'SDKS-5067: Standardize SDK Configuration' directly and clearly summarizes the main change: implementing a unified SDK configuration system across platforms.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering summary, detailed changes across packages, tests, and testing procedures. It exceeds the template requirements by providing substantial implementation details.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch SDKS-5067

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@pkg-pr-new

pkg-pr-new Bot commented Jun 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

@forgerock/davinci-client

pnpm add https://pkg.pr.new/@forgerock/davinci-client@684

@forgerock/device-client

pnpm add https://pkg.pr.new/@forgerock/device-client@684

@forgerock/journey-client

pnpm add https://pkg.pr.new/@forgerock/journey-client@684

@forgerock/oidc-client

pnpm add https://pkg.pr.new/@forgerock/oidc-client@684

@forgerock/protect

pnpm add https://pkg.pr.new/@forgerock/protect@684

@forgerock/sdk-types

pnpm add https://pkg.pr.new/@forgerock/sdk-types@684

@forgerock/sdk-utilities

pnpm add https://pkg.pr.new/@forgerock/sdk-utilities@684

@forgerock/iframe-manager

pnpm add https://pkg.pr.new/@forgerock/iframe-manager@684

@forgerock/sdk-logger

pnpm add https://pkg.pr.new/@forgerock/sdk-logger@684

@forgerock/sdk-oidc

pnpm add https://pkg.pr.new/@forgerock/sdk-oidc@684

@forgerock/sdk-request-middleware

pnpm add https://pkg.pr.new/@forgerock/sdk-request-middleware@684

@forgerock/storage

pnpm add https://pkg.pr.new/@forgerock/storage@684

commit: 23202ab

@codecov-commenter

codecov-commenter commented Jun 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.95817% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 21.99%. Comparing base (eafe277) to head (23202ab).
⚠️ Report is 31 commits behind head on main.

Files with missing lines Patch % Lines
...kages/sdk-utilities/src/lib/config/config.utils.ts 98.02% 4 Missing ⚠️
packages/sdk-utilities/src/lib/config/index.ts 25.00% 3 Missing ⚠️
packages/sdk-utilities/src/index.ts 0.00% 1 Missing ⚠️

❌ Your project status has failed because the head coverage (21.99%) is below the target coverage (40.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #684      +/-   ##
==========================================
+ Coverage   18.07%   21.99%   +3.92%     
==========================================
  Files         155      158       +3     
  Lines       24398    25094     +696     
  Branches     1203     1513     +310     
==========================================
+ Hits         4410     5520    +1110     
+ Misses      19988    19574     -414     
Files with missing lines Coverage Δ
packages/davinci-client/src/lib/client.store.ts 25.75% <100.00%> (+25.46%) ⬆️
packages/davinci-client/src/lib/config.types.ts 100.00% <ø> (ø)
packages/journey-client/src/lib/client.store.ts 83.68% <100.00%> (+3.17%) ⬆️
...es/oidc-client/src/lib/authorize.request.micros.ts 89.36% <100.00%> (ø)
...ges/oidc-client/src/lib/authorize.request.utils.ts 100.00% <ø> (+56.66%) ⬆️
packages/oidc-client/src/lib/client.store.ts 38.64% <100.00%> (+10.93%) ⬆️
packages/oidc-client/src/lib/config.types.ts 100.00% <ø> (ø)
packages/oidc-client/src/lib/logout.request.ts 100.00% <100.00%> (ø)
packages/oidc-client/src/lib/oidc.api.ts 65.81% <100.00%> (+18.60%) ⬆️
...ackages/sdk-effects/logger/src/lib/logger.types.ts 100.00% <ø> (ø)
... and 8 more

... and 12 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Deployed e8f6353 to https://ForgeRock.github.io/ping-javascript-sdk/pr-684/e8f6353bdc50db4bb6921dc12d0ce057aae55f13 branch gh-pages in ForgeRock/ping-javascript-sdk

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Size Analysis

📦 Bundle Size Analysis

🆕 New Packages

🆕 @forgerock/oidc-client - 30.6 KB (new)
🆕 @forgerock/sdk-types - 8.5 KB (new)
🆕 @forgerock/davinci-client - 53.8 KB (new)
🆕 @forgerock/sdk-utilities - 15.4 KB (new)
🆕 @forgerock/device-client - 0.0 KB (new)
🆕 @forgerock/device-client - 10.0 KB (new)
🆕 @forgerock/journey-client - 0.0 KB (new)
🆕 @forgerock/journey-client - 92.6 KB (new)
🆕 @forgerock/protect - 144.6 KB (new)
🆕 @forgerock/iframe-manager - 2.4 KB (new)
🆕 @forgerock/sdk-logger - 1.6 KB (new)
🆕 @forgerock/storage - 1.5 KB (new)
🆕 @forgerock/sdk-request-middleware - 4.6 KB (new)
🆕 @forgerock/sdk-oidc - 5.7 KB (new)


14 packages analyzed • Baseline from latest main build

Legend

🆕 New package
🔺 Size increased
🔻 Size decreased
➖ No change

ℹ️ How bundle sizes are calculated
  • Current Size: Total gzipped size of all files in the package's dist directory
  • Baseline: Comparison against the latest build from the main branch
  • Files included: All build outputs except source maps and TypeScript build cache
  • Exclusions: .map, .tsbuildinfo, and .d.ts.map files

🔄 Updated automatically on each push to this PR

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.

Nx Cloud has identified a possible root cause for your failed CI:

This CI failure appears to be related to the environment or external dependencies rather than your code changes.

No code changes were suggested for this issue.

Trigger a rerun:

Rerun CI

Nx Cloud View detailed reasoning on Nx Cloud ↗


🎓 Learn more about Self-Healing CI on nx.dev

Comment thread packages/davinci-client/src/lib/client.store.ts Outdated
@@ -4,7 +4,7 @@
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let's use @effect/vitest if we're testing effect returning functions

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated it. Thanks!

Comment thread packages/oidc-client/src/lib/authorize.request.utils.test.ts
Comment thread packages/sdk-utilities/src/lib/config/config.utils.ts Outdated

const REQUIRED_OIDC_FIELDS_JOURNEY: ReadonlyArray<keyof UnifiedOidcConfig> = ['discoveryEndpoint'];

function validateType(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

per our discussion today, this could be a worthwhile case for Either<_,ConfigValidationError]> and accumulate errors in the error channel

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated it to use Either instead. Thanks for the suggestion!

@ryanbas21 ryanbas21 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we really need to think about this. I'm concerned about how safe some of our changes here are, breaking changes, and the path we're taking here. I personally feel like we should discuss this more as a team because i'm not positive that this is the right path

@ancheetah ancheetah left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Couple comments after a quick initial scan

logger,
}: {
config: DaVinciConfig;
config: DaVinciConfig | Record<string, unknown>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In Andy's design doc, he suggests initializing the client through a new property called json which contains the json config. Is there a reason why you deviated from this? I think it may be a good idea to distinguish between the standard config and json config. The typing could also be a little more strict than Record<string, unknown>. If we have agreed on a standard JSON config as a team then we should be able to create an interface for it. This also removes the need for a isUnifiedSdkConfig utility.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Goal was to accept both legacy and unified configs, but for sure this was not the ideal way to achieve this. An utility function was added that validates and returns the config type each client expects, so the client interfaces stay the same.

Comment thread packages/davinci-client/src/lib/client.store.ts Outdated

@vatsalparikh vatsalparikh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

First review, mostly around type definition, usage, and duplications.

Side note: I do want to third (after AJ and Ryan) that we should think about narrowing the acceptable types for config instead of Record<string, unknown>

Comment thread packages/sdk-utilities/src/lib/config/config.types.ts Outdated
Comment thread packages/sdk-utilities/src/lib/config/config.types.ts Outdated
Comment thread packages/oidc-client/api-report/oidc-client.api.md Outdated
Comment thread packages/sdk-utilities/src/lib/config/config.types.ts Outdated
*/
export async function davinci<ActionType extends ActionTypes = ActionTypes>({
config,
config: rawConfig,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Rather than handling this new config structure in each client like we are doing here, I'd rather see a utility function that transforms this new config to our existing config. Something like this:

const davinciClient = davinci(configUtil(unifiedConfig));

The configUtil validates the unified config object and returns the strongly typed config structure that is already in use.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added a utility function for each client that vaidates and creates the right config type from the unified config.
Thanks!

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/oidc-client/api-report/oidc-client.api.md (1)

241-266: ⚠️ Potential issue | 🔴 Critical

Remove duplicate OauthTokens interface declaration.

The OauthTokens interface is declared twice in packages/oidc-client/src/lib/config.types.ts (lines 9-15 and 17-23) with identical content. In TypeScript, the second declaration overrides the first, making the duplicate redundant. Remove one of the declarations.

🤖 Prompt for 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.

In `@packages/oidc-client/api-report/oidc-client.api.md` around lines 241 - 266,
The OauthTokens interface is declared twice identically in the source file,
causing the duplicate to appear in the API report. Locate the two identical
OauthTokens interface declarations (one without the `@public` decorator and one
with it) and remove the second duplicate declaration, keeping only the first
one. This will eliminate the redundant interface from the API report file.
🧹 Nitpick comments (5)
packages/sdk-utilities/src/lib/config/config.utils.ts (4)

49-51: ⚡ Quick win

Improve error message for array inputs.

The check typeof input !== 'object' || input === null doesn't explicitly reject arrays. While arrays will fail validation later, the error message "Expected object, got object" is confusing when the input is an array.

📝 Suggested improvement
-  if (typeof input !== 'object' || input === null) {
-    return Either.left([{ field: prefix, message: `Expected object, got ${typeof input}` }]);
+  if (typeof input !== 'object' || input === null || Array.isArray(input)) {
+    return Either.left([{ field: prefix, message: `Expected object, got ${Array.isArray(input) ? 'array' : typeof input}` }]);
   }
🤖 Prompt for 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.

In `@packages/sdk-utilities/src/lib/config/config.utils.ts` around lines 49 - 51,
The type check in the condition at this location does not explicitly reject
arrays, which causes confusing error messages since typeof array returns
'object'. Modify the condition to additionally check if the input is an array
using Array.isArray(), and update the error message to properly distinguish
between array and non-object types by checking for arrays first and returning a
message like "Expected object, got array" when an array is detected, otherwise
use the existing type-based message.

259-266: ⚡ Quick win

Type guard doesn't explicitly exclude arrays.

The checks for oidc and journey verify they're objects and not null, but typeof [] === 'object' is true in JavaScript. While validation will catch array inputs later, the type guard should be more precise to ensure correct branching logic.

🔍 Suggested improvement
   const oidcIsObject =
-    'oidc' in raw && typeof raw['oidc'] === 'object' && raw['oidc'] !== null;
+    'oidc' in raw && typeof raw['oidc'] === 'object' && raw['oidc'] !== null && !Array.isArray(raw['oidc']);
   const journeyIsObject =
-    'journey' in raw && typeof raw['journey'] === 'object' && raw['journey'] !== null;
+    'journey' in raw && typeof raw['journey'] === 'object' && raw['journey'] !== null && !Array.isArray(raw['journey']);
🤖 Prompt for 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.

In `@packages/sdk-utilities/src/lib/config/config.utils.ts` around lines 259 -
266, The type guard function isUnifiedSdkConfig does not properly exclude arrays
when checking if oidc and journey properties are objects. Since typeof [] ===
'object' is true in JavaScript, arrays will pass the current object type checks.
Add an explicit Array.isArray() check to exclude arrays for both the
oidcIsObject and journeyIsObject conditions, ensuring that only plain objects
(not arrays) satisfy the type guard requirements.

146-148: ⚡ Quick win

Improve error message clarity for arrays.

The array check is present, but the error message doesn't distinguish between arrays and other non-object types. Use the same pattern as line 108 for consistency.

📝 Suggested improvement
     if (typeof raw['journey'] !== 'object' || Array.isArray(raw['journey'])) {
-      return [{ field: 'journey', message: `Expected object, got ${typeof raw['journey']}` }];
+      return [{ field: 'journey', message: `Expected object, got ${Array.isArray(raw['journey']) ? 'array' : typeof raw['journey']}` }];
     }
🤖 Prompt for 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.

In `@packages/sdk-utilities/src/lib/config/config.utils.ts` around lines 146 -
148, The error message for the journey field validation does not distinguish
between array and non-object types in the error message. Update the validation
logic to provide a more specific error message that explicitly states "Expected
object, got array" when the value is an array, following the same pattern used
at line 108 for consistency. This requires checking
Array.isArray(raw['journey']) separately and providing the appropriate error
message for each case rather than using a generic typeof check in the error
message.

130-132: ⚡ Quick win

Improve error message for array inputs.

Same issue as in validateUnifiedOidcConfig (line 49): array inputs should be explicitly rejected with a clear error message.

📝 Suggested improvement
-  if (typeof input !== 'object' || input === null) {
-    return Either.left([{ field: 'config', message: `Expected object, got ${typeof input}` }]);
+  if (typeof input !== 'object' || input === null || Array.isArray(input)) {
+    return Either.left([{ field: 'config', message: `Expected object, got ${Array.isArray(input) ? 'array' : typeof input}` }]);
   }
🤖 Prompt for 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.

In `@packages/sdk-utilities/src/lib/config/config.utils.ts` around lines 130 -
132, The validation check at lines 130-132 does not explicitly reject array
inputs, even though arrays should be invalid. Since typeof array returns
'object' in JavaScript, arrays would currently pass this validation. Add an
explicit check using Array.isArray() to detect and reject array inputs with a
clear error message that distinguishes arrays from other invalid types, similar
to how the issue is already handled in validateUnifiedOidcConfig at line 49.
Update the condition to catch arrays early and return an appropriate error.
packages/oidc-client/src/lib/config.types.ts (1)

9-15: ⚡ Quick win

Remove the duplicate OauthTokens declaration.

OauthTokens is declared twice in this file. Keeping a single declaration avoids unnecessary declaration merging and reduces maintenance risk.

Suggested cleanup
-export interface OauthTokens {
-  accessToken: string;
-  idToken: string;
-  refreshToken?: string;
-  expiresAt?: number;
-  expiryTimestamp?: number;
-}
🤖 Prompt for 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.

In `@packages/oidc-client/src/lib/config.types.ts` around lines 9 - 15, The
OauthTokens interface is declared twice in the file, which causes unnecessary
declaration merging. Locate both declarations of the OauthTokens interface and
remove the duplicate declaration, keeping only one instance that contains all
the necessary properties (accessToken, idToken, refreshToken, expiresAt, and
expiryTimestamp). If the two declarations have different properties, merge them
into a single definition before removing the duplicate.
🤖 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 @.changeset/sdks-5067-unified-config.md:
- Line 23: The changeset documentation on line 23 references incorrect type
names `OidcDisplayValue` and `OidcPromptValue` as being exported from
sdk-utilities, but the actual canonical type names exported from sdk-types are
`AuthDisplayValue` and `AuthPromptValue`. Either remove these type references
from the sdk-utilities bullet point on line 23, or move them to the sdk-types
section (lines 33-35) with the correct type names `AuthDisplayValue` and
`AuthPromptValue`, clarifying that sdk-types is the canonical source for these
types.

---

Outside diff comments:
In `@packages/oidc-client/api-report/oidc-client.api.md`:
- Around line 241-266: The OauthTokens interface is declared twice identically
in the source file, causing the duplicate to appear in the API report. Locate
the two identical OauthTokens interface declarations (one without the `@public`
decorator and one with it) and remove the second duplicate declaration, keeping
only the first one. This will eliminate the redundant interface from the API
report file.

---

Nitpick comments:
In `@packages/oidc-client/src/lib/config.types.ts`:
- Around line 9-15: The OauthTokens interface is declared twice in the file,
which causes unnecessary declaration merging. Locate both declarations of the
OauthTokens interface and remove the duplicate declaration, keeping only one
instance that contains all the necessary properties (accessToken, idToken,
refreshToken, expiresAt, and expiryTimestamp). If the two declarations have
different properties, merge them into a single definition before removing the
duplicate.

In `@packages/sdk-utilities/src/lib/config/config.utils.ts`:
- Around line 49-51: The type check in the condition at this location does not
explicitly reject arrays, which causes confusing error messages since typeof
array returns 'object'. Modify the condition to additionally check if the input
is an array using Array.isArray(), and update the error message to properly
distinguish between array and non-object types by checking for arrays first and
returning a message like "Expected object, got array" when an array is detected,
otherwise use the existing type-based message.
- Around line 259-266: The type guard function isUnifiedSdkConfig does not
properly exclude arrays when checking if oidc and journey properties are
objects. Since typeof [] === 'object' is true in JavaScript, arrays will pass
the current object type checks. Add an explicit Array.isArray() check to exclude
arrays for both the oidcIsObject and journeyIsObject conditions, ensuring that
only plain objects (not arrays) satisfy the type guard requirements.
- Around line 146-148: The error message for the journey field validation does
not distinguish between array and non-object types in the error message. Update
the validation logic to provide a more specific error message that explicitly
states "Expected object, got array" when the value is an array, following the
same pattern used at line 108 for consistency. This requires checking
Array.isArray(raw['journey']) separately and providing the appropriate error
message for each case rather than using a generic typeof check in the error
message.
- Around line 130-132: The validation check at lines 130-132 does not explicitly
reject array inputs, even though arrays should be invalid. Since typeof array
returns 'object' in JavaScript, arrays would currently pass this validation. Add
an explicit check using Array.isArray() to detect and reject array inputs with a
clear error message that distinguishes arrays from other invalid types, similar
to how the issue is already handled in validateUnifiedOidcConfig at line 49.
Update the condition to catch arrays early and return an appropriate error.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 408272e8-09af-432e-a266-9bc32654662e

📥 Commits

Reviewing files that changed from the base of the PR and between 806da7c and b28d227.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (37)
  • .changeset/sdks-5067-unified-config.md
  • packages/davinci-client/api-report/davinci-client.api.md
  • packages/davinci-client/api-report/davinci-client.types.api.md
  • packages/davinci-client/src/lib/client.store.test.ts
  • packages/davinci-client/src/lib/client.store.ts
  • packages/davinci-client/src/lib/config.types.ts
  • packages/journey-client/api-report/journey-client.api.md
  • packages/journey-client/api-report/journey-client.types.api.md
  • packages/journey-client/package.json
  • packages/journey-client/src/lib/client.store.test.ts
  • packages/journey-client/src/lib/client.store.ts
  • packages/journey-client/src/lib/config.types.ts
  • packages/oidc-client/api-report/oidc-client.api.md
  • packages/oidc-client/api-report/oidc-client.types.api.md
  • packages/oidc-client/src/lib/authorize.request.micros.test.ts
  • packages/oidc-client/src/lib/authorize.request.micros.ts
  • packages/oidc-client/src/lib/authorize.request.utils.test.ts
  • packages/oidc-client/src/lib/authorize.request.utils.ts
  • packages/oidc-client/src/lib/client.store.test.ts
  • packages/oidc-client/src/lib/client.store.ts
  • packages/oidc-client/src/lib/config.types.ts
  • packages/oidc-client/src/lib/logout.request.test.ts
  • packages/oidc-client/src/lib/logout.request.ts
  • packages/oidc-client/src/lib/oidc.api.ts
  • packages/sdk-effects/logger/package.json
  • packages/sdk-effects/logger/src/lib/logger.types.ts
  • packages/sdk-effects/logger/tsconfig.lib.json
  • packages/sdk-effects/oidc/src/lib/authorize.test.ts
  • packages/sdk-effects/oidc/src/lib/authorize.utils.ts
  • packages/sdk-types/src/lib/authorize.types.ts
  • packages/sdk-types/src/lib/config.types.ts
  • packages/sdk-utilities/package.json
  • packages/sdk-utilities/src/index.ts
  • packages/sdk-utilities/src/lib/config/config.test.ts
  • packages/sdk-utilities/src/lib/config/config.types.ts
  • packages/sdk-utilities/src/lib/config/config.utils.ts
  • packages/sdk-utilities/src/lib/config/index.ts

Comment thread .changeset/sdks-5067-unified-config.md Outdated
@SteinGabriel SteinGabriel force-pushed the SDKS-5067 branch 4 times, most recently from dd74f99 to a45f2b1 Compare June 15, 2026 20:56

@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 @.changeset/sdks-5067-unified-config.md:
- Line 24: The changeset bullet for `AuthDisplayValue` and `AuthPromptValue`
types contradicts other parts of the PR documentation by claiming
`sdk-utilities` is the canonical source when `sdk-types` is actually documented
as owning these types. Either reword this bullet point to clarify that
`sdk-utilities` re-exports or consumes these types (removing the "canonical
source" claim), or move the canonical source ownership note into the `sdk-types`
section of the changeset where it accurately reflects the actual location of
these type definitions. Choose whichever approach is consistent with the PR
summary and other documentation sections.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6fded97f-445e-46e9-a700-ccf208e5d75c

📥 Commits

Reviewing files that changed from the base of the PR and between dd74f99 and a45f2b1.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (39)
  • .changeset/sdks-5067-unified-config.md
  • e2e/journey-suites/src/login.test.ts
  • packages/davinci-client/api-report/davinci-client.api.md
  • packages/davinci-client/api-report/davinci-client.types.api.md
  • packages/davinci-client/src/lib/client.store.test.ts
  • packages/davinci-client/src/lib/client.store.ts
  • packages/davinci-client/src/lib/config.types.ts
  • packages/journey-client/api-report/journey-client.api.md
  • packages/journey-client/api-report/journey-client.types.api.md
  • packages/journey-client/src/lib/client.store.test.ts
  • packages/journey-client/src/lib/client.store.ts
  • packages/journey-client/src/lib/config.types.ts
  • packages/journey-client/src/lib/journey.utils.ts
  • packages/journey-client/src/types.ts
  • packages/oidc-client/api-report/oidc-client.api.md
  • packages/oidc-client/api-report/oidc-client.types.api.md
  • packages/oidc-client/src/lib/authorize.request.micros.test.ts
  • packages/oidc-client/src/lib/authorize.request.micros.ts
  • packages/oidc-client/src/lib/authorize.request.utils.test.ts
  • packages/oidc-client/src/lib/authorize.request.utils.ts
  • packages/oidc-client/src/lib/client.store.test.ts
  • packages/oidc-client/src/lib/client.store.ts
  • packages/oidc-client/src/lib/config.types.ts
  • packages/oidc-client/src/lib/logout.request.test.ts
  • packages/oidc-client/src/lib/logout.request.ts
  • packages/oidc-client/src/lib/oidc.api.ts
  • packages/sdk-effects/logger/package.json
  • packages/sdk-effects/logger/src/lib/logger.types.ts
  • packages/sdk-effects/logger/tsconfig.lib.json
  • packages/sdk-effects/oidc/src/lib/authorize.test.ts
  • packages/sdk-effects/oidc/src/lib/authorize.utils.ts
  • packages/sdk-types/src/lib/authorize.types.ts
  • packages/sdk-types/src/lib/config.types.ts
  • packages/sdk-utilities/package.json
  • packages/sdk-utilities/src/index.ts
  • packages/sdk-utilities/src/lib/config/config.test.ts
  • packages/sdk-utilities/src/lib/config/config.types.ts
  • packages/sdk-utilities/src/lib/config/config.utils.ts
  • packages/sdk-utilities/src/lib/config/index.ts
✅ Files skipped from review due to trivial changes (6)
  • packages/journey-client/src/lib/journey.utils.ts
  • packages/journey-client/src/types.ts
  • e2e/journey-suites/src/login.test.ts
  • packages/sdk-effects/logger/tsconfig.lib.json
  • packages/oidc-client/src/lib/authorize.request.micros.test.ts
  • packages/journey-client/api-report/journey-client.api.md
🚧 Files skipped from review as they are similar to previous changes (30)
  • packages/oidc-client/src/lib/client.store.ts
  • packages/sdk-utilities/package.json
  • packages/journey-client/src/lib/config.types.ts
  • packages/oidc-client/src/lib/oidc.api.ts
  • packages/sdk-utilities/src/index.ts
  • packages/oidc-client/src/lib/logout.request.ts
  • packages/oidc-client/src/lib/authorize.request.utils.test.ts
  • packages/sdk-effects/oidc/src/lib/authorize.utils.ts
  • packages/sdk-effects/logger/package.json
  • packages/sdk-effects/logger/src/lib/logger.types.ts
  • packages/oidc-client/src/lib/client.store.test.ts
  • packages/davinci-client/src/lib/client.store.test.ts
  • packages/sdk-utilities/src/lib/config/index.ts
  • packages/journey-client/src/lib/client.store.ts
  • packages/sdk-types/src/lib/authorize.types.ts
  • packages/davinci-client/src/lib/client.store.ts
  • packages/journey-client/src/lib/client.store.test.ts
  • packages/sdk-types/src/lib/config.types.ts
  • packages/oidc-client/api-report/oidc-client.api.md
  • packages/davinci-client/src/lib/config.types.ts
  • packages/sdk-utilities/src/lib/config/config.types.ts
  • packages/oidc-client/src/lib/authorize.request.micros.ts
  • packages/davinci-client/api-report/davinci-client.api.md
  • packages/oidc-client/src/lib/config.types.ts
  • packages/davinci-client/api-report/davinci-client.types.api.md
  • packages/journey-client/api-report/journey-client.types.api.md
  • packages/sdk-effects/oidc/src/lib/authorize.test.ts
  • packages/oidc-client/src/lib/logout.request.test.ts
  • packages/sdk-utilities/src/lib/config/config.utils.ts
  • packages/sdk-utilities/src/lib/config/config.test.ts

Comment thread .changeset/sdks-5067-unified-config.md

@vatsalparikh vatsalparikh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some comments on packages/sdk-utilities/src/lib/config/config.utils.ts file

Comment thread e2e/journey-suites/src/login.test.ts Outdated
Comment thread packages/journey-client/src/types.ts Outdated
Comment thread packages/journey-client/src/lib/journey.utils.ts Outdated
Comment thread packages/sdk-utilities/src/lib/config/config.utils.ts Outdated
Comment thread packages/sdk-utilities/src/lib/config/config.utils.ts Outdated
@SteinGabriel SteinGabriel force-pushed the SDKS-5067 branch 3 times, most recently from 7c54ffa to 87a8396 Compare June 16, 2026 21:06

@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: 4

🤖 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 `@packages/sdk-utilities/src/lib/config/config.utils.ts`:
- Around line 56-66: The scopes field validation in the requiredFields flatMap
only checks that scopes is an array type using checkType, but does not validate
that each element within the array is a string. Add validation logic to iterate
through the scopes array elements and check that each one is a string, returning
appropriate validation errors for any non-string elements. This validation needs
to be added at the anchor location
(packages/sdk-utilities/src/lib/config/config.utils.ts lines 56-66) in the
requiredFields flatMap after the checkType call, and the same validation pattern
must be applied to the sibling scopes validation sites at lines 68-77, 197-197,
and 252-252.
- Around line 134-136: The validation for the log field currently only checks if
it is a string type using checkType, but does not validate that the string value
is one of the supported LogLevel values. This allows any arbitrary string to
pass validation and later be force-cast by toMappedLogLevel, potentially causing
runtime issues. Instead of just type-checking as a string, add validation to
ensure the log value matches one of the supported LogLevel enum values. Apply
this fix at line 134-136 where logError is assigned (the checkType call for the
log field) and also at line 212 where similar log validation occurs as indicated
by the consolidated comment.
- Around line 194-200: Guard the `oidc.discoveryEndpoint` value in the
`unifiedToOidcConfig` mapper (lines 194-200) to prevent `serverConfig.wellknown`
from being undefined when malformed input is passed directly to the mapper.
Apply the same guard pattern to `unifiedToJourneyConfig` (lines 223-226) and
`unifiedToDavinciConfig` (lines 249-255), ensuring each mapper validates that
their respective discovery endpoint or equivalent configuration value exists
before including it in the returned serverConfig object. This ensures the
mappers fail safely or provide defined values rather than allowing undefined to
propagate to client initialization.
- Around line 96-99: The validation for refreshThreshold in the checkType call
currently only verifies the type is a number, but does not constrain it to be
finite and non-negative, allowing NaN, Infinity, and negative values through
which can cause unstable behavior. Replace or enhance the type check to
additionally validate that refreshThreshold is finite (using Number.isFinite)
and is greater than or equal to zero. Apply this same stricter validation at the
other locations in the file where similar validation occurs for this field.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 747f2b6e-b8d6-49a4-b705-5ad679eb8030

📥 Commits

Reviewing files that changed from the base of the PR and between ba1d11a and 87a8396.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (36)
  • .changeset/sdks-5067-unified-config.md
  • packages/davinci-client/api-report/davinci-client.api.md
  • packages/davinci-client/api-report/davinci-client.types.api.md
  • packages/davinci-client/src/lib/client.store.test.ts
  • packages/davinci-client/src/lib/client.store.ts
  • packages/davinci-client/src/lib/config.types.ts
  • packages/journey-client/api-report/journey-client.api.md
  • packages/journey-client/api-report/journey-client.types.api.md
  • packages/journey-client/src/lib/client.store.test.ts
  • packages/journey-client/src/lib/client.store.ts
  • packages/journey-client/src/lib/config.types.ts
  • packages/oidc-client/api-report/oidc-client.api.md
  • packages/oidc-client/api-report/oidc-client.types.api.md
  • packages/oidc-client/src/lib/authorize.request.micros.test.ts
  • packages/oidc-client/src/lib/authorize.request.micros.ts
  • packages/oidc-client/src/lib/authorize.request.utils.test.ts
  • packages/oidc-client/src/lib/authorize.request.utils.ts
  • packages/oidc-client/src/lib/client.store.test.ts
  • packages/oidc-client/src/lib/client.store.ts
  • packages/oidc-client/src/lib/config.types.ts
  • packages/oidc-client/src/lib/logout.request.test.ts
  • packages/oidc-client/src/lib/logout.request.ts
  • packages/oidc-client/src/lib/oidc.api.ts
  • packages/sdk-effects/logger/package.json
  • packages/sdk-effects/logger/src/lib/logger.types.ts
  • packages/sdk-effects/logger/tsconfig.lib.json
  • packages/sdk-effects/oidc/src/lib/authorize.test.ts
  • packages/sdk-effects/oidc/src/lib/authorize.utils.ts
  • packages/sdk-types/src/lib/authorize.types.ts
  • packages/sdk-types/src/lib/config.types.ts
  • packages/sdk-utilities/package.json
  • packages/sdk-utilities/src/index.ts
  • packages/sdk-utilities/src/lib/config/config.test.ts
  • packages/sdk-utilities/src/lib/config/config.types.ts
  • packages/sdk-utilities/src/lib/config/config.utils.ts
  • packages/sdk-utilities/src/lib/config/index.ts
✅ Files skipped from review due to trivial changes (4)
  • packages/sdk-utilities/src/lib/config/index.ts
  • packages/oidc-client/src/lib/authorize.request.micros.test.ts
  • packages/oidc-client/api-report/oidc-client.types.api.md
  • packages/journey-client/api-report/journey-client.api.md
🚧 Files skipped from review as they are similar to previous changes (24)
  • packages/sdk-utilities/package.json
  • packages/sdk-effects/logger/tsconfig.lib.json
  • packages/oidc-client/src/lib/client.store.ts
  • packages/sdk-effects/oidc/src/lib/authorize.test.ts
  • packages/oidc-client/src/lib/logout.request.ts
  • packages/oidc-client/src/lib/authorize.request.utils.test.ts
  • packages/davinci-client/src/lib/client.store.test.ts
  • packages/oidc-client/src/lib/config.types.ts
  • packages/davinci-client/src/lib/client.store.ts
  • packages/sdk-utilities/src/lib/config/config.types.ts
  • packages/sdk-utilities/src/index.ts
  • packages/journey-client/src/lib/client.store.ts
  • packages/sdk-types/src/lib/authorize.types.ts
  • packages/oidc-client/src/lib/oidc.api.ts
  • packages/journey-client/src/lib/config.types.ts
  • packages/journey-client/src/lib/client.store.test.ts
  • packages/sdk-types/src/lib/config.types.ts
  • packages/oidc-client/src/lib/authorize.request.micros.ts
  • packages/oidc-client/api-report/oidc-client.api.md
  • packages/sdk-effects/logger/src/lib/logger.types.ts
  • packages/oidc-client/src/lib/client.store.test.ts
  • packages/davinci-client/src/lib/config.types.ts
  • packages/oidc-client/src/lib/authorize.request.utils.ts
  • packages/oidc-client/src/lib/logout.request.test.ts

Comment thread packages/sdk-utilities/src/lib/config/config.utils.ts Outdated
Comment on lines +96 to +99
const refreshThresholdError =
raw['refreshThreshold'] !== undefined && raw['refreshThreshold'] !== null
? checkType(raw['refreshThreshold'], 'number', `${prefix}.refreshThreshold`)
: null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Constrain refreshThreshold to finite non-negative numbers.

typeof number currently permits NaN, Infinity, and negatives, which can map to unstable oauthThreshold values.

Suggested fix
   const refreshThresholdError =
     raw['refreshThreshold'] !== undefined && raw['refreshThreshold'] !== null
-      ? checkType(raw['refreshThreshold'], 'number', `${prefix}.refreshThreshold`)
+      ? typeof raw['refreshThreshold'] !== 'number' ||
+        !Number.isFinite(raw['refreshThreshold']) ||
+        raw['refreshThreshold'] < 0
+        ? ({
+            field: `${prefix}.refreshThreshold`,
+            message: 'Expected a finite number greater than or equal to 0',
+          } satisfies ConfigValidationError)
+        : null
       : null;

Also applies to: 202-202, 257-257

🤖 Prompt for 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.

In `@packages/sdk-utilities/src/lib/config/config.utils.ts` around lines 96 - 99,
The validation for refreshThreshold in the checkType call currently only
verifies the type is a number, but does not constrain it to be finite and
non-negative, allowing NaN, Infinity, and negative values through which can
cause unstable behavior. Replace or enhance the type check to additionally
validate that refreshThreshold is finite (using Number.isFinite) and is greater
than or equal to zero. Apply this same stricter validation at the other
locations in the file where similar validation occurs for this field.

Comment on lines +134 to +136
const logError =
raw['log'] !== undefined && raw['log'] !== null ? checkType(raw['log'], 'string', 'log') : null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate log against supported values before mapping.

validateUnifiedSdkConfig currently accepts any string for log, then toMappedLogLevel force-casts it to LogLevel. Unsupported values can silently pass through as runtime config.

Suggested fix
+const ALLOWED_LOG_LEVELS = ['DEBUG', 'INFO', 'WARN', 'ERROR'] as const;
+
   const logError =
-    raw['log'] !== undefined && raw['log'] !== null ? checkType(raw['log'], 'string', 'log') : null;
+    raw['log'] !== undefined && raw['log'] !== null
+      ? typeof raw['log'] !== 'string'
+        ? ({ field: 'log', message: `Expected string, got ${typeof raw['log']}` } satisfies ConfigValidationError)
+        : !ALLOWED_LOG_LEVELS.includes(raw['log'].toUpperCase() as (typeof ALLOWED_LOG_LEVELS)[number])
+          ? ({ field: 'log', message: `Expected one of ${ALLOWED_LOG_LEVELS.join(', ')}, got ${raw['log']}` } satisfies ConfigValidationError)
+          : null
+      : null;

Also applies to: 212-212

🤖 Prompt for 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.

In `@packages/sdk-utilities/src/lib/config/config.utils.ts` around lines 134 -
136, The validation for the log field currently only checks if it is a string
type using checkType, but does not validate that the string value is one of the
supported LogLevel values. This allows any arbitrary string to pass validation
and later be force-cast by toMappedLogLevel, potentially causing runtime issues.
Instead of just type-checking as a string, add validation to ensure the log
value matches one of the supported LogLevel enum values. Apply this fix at line
134-136 where logError is assigned (the checkType call for the log field) and
also at line 212 where similar log validation occurs as indicated by the
consolidated comment.

Comment on lines +194 to +200
return Either.right({
clientId,
redirectUri,
scope: scopes.join(' '),
serverConfig: {
wellknown: oidc.discoveryEndpoint,
...(config.timeout !== undefined && { timeout: config.timeout }),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard oidc.discoveryEndpoint in each mapper.

The unifiedTo*Config mappers can currently return serverConfig.wellknown: undefined when called directly with malformed input, which then fails later in client initialization.

Suggested fix
   const oidc = config.oidc;
+  if (!oidc.discoveryEndpoint) {
+    return Either.left({ field: 'oidc.discoveryEndpoint', message: 'Required field is missing' });
+  }

Apply the same guard in unifiedToOidcConfig, unifiedToJourneyConfig, and unifiedToDavinciConfig.

Also applies to: 223-226, 249-255

🤖 Prompt for 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.

In `@packages/sdk-utilities/src/lib/config/config.utils.ts` around lines 194 -
200, Guard the `oidc.discoveryEndpoint` value in the `unifiedToOidcConfig`
mapper (lines 194-200) to prevent `serverConfig.wellknown` from being undefined
when malformed input is passed directly to the mapper. Apply the same guard
pattern to `unifiedToJourneyConfig` (lines 223-226) and `unifiedToDavinciConfig`
(lines 249-255), ensuring each mapper validates that their respective discovery
endpoint or equivalent configuration value exists before including it in the
returned serverConfig object. This ensures the mappers fail safely or provide
defined values rather than allowing undefined to propagate to client
initialization.

feat(sdk-utilities): add pure unified config validation

feat(sdk-utilities): add unified config mapping functions

feat(sdk-utilities): export config module from sdk-utilities

test(sdk-utilities): add unit tests for config mapping and validation

feat(sdk-types): add OIDC authorize params to GetAuthorizationUrlOptions

feat(sdk-oidc): wire OIDC authorize params into buildAuthorizeParams

feat(oidc-client): add signOutRedirectUri to endSession URL

feat(oidc-client): accept unified JSON config in oidc factory

feat(journey-client): accept unified JSON config in journey factory

feat(davinci-client): accept unified JSON config in davinci factory

chore: update api-reports for unified config param widening

feat(sdk-utilities): align unified config schema with new journey
sub-object

refactor(sdk-utilities): mapper functions return ConfigMappingResult
with single error

fix(sdk-utilities): map log field and use config.log in factories

fix(sdk-utilities): tighten isUnifiedSdkConfig discriminant to require
object values

fix(oidc-client): use throw instead of Promise.reject in unified config
error paths

refactor(oidc-client): migrate logout.request.test.ts to it +
Micro.runPromise pattern

docs(oidc-client): add JSDoc to OidcConfig and all new fields

fix(sdk): tighten config param types to XConfig | UnifiedSdkConfig

test(oidc-client): migrate authorize.request.micros tests to @effect/vitest

test(oidc-client): migrate authorize.request.utils tests to @effect/vitest

refactor(sdk-utilities): use as const satisfies for required-field constants

refactor(sdk-utilities): replace mutable error array with effect Either in config validators

refactor(sdk): utility-first config — move json→config transform to sdk-utilities

refactor(sdk-utilities): remove LogLevel duplicates — use LogLevel from sdk-types

docs(changeset): update sdks-5067 changeset to reflect utility-first config API

refactor(sdk-utilities): rename *ConfigFromJson to make*Config

refactor(sdk-types): move client config types to sdk-types, delete Mapped* mirrors

fix(oidc-client): remove duplicate OauthTokens interface declaration

fix(oidc-client): remove config.state from OidcConfig — PKCE state must not be overridden

refactor(sdk-utilities): remove isUnifiedSdkConfig — dead code after utility-first refactor

refactor(sdk-utilities): remove strictOidc param — move strict field checks into mappers

fix(sdk-utilities): guard empty scopes array in unifiedToOidcConfig and unifiedToDavinciConfig

refactor(sdk-utilities): move impure config factories to config.effects.ts
import { it, expect } from '@effect/vitest';
import { it } from '@effect/vitest';
import { Micro } from 'effect';
import { vi, afterEach } from 'vitest';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

FWIW - we don't need the vitest import, everything is the same on @effect/vitest. I think for micros/effects we want to use assert also

* of the MIT license. See the LICENSE file for details.
*/

import { Either } from 'effect';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let's namespace import these when possible.

: { field, message: `Expected ${expected}, got ${typeof value}` };
}

export function validateUnifiedOidcConfig(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this is where I start having issues with the PR. I think we're still doing validation not parsing. And this is a brainful to process in my head. (not sure if this is a phrase but i'm using it!)

I think what we can look at to make this more manageable -

We can create a parser per section we need to parse. So perhaps it could be parser per key.

input -> parser -> (input, Either<ParsedConfig, Error[]>) can roughly be how we imagine this function.

Maybe the typescript is:

type ParseResult<A> = Either<A, ConfigValidationError[]>;

type Parser<A> = (input: Record<string, unknown>) => [
  remaining: Record<string, unknown>,
  result: ParseResult<A>,
];

So a clientId parser would:

Take the full input object
Pull out clientId, validate and type it
Return the object minus clientId as remaining, plus Right or Left<Error[]> <-- this part is up for debate since json is a bit weird in that everything is immediately available, however the pattern still is here.

This is typically how parsers work, they take some input, and return the input and the new parsed input. The key is that we can continually compose based on the parsing result whatever it is.

then we can apply the next parser, this finishes when there is no input to parse further, or in our case, when there are no parsers left to apply since we have all the keys at one time.

Then we have a list of parser errors on the left or the final result on the right

This can help us:
A) make the parsing testable
B) break down the logic into smaller bits
C) helps us compose future parsers and extend the logic if new json comes in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

6 participants