Skip to content

feat: initialize(withProjectId:); the JWT provider restores a signed session after a relaunch; version 19.5.0 - #65

Merged
boehlerlukas merged 1 commit into
mainfrom
feat/project-id-and-provider-restore
Nov 7, 2026
Merged

boehlerlukas merged 1 commit into
mainfrom
feat/project-id-and-provider-restore

Conversation

@boehlerlukas

Copy link
Copy Markdown
Contributor

Implements the Project ID contract (7 Nov 2026) for iOS and ports the identity fix from GleapSDK/JavaScript-SDK#208.

1. "SDK key" is now "Project ID"

  • New: +[Gleap initializeWithProjectId:] (Swift Gleap.initialize(withProjectId:)) and the projectId property.
  • Deprecated aliases that keep working: +[Gleap initializeWithToken:] (Swift initialize(withToken:)) now calls initializeWithProjectId:, and the token property reads and writes projectId. Both are marked __attribute__((deprecated)). That is a compiler warning only, with no runtime log.
  • The value is unchanged, so every existing key keeps working.
  • Internal reads use projectId. The README, the example app and log lines ("already initialized with this Project ID", "check your Project ID") use the new name. The Api-Token header, the apiKey WebSocket query parameter and the sdkKey field sent to the widget are wire names and stay as they are.

2. The JWT provider restores a signed session after a relaunch

The gap existed. setUserJwt keeps the token in memory only. After a relaunch on a Signed project, /sessions answered identity: { mode: 'signed', signed: false } and the grant was dropped. requestSignedGrantIfNeeded returned early because there was no lastIdentifyAction with a hash. A provider set with setUserJwtProvider was only asked when a token expired, so the user stayed unsigned.

Fix (GleapSessionHelper identifyWithProviderForSignedModeIfNeeded, called after the /sessions answer in startSessionWith: and from setUserJwtProvider:). The provider is asked once per app launch (signedModeProviderAsked, reset in clearSession) when all of these hold:

  • the answer says Signed mode and the identified session has no grant (signedGrantMissingFor:)
  • no token or user hash is at hand (lastIdentifyAction without a hash)
  • no identify is queued or in flight
  • a provider is set

The token goes through setUserJwt:, the normal path. That identify is the one signed identify of the session (signedGrantRequestedFor), so there is never a loop. Other behaviour:

  • The gate's guards still apply: one call at a time, 10 s timeout, 30 s pause after a failure.
  • A nil token sends nothing.
  • A logout (sessionEpoch), an identify from the app, or a grant that arrives while the provider runs drops its token.
  • A token for another user goes through the existing identity_mismatch recovery.
  • Header docs, README and CHANGELOG describe the new behaviour.

Tests

New GleapSignedModeProviderTests, 11 tests:

  • the provider is asked once and the identify carries its token, and the grant comes back
  • repeated unsigned answers never loop
  • a nil token sends nothing and the provider is not asked again
  • no provider means no identify
  • a provider set after the session answer is asked
  • no provider call for a Classic answer, an anonymous session or a live grant
  • a token from the app is sent instead of asking the provider
  • a logout while the provider runs drops its token
  • the deprecated token property aliases projectId

GleapRemoteConfigTests now uses initialize(withProjectId:), and one re-initialize goes through the deprecated initializeWithToken: (called through the runtime, so the build stays warning-free). With the restore disabled, the 5 positive provider tests fail. The other 6 cover the guards and pass either way.

Results

  • xcodebuild test -scheme Gleap on the iPhone 18 Pro simulator (Xcode 27.2): 166 tests, 0 failures.
  • pod lib lint was not run locally; CI runs it.

Versioning

Gleap.podspec, SDK_VERSION and CHANGELOG.md move to 19.5.0. This is a minor bump for the new initialize(withProjectId:) API; Android goes to 19.5.0 too to stay in sync. Nothing is tagged or pushed to CocoaPods trunk.

For the wrapper SDKs

  • Call initializeWithProjectId: when building against native 19.5.0 or later. To support older native versions too, check [Gleap respondsToSelector:@selector(initializeWithProjectId:)] and fall back to initializeWithToken:, which works everywhere.
  • The restore logic is native. Wrappers need no logic change; their provider bridge just has to answer within 10 s, pass nil on failure, and work whether it is set before or after initialize.

🤖 Generated with Claude Code

…session after a relaunch; version 19.5.0

Project ID: the key the SDK is initialized with is now called the Project ID.
New Gleap.initialize(withProjectId:) (Objective-C initializeWithProjectId:)
and the projectId property; initialize(withToken:) and the token property
stay as deprecated aliases (compiler deprecation only, no runtime log). The
value is unchanged, so every existing key keeps working. README, the example
app and log lines use the new name.

Identity: setUserJwt keeps the token in memory only, so after a relaunch on a
Signed project the SDK had the session but no token, and a provider set with
setUserJwtProvider was never asked; the user stayed unsigned. When the
/sessions answer says identity.mode "signed" without a grant for an
identified session, no token or user hash is at hand and a provider is set,
the provider is now asked once per app launch and its token goes through
setUserJwt (the one signed identify of the session). The provider's guards
apply, a nil token sends nothing, a logout or an identify of the app while it
runs drops the token, and setUserJwtProvider after the session answer runs
the same check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
boehlerlukas added a commit to GleapSDK/ReactNative-SDK that referenced this pull request Nov 7, 2026
Native iOS SDK 19.5.0 (GleapSDK/Gleap-iOS-SDK#65) adds
initializeWithProjectId: and deprecates initializeWithToken:. The bridge
looks the new selector up at runtime and falls back to initializeWithToken:
(the released 19.4.0), so it builds and runs against both without a
deprecation warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
boehlerlukas added a commit to GleapSDK/Flutter-SDK that referenced this pull request Nov 7, 2026
Native iOS SDK 19.5.0 (GleapSDK/Gleap-iOS-SDK#65) adds
initializeWithProjectId: and deprecates initializeWithToken:. The bridge
looks the new selector up at runtime and falls back to initializeWithToken:
(the released 19.4.0), so it builds and runs against both without a
deprecation warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
boehlerlukas added a commit to GleapSDK/Capacitor-SDK that referenced this pull request Nov 7, 2026
Native iOS SDK 19.5.0 (GleapSDK/Gleap-iOS-SDK#65) adds
initializeWithProjectId: and deprecates initializeWithToken:. The bridge
looks the new selector up at runtime and falls back to initializeWithToken:
(the released 19.4.0), so it builds and runs against both without a
deprecation warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@boehlerlukas
boehlerlukas merged commit b717c24 into main Nov 7, 2026
1 check passed
boehlerlukas added a commit to GleapSDK/Capacitor-SDK that referenced this pull request Nov 7, 2026
…on 19.5.0 (#34)

* feat: initialize({ projectId }) next to the former { API_KEY }; version 19.5.0

- GleapInitializeOptions: projectId (new) and API_KEY (deprecated alias of
  the same value).
- The plugin wrapper sends the Project ID under both names, so JavaScript
  updated over the air keeps working on an older native build. iOS and
  Android read projectId and fall back to API_KEY, then call
  initialize(withToken:) / Gleap.initialize(String, Application) of the
  released 19.4.0 native SDKs; web passes it to Gleap.initialize.
- Tests for the key resolution and for a JWT provider set before or after
  initialize.
- README, example, regenerated API docs and dist/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ios): prefer initializeWithProjectId: when the native SDK has it

Native iOS SDK 19.5.0 (GleapSDK/Gleap-iOS-SDK#65) adds
initializeWithProjectId: and deprecates initializeWithToken:. The bridge
looks the new selector up at runtime and falls back to initializeWithToken:
(the released 19.4.0), so it builds and runs against both without a
deprecation warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: native Gleap SDKs 19.5.0 (provider restores the signed session after a restart)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
boehlerlukas added a commit to GleapSDK/Flutter-SDK that referenced this pull request Nov 7, 2026
….5.0 (#51)

* feat: Gleap.initialize(projectId:), token: deprecated; JWT provider before initialize; version 19.5.0

- initialize takes projectId (the former SDK key, same value); token stays
  as a @deprecated alias. The Project ID goes over the channel as projectId
  and token; Android, iOS and web read projectId and fall back to token, and
  call the native initialize of the released 19.4.0 SDKs.
- setUserJwtProvider installs the method channel handler itself, so token
  requests are answered when the Dart initialize has not run in this engine
  (natively initialized SDK, hot restart).
- README and example use projectId; helper tests for the resolution.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ios): prefer initializeWithProjectId: when the native SDK has it

Native iOS SDK 19.5.0 (GleapSDK/Gleap-iOS-SDK#65) adds
initializeWithProjectId: and deprecates initializeWithToken:. The bridge
looks the new selector up at runtime and falls back to initializeWithToken:
(the released 19.4.0), so it builds and runs against both without a
deprecation warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: native Gleap SDKs 19.5.0 (provider restores the signed session after a restart)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
boehlerlukas added a commit to GleapSDK/ReactNative-SDK that referenced this pull request Nov 7, 2026
* feat: Gleap.initialize(projectId) naming; JWT provider order tests; version 19.5.0

- Typings, JSDoc, native bridge parameter names, README and example call
  the initialize key "Project ID" (the former SDK key, same value). The
  bridge still calls initializeWithToken: / Gleap.initialize(String,
  Application) of the released 19.4.0 native SDKs.
- Tests: the Project ID reaches the native initialize unchanged; a JWT
  provider set before or after initialize answers token requests on iOS
  and Android.
- README: setUserJwtProvider may be called before or after initialize.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ios): prefer initializeWithProjectId: when the native SDK has it

Native iOS SDK 19.5.0 (GleapSDK/Gleap-iOS-SDK#65) adds
initializeWithProjectId: and deprecates initializeWithToken:. The bridge
looks the new selector up at runtime and falls back to initializeWithToken:
(the released 19.4.0), so it builds and runs against both without a
deprecation warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: native Gleap SDKs 19.5.0 (provider restores the signed session after a restart)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant