Skip to content

feat: [SDK-5238] force the create-user path under Identity Verification - #1505

Merged
sherwinski merged 1 commit into
sherwin/sdk-5236from
sherwin/sdk-5238
Sep 22, 2026
Merged

sherwinski merged 1 commit into
sherwin/sdk-5236from
sherwin/sdk-5238

Conversation

@sherwinski

@sherwinski sherwinski commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Description

1 Line Summary

Under Identity Verification, login goes straight to create-user and never references the anonymous user's id.

Details

Fifth pull request of the M3 stack for Identity Verification for Web SDK. Stacked on SDK-5236. Web mirror of Android LoginHelper.kt:63-71 and LoginUserOperationExecutor.kt:84-96.

src/page/managers/LoginManager.ts

  • existingOneSignalId is undefined when isIvBehaviorActive(). Otherwise it is the current onesignalId only when the current user is anonymous, as before. Under IV the anonymous user was never created on the server, so the identify step would address a user that does not exist.

src/core/executors/LoginUserOperationExecutor.ts

  • _loginUser goes to _createUser when existingOnesignalId is missing, externalId is missing, or isIvBehaviorActive(). The identify step addresses the user by onesignal_id, and the IV alias switch from SDK-5236 would rewrite that to an external_id the server does not know yet, which gives a 404 or a hit on the wrong user. Create-user with external_id in the identity map is an upsert on the server, so it covers both the new and the existing user.
  • The check is isIvBehaviorActive() alone, not isIvCodePathEnabled() && isIvBehaviorActive(). isIvCodePathEnabled is defined as flag || isIvBehaviorActive(), so the outer gate is implied. I can add the outer gate if you want every IV branch to read the same way for the M6 removal.

Follow-up refresh. _createUser already enqueues RefreshUserOperation(appId, backendOneSignalId, externalId). A test now pins that the refresh carries externalId, so the resolver can sign it.

Bundle size. page.es6.js grows by 9 B gzipped to 44.49 kB. The limit moves to the measured size.

Systems Affected

  • WebSDK
  • Backend
  • Dashboard

Validation

Tests

Info

src/page/managers/LoginManager.test.ts, the web mirror of LoginHelperTests.kt:209-269:

  • IV inactive, anonymous user: the LoginUserOperation carries the current onesignalId.
  • IV inactive, identified user: it carries no onesignalId.
  • IV active, anonymous user: it carries no onesignalId.

src/core/executors/LoginUserOperationExecutor.test.ts, create-vs-identify:

  • IV active with existingOnesignalId and externalId: no set-alias request, one POST /users with identity: { external_id }, id translation to the backend id.
  • The follow-up RefreshUserOperation carries the backend onesignalId and externalId.

The existing identify-first tests still pass with IV inactive.

vp check, vp test (759 tests), and vp run build:prod pass.

Checklist

  • All the automated tests pass or I explained why that is not possible
  • I have personally tested this on my machine or explained why that is not possible
  • I have included test coverage for these changes or explained why they are not needed

Programming Checklist
Interfaces:

  • Don't use default export
  • New interfaces are in model files

Functions:

  • Don't use default export
  • All function signatures have return types
  • Helpers should not access any data but rather be given the data to operate on.

Typescript:

  • No Typescript warnings
  • Avoid silencing null/undefined warnings with the exclamation point

Other:

  • Iteration: refrain from using elem of array syntax. Prefer forEach or use map
  • Avoid using global OneSignal accessor for context if possible. Instead, we can pass it to function/constructor so that we don't call OneSignal.context

Screenshots

Info

Not needed. No user-visible change.

Checklist

  • I have included screenshots/recordings of the intended results or explained why they are not needed

Related Tickets

LoginManager passes no existingOnesignalId when the requirement is on.
Under IV the anonymous user was never created on the server, so the
identify step would address a user that does not exist.

LoginUserOperationExecutor goes straight to create-user when IV is
active. The identify step addresses the user by onesignal_id, and the
IV alias switch would rewrite that to an external_id the server does
not know yet. Create-user with external_id is an upsert on the server.

The follow-up RefreshUserOperation already carries externalId; a test
now pins that so the refresh can be signed.

The page bundle grows by 9 B gzipped to 44.56 kB.
@sherwinski
sherwinski merged commit 87288bc into feat/identity-verification Sep 22, 2026
2 of 3 checks passed
@sherwinski
sherwinski deleted the sherwin/sdk-5238 branch September 22, 2026 23:37
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.

2 participants