Skip to content

fix(flags): drop flag loads in flight across reset() - #1044

Closed
turnipdabeets wants to merge 1 commit into
chore/v4-remove-deprecatedfrom
fix/v4-drop-flag-loads-across-reset
Closed

turnipdabeets wants to merge 1 commit into
chore/v4-remove-deprecatedfrom
fix/v4-drop-flag-loads-across-reset

Conversation

@turnipdabeets

@turnipdabeets turnipdabeets commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

sdk-specs requires that a flag load in flight when reset() or close() runs never reaches a listener and isn't replayed to one registered later (on-feature-flags, "Loads discarded by reset or close reach no listener", from PostHog/sdk-specs#161). iOS met this for close() but not reset(), and it's the only gap on the iOS On Feature Flags compliance row (PostHog/sdk-specs#187). posthog-flutter on iOS/macOS inherits it.

reset() cleared the flag cache and queued a reload for the new identity, but the /flags request already in flight for the previous identity had no staleness check. When it completed it wrote the previous user's flags into the cache and notified onFeatureFlags listeners, until the queued reload replaced them. Listeners and getters briefly saw the previous user's flags, and a listener registered in that window got them replayed.

Changes

PostHogRemoteConfig keeps a reset generation, bumped by clear() (called from reset()) under featureFlagsLock, like posthog-android 4.0 and posthog-js:

  • A load records the generation before reading the identity. A response from an older generation is dropped: it doesn't write the cache, isn't sent to onFeatureFlagsLoaded, so it's never stored for replay to a late listener. The check is repeated under the cache lock, so a reset() that lands mid-response can't be undone.
  • A flags-loaded notification already queued on main is also dropped if a reset() ran since it was sent.
  • The reload reset() queued still runs. A reloadFeatureFlags(_:) callback of the dropped load gets that reload's result instead. If no reload is queued, it gets a failed result (errorsLoading: true) with the current, cleared flags.
  • A queued request that read the old identity can't replace the queued post-reset one.

close() is unchanged (it already drops these). The changeset gets a "Fix" line.

💚 How did you test it?

New tests in PostHogFeatureFlagsTest / TestOnFeatureFlags, each holding the first /flags response until after reset():

  • "drops a load in flight across reset() and delivers the reload reset() started": the listener gets only the post-reset flags, the held response doesn't write the cache, and the held load's reloadFeatureFlags callback gets the post-reset flags.
  • "does not replay a load dropped by reset() to a listener registered afterwards": with the post-reset reload skipped, a listener registered afterwards gets nothing and the cache stays empty.

With the fix reverted, both fail (5 issues: the listener receives previous-user, the cache holds previous-user, and so does the callback). With the fix:

  • make test filter="'PostHogFeatureFlags|PostHogRemoteConfig|PostHogSDKTest|Survey'": 388 tests in 58 suites passed.
  • make test (full): failures only in PostHogLogsQueueTest, PostHogPushNotificationTest and PostHogPropertiesSerializationTest (timeouts). Rerun alone, only one PostHogLogsQueueTest case failed, and a PostHogLogsQueueTest case fails the same way on the base branch.
  • make lint: 0 serious violations.

iOS simulator (iPhone 17):

  • Unit tests: xcodebuild build-for-testing succeeded, but xcodebuild test-without-building -scheme PostHog -destination 'id=CEF9AA9B-6E3E-4A94-BCA4-892ED863F9C3' -only-testing:PostHogTests/PostHogFeatureFlagsTest -only-testing:PostHogTests/PostHogRemoteConfigTest hung three times with "The test runner hung before establishing connection", before any test ran. CI's test-ios-simulator (unit tests) job ran both new tests on a simulator, and they passed.
  • Example app: PostHogExample, changed locally (not committed) and pointed at a local stub server that holds /flags for previous-user for 3 s. It calls identify("previous-user"), then reset() 0.5 s later, with a listener registered and the flag read every second.
Listener received Late listener received
Base branch previous-user, then new-user —
This branch new-user only new-user

📝 Checklist

  • All commits are signed (see Commit signing)
  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Added a line to the existing 4.0 changeset (.changeset/v4-major-release.md)

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

  • Claude Code (Claude Opus 5.5). Dropped the stale response inside PostHogRemoteConfig rather than only at listener delivery (as posthog-android does), so it also never reaches the cache or flag getters.
  • Moving the dropped load's reloadFeatureFlags(_:) callback onto the post-reset reload was a choice: the alternative was answering it with the previous identity's flags or a failure.
  • 3.x (main) has the same gap; this PR only targets 4.0.

🤖 Generated with Claude Code

reset() cleared the flag cache and queued a reload for the new identity,
but a /flags request already in flight for the previous identity still
wrote its flags into the cache and notified onFeatureFlags listeners
when it completed, until the queued reload corrected it.

PostHogRemoteConfig now bumps a reset generation in clear() and drops a
response, or a queued notification, from an older generation: it doesn't
write the cache or reach listeners, so it can't be replayed to a late
listener either. The queued post-reset reload still runs, and a
reloadFeatureFlags(_:) callback of the dropped load gets that reload's
result instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@turnipdabeets turnipdabeets self-assigned this Nov 9, 2026
@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

posthog-ios Compliance Report

Date: 2026-11-09T17:52:36.624738+00:00
Duration: 942616ms

✅ All Tests Passed!

234/234 tests passed


Capture_V1 Tests

✅ 106/106 tests passed

View Details
Test Status Duration
Endpoint And Method.Targets V1 Endpoint ✅ 2869ms
Endpoint And Method.Does Not Use Legacy Endpoints ✅ 2946ms
Required Headers.Has Authorization Bearer Header ✅ 438ms
Required Headers.Has Content Type Json ✅ 479ms
Required Headers.Has Posthog Sdk Info Format ✅ 2853ms
Required Headers.Has Posthog Attempt Header ✅ 2732ms
Required Headers.Has Posthog Request Id ✅ 2749ms
Required Headers.Has Posthog Request Timestamp ✅ 2830ms
Required Headers.Has User Agent ✅ 2814ms
Body Format.Body Has Created At And Batch ✅ 2872ms
Body Format.No Api Key In Body ✅ 2878ms
Body Format.No Sent At In Body ✅ 2805ms
Event Format.Event Has Required Root Fields ✅ 2794ms
Event Format.Event Uuid Is Valid ✅ 397ms
Event Format.Event Timestamp Is Rfc3339 ✅ 2887ms
Event Format.Non Utc Event Timestamp Is Converted To Utc ✅ 519ms
Event Format.Distinct Id Is String ✅ 2832ms
Event Format.Distinct Id At Root Not Properties ✅ 2721ms
Event Format.Custom Properties Preserved ✅ 2710ms
Event Format.Set Properties Preserved ✅ 2900ms
Event Format.Set Once Properties Preserved ✅ 2835ms
Event Format.Groups Properties Preserved ✅ 474ms
Event Format.Sdk Generates Uuid If Not Provided ✅ 2776ms
Event Format.Event Has Required Root Fields Batch ✅ 2851ms
Event Format.Event Uuid Is Valid Batch ✅ 3000ms
Event Format.Event Timestamp Is Rfc3339 Batch ✅ 2911ms
Event Format.Distinct Id Is String Batch ✅ 2836ms
Event Format.Distinct Id At Root Not Properties Batch ✅ 517ms
Event Format.Custom Properties Preserved Batch ✅ 2834ms
Event Format.Set Properties Preserved Batch ✅ 3079ms
Event Format.Set Once Properties Preserved Batch ✅ 2853ms
Event Format.Groups Properties Preserved Batch ✅ 3171ms
Event Format.Sdk Generates Uuid If Not Provided Batch ✅ 2989ms
Batch Behavior.Multiple Events In Single Batch ✅ 3085ms
Batch Behavior.Batch Envelope Smoke ✅ 2936ms
Batch Behavior.Flush With No Events Sends Nothing ✅ 295ms
Batch Behavior.Flush At Triggers Batch ✅ 1206ms
Batch Behavior.Created At Reflects Batch Creation Time ✅ 2829ms
Deduplication.Generates Unique Uuids ✅ 3005ms
Deduplication.Different Events Same Content Different Uuids ✅ 2859ms
Deduplication.Preserves Uuid On Retry ✅ 9228ms
Deduplication.Preserves Timestamp On Retry ✅ 9261ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 7851ms
Deduplication.No Duplicate Events In Batch ✅ 3037ms
Header Behavior On Retry.Attempt Header Starts At One ✅ 2773ms
Header Behavior On Retry.Attempt Header Increments On Retry ✅ 16268ms
Header Behavior On Retry.Request Id Preserved On Retry ✅ 9302ms
Header Behavior On Retry.Different Requests Have Different Request Ids ✅ 5236ms
Header Behavior On Retry.Request Timestamp Changes On Retry ✅ 9180ms
Response Format Validation.Success Response Has Uuid Keyed Results ✅ 389ms
Response Format Validation.Success Response Has Ok For Each Event ✅ 2702ms
Response Format Validation.Success No Retry After When All Ok ✅ 2642ms
Response Format Validation.Success Retry After Present When Retry Events ✅ 2796ms
Response Format Validation.Success No Retry After When Drop Only ✅ 2809ms
Response Format Validation.Response Echoes Request Id ✅ 2652ms
Retry Behavior.Retries On 408 ✅ 8842ms
Retry Behavior.Retries On 500 ✅ 8811ms
Retry Behavior.Retries On 503 ✅ 11299ms
Retry Behavior.Retries On 504 ✅ 9156ms
Retry Behavior.Retries On 404 ✅ 5403ms
Retry Behavior.Retries On 429 ✅ 9295ms
Retry Behavior.Retries On 502 ✅ 9133ms
Retry Behavior.Retryable Errors Have Retry After ✅ 6084ms
Retry Behavior.Respects Retry After On Retryable Error ✅ 10699ms
Retry Behavior.Does Not Retry On 400 ✅ 2310ms
Retry Behavior.Does Not Retry On 401 ✅ 4785ms
Retry Behavior.Does Not Retry On 402 ✅ 4758ms
Retry Behavior.Does Not Retry On 413 ✅ 4752ms
Retry Behavior.Does Not Retry On 415 ✅ 4768ms
Retry Behavior.Non Retryable Errors Have No Retry After ✅ 2232ms
Retry Behavior.Implements Backoff ✅ 18869ms
Partial Batch Handling.Handles 200 Full Success ✅ 4741ms
Partial Batch Handling.Handles 200 With All Ok ✅ 5848ms
Partial Batch Handling.Does Not Retry Dropped Events ✅ 5810ms
Partial Batch Handling.Does Not Retry Warning Events ✅ 5843ms
Partial Batch Handling.Prunes Ok Events On Partial Retry ✅ 7750ms
Partial Batch Handling.Prunes Dropped Events On Partial Retry ✅ 7776ms
Partial Batch Handling.Retries Only Retry Events From Partial ✅ 7858ms
Partial Batch Handling.Partial Retry Preserves Uuids ✅ 7781ms
Partial Batch Handling.Partial Retry Attempt Header Increments ✅ 7759ms
Partial Batch Handling.Partial Retry Request Id Preserved ✅ 7682ms
Partial Batch Handling.Respects Retry After On Partial ✅ 7788ms
Partial Batch Handling.Unknown Result Treated As Terminal ✅ 5796ms
Partial Batch Handling.Mixed Ok Drop Warning No Retry ✅ 5823ms
Compression.Sends Gzip Content Encoding ✅ 2770ms
Compression.No Content Encoding When Disabled ✅ 2816ms
Compression.Compressed Body Is Decompressible ✅ 292ms
Error Handling.Does Not Retry On Unknown 4Xx ✅ 4673ms
Event Options.Cookieless Mode Override ✅ 306ms
Event Options.Disable Skew Correction Override ✅ 249ms
Event Options.Process Person Profile Override ✅ 2625ms
Event Options.Product Tour Id Override ✅ 2768ms
Event Options.Unset Options Omitted ✅ 2742ms
Event Options.Options Override In Batch ✅ 2765ms
Event Options.Unknown Option Passes Through ✅ 2632ms
Event Options.Option Value Is Not Converted ✅ 2718ms
Event Options.Lenient Bool Option Values Are Not Converted ✅ 2817ms
Event Options.Option Wins Over Legacy Property ✅ 2699ms
Event Options.Legacy Property Fills Unset Option ✅ 314ms
Event Options.Null Option Falls Back To Legacy Property ✅ 2686ms
Property Layers.Caller Property Beats Registered Property ✅ 2779ms
Property Layers.Before Send Runs Last ✅ 2714ms
Fail Open.Empty Api Key Sends Nothing ✅ 1217ms
Fail Open.Personal Api Key Sends Nothing ✅ 1201ms
Geoip And Historical Migration.Geoip Disable Injected Into Properties ✅ 2765ms
Geoip And Historical Migration.Historical Migration Absent By Default ✅ 2821ms

Capture_Ai_V1 Tests

✅ 111/111 tests passed

View Details
Test Status Duration
Endpoint And Method.Targets V1 Endpoint ✅ 2755ms
Endpoint And Method.Does Not Use Legacy Endpoints ✅ 2643ms
Endpoint And Method.Capture Does Not Reroute Ai Named Events ✅ 2768ms
Endpoint And Method.Capture Ai Does Not Reroute Non Ai Events ✅ 388ms
Lane Isolation.Failing Ai Lane Does Not Delay Analytics ✅ 5386ms
Required Headers.Has Authorization Bearer Header ✅ 2693ms
Required Headers.Has Content Type Json ✅ 2750ms
Required Headers.Has Posthog Sdk Info Format ✅ 2750ms
Required Headers.Has Posthog Attempt Header ✅ 2734ms
Required Headers.Has Posthog Request Id ✅ 2805ms
Required Headers.Has Posthog Request Timestamp ✅ 2764ms
Required Headers.Has User Agent ✅ 2754ms
Body Format.Body Has Created At And Batch ✅ 2737ms
Body Format.No Api Key In Body ✅ 2694ms
Body Format.No Sent At In Body ✅ 2816ms
Event Format.Event Has Required Root Fields ✅ 2795ms
Event Format.Event Uuid Is Valid ✅ 417ms
Event Format.Event Timestamp Is Rfc3339 ✅ 482ms
Event Format.Non Utc Event Timestamp Is Converted To Utc ✅ 2808ms
Event Format.Distinct Id Is String ✅ 396ms
Event Format.Distinct Id At Root Not Properties ✅ 387ms
Event Format.Custom Properties Preserved ✅ 2775ms
Event Format.Set Properties Preserved ✅ 2734ms
Event Format.Set Once Properties Preserved ✅ 2750ms
Event Format.Groups Properties Preserved ✅ 2815ms
Event Format.Sdk Generates Uuid If Not Provided ✅ 2809ms
Event Format.Event Has Required Root Fields Batch ✅ 453ms
Event Format.Event Uuid Is Valid Batch ✅ 425ms
Event Format.Event Timestamp Is Rfc3339 Batch ✅ 2779ms
Event Format.Distinct Id Is String Batch ✅ 2897ms
Event Format.Distinct Id At Root Not Properties Batch ✅ 2821ms
Event Format.Custom Properties Preserved Batch ✅ 2888ms
Event Format.Set Properties Preserved Batch ✅ 2866ms
Event Format.Set Once Properties Preserved Batch ✅ 2895ms
Event Format.Groups Properties Preserved Batch ✅ 2733ms
Event Format.Sdk Generates Uuid If Not Provided Batch ✅ 2833ms
Batch Behavior.Multiple Events In Single Batch ✅ 2891ms
Batch Behavior.Batch Envelope Smoke ✅ 2814ms
Batch Behavior.Flush At Triggers Batch ✅ 1125ms
Batch Behavior.Created At Reflects Batch Creation Time ✅ 405ms
Deduplication.Generates Unique Uuids ✅ 2983ms
Deduplication.Different Events Same Content Different Uuids ✅ 2841ms
Deduplication.Preserves Uuid On Retry ✅ 5423ms
Deduplication.Preserves Timestamp On Retry ✅ 9247ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 8002ms
Deduplication.No Duplicate Events In Batch ✅ 2995ms
Header Behavior On Retry.Attempt Header Starts At One ✅ 2812ms
Header Behavior On Retry.Attempt Header Increments On Retry ✅ 16207ms
Header Behavior On Retry.Request Id Preserved On Retry ✅ 9314ms
Header Behavior On Retry.Different Requests Have Different Request Ids ✅ 5106ms
Header Behavior On Retry.Request Timestamp Changes On Retry ✅ 9141ms
Response Format Validation.Success Response Has Uuid Keyed Results ✅ 3607ms
Response Format Validation.Success Response Has Ok For Each Event ✅ 3071ms
Response Format Validation.Success No Retry After When All Ok ✅ 2928ms
Response Format Validation.Success Retry After Present When Retry Events ✅ 2869ms
Response Format Validation.Success No Retry After When Drop Only ✅ 2927ms
Response Format Validation.Response Echoes Request Id ✅ 3021ms
Retry Behavior.Retries On 408 ✅ 5691ms
Retry Behavior.Retries On 500 ✅ 9356ms
Retry Behavior.Retries On 503 ✅ 11833ms
Retry Behavior.Retries On 504 ✅ 5431ms
Retry Behavior.Retries On 404 ✅ 9281ms
Retry Behavior.Retries On 429 ✅ 5384ms
Retry Behavior.Retries On 502 ✅ 5469ms
Retry Behavior.Retryable Errors Have Retry After ✅ 6237ms
Retry Behavior.Respects Retry After On Retryable Error ✅ 10805ms
Retry Behavior.Does Not Retry On 400 ✅ 4822ms
Retry Behavior.Does Not Retry On 401 ✅ 4841ms
Retry Behavior.Does Not Retry On 402 ✅ 2464ms
Retry Behavior.Does Not Retry On 413 ✅ 4856ms
Retry Behavior.Does Not Retry On 415 ✅ 2322ms
Retry Behavior.Non Retryable Errors Have No Retry After ✅ 4758ms
Retry Behavior.Implements Backoff ✅ 18823ms
Partial Batch Handling.Handles 200 Full Success ✅ 2578ms
Partial Batch Handling.Handles 200 With All Ok ✅ 5835ms
Partial Batch Handling.Does Not Retry Dropped Events ✅ 5803ms
Partial Batch Handling.Does Not Retry Warning Events ✅ 5952ms
Partial Batch Handling.Prunes Ok Events On Partial Retry ✅ 7947ms
Partial Batch Handling.Prunes Dropped Events On Partial Retry ✅ 7964ms
Partial Batch Handling.Retries Only Retry Events From Partial ✅ 7929ms
Partial Batch Handling.Partial Retry Preserves Uuids ✅ 7939ms
Partial Batch Handling.Partial Retry Attempt Header Increments ✅ 7803ms
Partial Batch Handling.Partial Retry Request Id Preserved ✅ 7858ms
Partial Batch Handling.Respects Retry After On Partial ✅ 7839ms
Partial Batch Handling.Unknown Result Treated As Terminal ✅ 5990ms
Partial Batch Handling.Mixed Ok Drop Warning No Retry ✅ 5904ms
Compression.Sends Gzip Content Encoding ✅ 2964ms
Compression.No Content Encoding When Disabled ✅ 2781ms
Compression.Compressed Body Is Decompressible ✅ 2818ms
Error Handling.Does Not Retry On Unknown 4Xx ✅ 4797ms
Event Options.Cookieless Mode Override ✅ 2855ms
Event Options.Disable Skew Correction Override ✅ 2818ms
Event Options.Process Person Profile Override ✅ 2879ms
Event Options.Product Tour Id Override ✅ 426ms
Event Options.Unset Options Omitted ✅ 2876ms
Event Options.Options Override In Batch ✅ 512ms
Event Options.Unknown Option Passes Through ✅ 2772ms
Event Options.Option Value Is Not Converted ✅ 2862ms
Event Options.Lenient Bool Option Values Are Not Converted ✅ 321ms
Event Options.Option Wins Over Legacy Property ✅ 369ms
Event Options.Legacy Property Fills Unset Option ✅ 435ms
Event Options.Null Option Falls Back To Legacy Property ✅ 2850ms
Event Size.Event Over Ceiling Is Not Sent ✅ 4162ms
Event Size.Over Ceiling Drop Is Reported Or Logged Without Content ✅ 2790ms
Event Size.Batches Close Before Byte Target ✅ 8286ms
Geoip And Historical Migration.Geoip Disable Injected Into Properties ✅ 2819ms
Geoip And Historical Migration.Historical Migration Absent By Default ✅ 2800ms
Property Layers.Caller Property Beats Registered Property ✅ 2763ms
Property Layers.Before Send Runs Last ✅ 2810ms
Fail Open.Empty Api Key Sends Nothing ✅ 1326ms
Fail Open.Personal Api Key Sends Nothing ✅ 1253ms

Feature_Flags Tests

✅ 17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 2867ms
Request Payload.Flags Request Uses V2 Query Param ✅ 2863ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 2888ms
Request Payload.Flags Request Omits Authorization Header ✅ 2803ms
Request Payload.Token In Flags Body Matches Init ✅ 2854ms
Request Payload.Groups Round Trip ✅ 2751ms
Request Payload.Groups Default To Empty Object ✅ 2888ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 2886ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 2836ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 2859ms
Request Lifecycle.No Flags Request On Init Alone ✅ 108ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 2813ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 5631ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 2800ms
Retry Behavior.Retries Flags On 502 ✅ 2895ms
Retry Behavior.Retries Flags On 504 ✅ 2943ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 3250ms

@turnipdabeets
turnipdabeets marked this pull request as ready for review November 9, 2026 18:19
@turnipdabeets
turnipdabeets requested a review from a team as a code owner November 9, 2026 18:19
@veria-ai

veria-ai Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

PR overview

The PR updates remote feature-flag loading to discard in-flight responses that arrive after reset().

One issue remains open: a pre-reset response can still reactivate session replay after reset, even when its cache update and notification are discarded. This can allow screenshot capture based on the previous user's replay state, and the stale state can persist if the post-reset reload fails.

Open issues (1)

Fixed/addressed: 0 · PR risk: 6/10

Reviews

@turnipdabeets

Copy link
Copy Markdown
Contributor Author

Closing in favour of #1048, which makes this fix on main; it reaches 4.0 when main is next merged into chore/v4-remove-deprecated. That merge will conflict in PostHogRemoteConfig.swift because 4.0 changed the reload callback (#913) and removed didReceiveFeatureFlags (#965). Resolve it with this branch's version (fix/v4-drop-flag-loads-across-reset, kept for reference).

self.featureFlagsLock.withLock {
let isStale = self.featureFlagsLock.withLock { () -> Bool in
// Re-checked under the cache lock, so a reset() since the check above can't be undone.
guard self.featureFlagsResetGeneration == generation else { return true }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Medium: Replay activation remains outside the generation guard

This locked check runs after processSessionRecordingConfig, so if reset() finishes between the initial check and that call, the old response can restore the previous user's sessionReplayFlagActive = true even though its cache write and notification are discarded; isSessionReplayActive() trusts that state when allowing screenshot capture, and a failed post-reset reload leaves it unchanged. Make the generation check and replay-state mutation atomic with clear() in both successful and quota-limited paths, keeping exposure callbacks outside the locks.

turnipdabeets added a commit that referenced this pull request Nov 10, 2026
…cated

Brings in #1048 (drop flag loads in flight across reset()). PostHogRemoteConfig.swift
and its tests take the 4.0 resolution from #1044 (fix/v4-drop-flag-loads-across-reset),
which keeps 4.0's FeatureFlagsLoadResult callback and the removed didReceiveFeatureFlags.
PostHog.podspec stays deleted.
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