Skip to content

feat: [SDK-5229] drop anonymous operations at enqueue when Identity Verification is active - #1497

Merged
sherwinski merged 1 commit into
sherwin/sdk-5231from
sherwin/sdk-5229
Sep 22, 2026
Merged

sherwinski merged 1 commit into
sherwin/sdk-5231from
sherwin/sdk-5229

Conversation

@sherwinski

@sherwinski sherwinski commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Description

1 Line Summary

Drop an anonymous operation at enqueue when IV behavior is active, warn the developer, and keep the push grant lenient.

Details

Sixth of 7 M2 pull requests for Identity Verification for Web SDK. Stacked on #1496 (SDK-5231). Targets sherwin/sdk-5231 now; retarget to feat/identity-verification after the earlier PRs merge.

Follows decision D4 in the design doc, recorded on SDK-5215: with the requirement on, the server rejects an unsigned POST apps/{appId}/users, so an anonymous backend user cannot exist. The SDK stays lenient. A prompt-first visitor sees no error; the SDK holds the subscription locally. Mirrors Android OperationRepo.kt:164-182.

Scope: this PR alone does not complete the prompt-first flow in the same session. The exempt anonymous LoginUserOperation stays in the queue, gated forever. A later login(externalId, jwt) enqueues an identified LoginUserOperation with existingOnesignalId set to the anonymous local id, and its _canStartExecute waits for that id to resolve. The anonymous login never runs, so the identified login waits until the next page load, when the purge in SDK-5230 (#1498) removes the anonymous login and clears existingOnesignalId. SDK-5238 (M3, force the create-user path under IV and never carry the anonymous id) completes the in-session flow. Until SDK-5238 merges, do not read this PR as end-to-end prompt-first support.

src/core/operationRepo/OperationRepo.ts

  • _shouldSuppressAnonymousOp(op) runs at the top of _enqueue and _enqueueAndWait, behind the isIvCodePathEnabled outer gate. It returns true when IV behavior is active and the operation has no externalId.
  • LoginUserOperation is exempt. login and the push grant enqueue an anonymous one on purpose, and the purge in SDK-5230 removes a stale one at start.
  • A suppressed operation never enters the queue or the store. _enqueue returns. _enqueueAndWait rejects with OperationFailedError and _result: ExecutionResult._Suppressed.
  • The warning goes through console.warn, not Log._warn, because Log is silent in production builds and the developer needs to see this. Same pattern as the feature flag override warning from M1.

src/shared/managers/subscription/page.ts

  • createSubscribedUser catches the _Suppressed rejection from _enqueueAndWait and returns. The push model stays local in IndexedDB. Once the identified login can start (see the scope note above), LoginManager._switchUser enqueues a TransferSubscriptionOperation and LoginUserOperationExecutor reads the token from the local model, so the create-user request carries the push subscription. Any other rejection still propagates.

Why the dispatch gate is not enough: an anonymous operation can never pass it, so without this PR the operation would sit in the queue forever and block later operations with the same comparison key.

Test changes. Two earlier gate tests and one 401 test enqueued anonymous operations under IV. They now place the operation in the queue directly through a loadIntoQueue helper, which models a row persisted before IV was on. One 401 test left an unconsumed mockResolvedValueOnce that leaked into 3 later tests; the rewrite removes the leak.

Bundle size. Adds 130 B gzipped to page.es6.js. The page limit moves to the measured 44.10 kB.

Systems Affected

  • WebSDK
  • Backend
  • Dashboard

Validation

Tests

Info

src/core/operationRepo/OperationRepo.test.ts, new anonymous operation suppression at enqueue block:

  • IV active: _enqueue drops an anonymous operation, the queue and store stay empty, and console.warn fires once with the operation name.
  • IV active: _enqueueAndWait rejects an anonymous operation with _Suppressed.
  • IV active: an anonymous LoginUserOperation is queued and no warning fires.
  • IV active: an identified operation is queued and no warning fires.
  • IV inactive with the flag on: an anonymous operation is queued and no warning fires.

src/shared/managers/SubscriptionManager.test.ts:

  • under IV, an anonymous push grant resolves without an error, the subscription model stays local, the warning names create-subscription, only the exempt login-user operation is in the queue, and no create-user request is sent.

Not covered: autoResubscribe on a returning device under IV. The SDK-5215 comment lists it as untested. The first-grant path shares the same createSubscribedUser function, so the catch applies to both, but I did not add a test for the returning-device entry point.

vp check, vp test, 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 UI change.

Checklist

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

Related Tickets

… is active

When the app requires a JWT, an anonymous operation can never pass the
dispatch gate because an anonymous user has no token. Drop it at enqueue
time and warn the developer instead of holding it in the queue forever.

- OperationRepo._shouldSuppressAnonymousOp runs in _enqueue and
  _enqueueAndWait, behind the isIvCodePathEnabled outer gate
- LoginUserOperation is exempt so login and the push grant still queue it
- _enqueueAndWait rejects with OperationFailedError(_Suppressed)
- The push grant catches the _Suppressed rejection and keeps the model
  local, so an anonymous visitor under IV does not see an error
- The warning uses console.warn so it shows in production builds
@sherwinski
sherwinski merged commit 7645e77 into feat/identity-verification Sep 22, 2026
1 of 2 checks passed
@sherwinski
sherwinski deleted the sherwin/sdk-5229 branch September 22, 2026 00:29
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