Skip to content

fix: keep a registered personless setting off identity events - #1067

Merged
turnipdabeets merged 4 commits into
chore/v4-remove-deprecatedfrom
fix/v4-identity-person-processing
Nov 13, 2026
Merged

turnipdabeets merged 4 commits into
chore/v4-remove-deprecatedfrom
fix/v4-identity-person-processing

Conversation

@turnipdabeets

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

In 3.x the SDK replaced a registered $process_person_profile with its own value, so a registered false did nothing. In 4.0 it's sent as the process_person_profile option, and it also reached the events identify, alias, group and setPersonProperties send. PostHog drops identity events with person processing off, so an app that registered false would silently stop identifying users after upgrading.

This matches the rule the server SDKs adopt for their v1 releases (posthog-python#1247, posthog-go#450, posthog-rs#363, posthog-js#5712), and Flutter and KMP pick it up from here.

  • For $identify, $create_alias, $merge_dangerously, $groupidentify, $set and $set_once, the SDK ignores a registered $process_person_profile property and a process_person_profile option registered with registerOptionsForWrapper.
  • A value passed on the call, or set in beforeSend, still applies. personProfiles = never still skips these calls.
  • Other events keep the 4.0 behavior: a registered false makes them personless.
  • The SDK drops the registered value instead of sending true. PostHog treats a missing value and true the same way.
  • The migration guide replaces the "pass true on each identity call" workaround with the new rule, and the v4 changeset gets one line.

💚 How did you test it?

  • New tests: a registered option and super property set to false don't reach $identify, $create_alias, $groupidentify or $set, while a regular event still gets false. A false passed on the call still applies.
  • The first test fails on the base branch and passes with the fix.
  • One existing case assumed a registered false makes a $set personless. It now uses a false option on the call instead.

📝 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

  • Ran pnpm changeset to generate a changeset file (added a line to the existing 4.0 changeset)

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Written with Claude Code at Anna's direction, as a follow-up to the capture v1 discussion about identity events under a global personless setting. Same event list as the server SDKs. The SDK strips the registered value rather than sending an explicit true, which keeps the payload of every other identity call unchanged.

🤖 Generated with Claude Code

A registered `$process_person_profile: false`, or a `process_person_profile`
option a wrapper registers, no longer applies to `$identify`, `$create_alias`,
`$merge_dangerously`, `$groupidentify`, `$set` and `$set_once`. PostHog drops
those events with person processing off. A value passed on the call or set
in `beforeSend` still applies.
@turnipdabeets
turnipdabeets requested a review from a team as a code owner November 13, 2026 18:24
@turnipdabeets turnipdabeets self-assigned this Nov 13, 2026
@veria-ai

veria-ai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

PR overview

No security issues were found in this pull request.

Reviews

@github-actions

github-actions Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

posthog-ios Compliance Report

Date: 2026-11-13T19:42:35.861922+00:00
Duration: 989778ms

✅ 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 ✅ 2848ms
Endpoint And Method.Does Not Use Legacy Endpoints ✅ 2756ms
Required Headers.Has Authorization Bearer Header ✅ 2745ms
Required Headers.Has Content Type Json ✅ 2871ms
Required Headers.Has Posthog Sdk Info Format ✅ 2704ms
Required Headers.Has Posthog Attempt Header ✅ 2880ms
Required Headers.Has Posthog Request Id ✅ 396ms
Required Headers.Has Posthog Request Timestamp ✅ 2700ms
Required Headers.Has User Agent ✅ 2806ms
Body Format.Body Has Created At And Batch ✅ 2773ms
Body Format.No Api Key In Body ✅ 2823ms
Body Format.No Sent At In Body ✅ 2763ms
Event Format.Event Has Required Root Fields ✅ 2752ms
Event Format.Event Uuid Is Valid ✅ 2816ms
Event Format.Event Timestamp Is Rfc3339 ✅ 2701ms
Event Format.Non Utc Event Timestamp Is Converted To Utc ✅ 400ms
Event Format.Distinct Id Is String ✅ 2797ms
Event Format.Distinct Id At Root Not Properties ✅ 2765ms
Event Format.Custom Properties Preserved ✅ 2704ms
Event Format.Set Properties Preserved ✅ 2833ms
Event Format.Set Once Properties Preserved ✅ 2713ms
Event Format.Groups Properties Preserved ✅ 2720ms
Event Format.Sdk Generates Uuid If Not Provided ✅ 2741ms
Event Format.Event Has Required Root Fields Batch ✅ 2835ms
Event Format.Event Uuid Is Valid Batch ✅ 2868ms
Event Format.Event Timestamp Is Rfc3339 Batch ✅ 2826ms
Event Format.Distinct Id Is String Batch ✅ 2853ms
Event Format.Distinct Id At Root Not Properties Batch ✅ 2885ms
Event Format.Custom Properties Preserved Batch ✅ 408ms
Event Format.Set Properties Preserved Batch ✅ 2826ms
Event Format.Set Once Properties Preserved Batch ✅ 2790ms
Event Format.Groups Properties Preserved Batch ✅ 2898ms
Event Format.Sdk Generates Uuid If Not Provided Batch ✅ 2887ms
Batch Behavior.Multiple Events In Single Batch ✅ 2999ms
Batch Behavior.Batch Envelope Smoke ✅ 3035ms
Batch Behavior.Flush With No Events Sends Nothing ✅ 316ms
Batch Behavior.Flush At Triggers Batch ✅ 1206ms
Batch Behavior.Created At Reflects Batch Creation Time ✅ 2793ms
Deduplication.Generates Unique Uuids ✅ 446ms
Deduplication.Different Events Same Content Different Uuids ✅ 2905ms
Deduplication.Preserves Uuid On Retry ✅ 5548ms
Deduplication.Preserves Timestamp On Retry ✅ 9494ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 8235ms
Deduplication.No Duplicate Events In Batch ✅ 2843ms
Header Behavior On Retry.Attempt Header Starts At One ✅ 2717ms
Header Behavior On Retry.Attempt Header Increments On Retry ✅ 16483ms
Header Behavior On Retry.Request Id Preserved On Retry ✅ 9324ms
Header Behavior On Retry.Different Requests Have Different Request Ids ✅ 7630ms
Header Behavior On Retry.Request Timestamp Changes On Retry ✅ 9279ms
Response Format Validation.Success Response Has Uuid Keyed Results ✅ 2820ms
Response Format Validation.Success Response Has Ok For Each Event ✅ 3231ms
Response Format Validation.Success No Retry After When All Ok ✅ 2800ms
Response Format Validation.Success Retry After Present When Retry Events ✅ 2885ms
Response Format Validation.Success No Retry After When Drop Only ✅ 2915ms
Response Format Validation.Response Echoes Request Id ✅ 2812ms
Retry Behavior.Retries On 408 ✅ 9209ms
Retry Behavior.Retries On 500 ✅ 9321ms
Retry Behavior.Retries On 503 ✅ 11769ms
Retry Behavior.Retries On 504 ✅ 9141ms
Retry Behavior.Retries On 404 ✅ 5437ms
Retry Behavior.Retries On 429 ✅ 8809ms
Retry Behavior.Retries On 502 ✅ 8819ms
Retry Behavior.Retryable Errors Have Retry After ✅ 6254ms
Retry Behavior.Respects Retry After On Retryable Error ✅ 10810ms
Retry Behavior.Does Not Retry On 400 ✅ 4791ms
Retry Behavior.Does Not Retry On 401 ✅ 4833ms
Retry Behavior.Does Not Retry On 402 ✅ 4728ms
Retry Behavior.Does Not Retry On 413 ✅ 2311ms
Retry Behavior.Does Not Retry On 415 ✅ 4707ms
Retry Behavior.Non Retryable Errors Have No Retry After ✅ 4797ms
Retry Behavior.Implements Backoff ✅ 18245ms
Partial Batch Handling.Handles 200 Full Success ✅ 4774ms
Partial Batch Handling.Handles 200 With All Ok ✅ 5706ms
Partial Batch Handling.Does Not Retry Dropped Events ✅ 5820ms
Partial Batch Handling.Does Not Retry Warning Events ✅ 5986ms
Partial Batch Handling.Prunes Ok Events On Partial Retry ✅ 7829ms
Partial Batch Handling.Prunes Dropped Events On Partial Retry ✅ 7696ms
Partial Batch Handling.Retries Only Retry Events From Partial ✅ 7801ms
Partial Batch Handling.Partial Retry Preserves Uuids ✅ 7800ms
Partial Batch Handling.Partial Retry Attempt Header Increments ✅ 7800ms
Partial Batch Handling.Partial Retry Request Id Preserved ✅ 7805ms
Partial Batch Handling.Respects Retry After On Partial ✅ 7876ms
Partial Batch Handling.Unknown Result Treated As Terminal ✅ 5760ms
Partial Batch Handling.Mixed Ok Drop Warning No Retry ✅ 5766ms
Compression.Sends Gzip Content Encoding ✅ 2687ms
Compression.No Content Encoding When Disabled ✅ 2775ms
Compression.Compressed Body Is Decompressible ✅ 2654ms
Error Handling.Does Not Retry On Unknown 4Xx ✅ 2349ms
Event Options.Cookieless Mode Override ✅ 2762ms
Event Options.Disable Skew Correction Override ✅ 2801ms
Event Options.Process Person Profile Override ✅ 430ms
Event Options.Product Tour Id Override ✅ 2759ms
Event Options.Unset Options Omitted ✅ 2800ms
Event Options.Options Override In Batch ✅ 2843ms
Event Options.Unknown Option Passes Through ✅ 272ms
Event Options.Option Value Is Not Converted ✅ 2726ms
Event Options.Lenient Bool Option Values Are Not Converted ✅ 2731ms
Event Options.Option Wins Over Legacy Property ✅ 2771ms
Event Options.Legacy Property Fills Unset Option ✅ 2738ms
Event Options.Null Option Falls Back To Legacy Property ✅ 2881ms
Property Layers.Caller Property Beats Registered Property ✅ 2717ms
Property Layers.Before Send Runs Last ✅ 2790ms
Fail Open.Empty Api Key Sends Nothing ✅ 1240ms
Fail Open.Personal Api Key Sends Nothing ✅ 1308ms
Geoip And Historical Migration.Geoip Disable Injected Into Properties ✅ 2802ms
Geoip And Historical Migration.Historical Migration Absent By Default ✅ 2672ms

Capture_Ai_V1 Tests

✅ 111/111 tests passed

View Details
Test Status Duration
Endpoint And Method.Targets V1 Endpoint ✅ 416ms
Endpoint And Method.Does Not Use Legacy Endpoints ✅ 2677ms
Endpoint And Method.Capture Does Not Reroute Ai Named Events ✅ 2753ms
Endpoint And Method.Capture Ai Does Not Reroute Non Ai Events ✅ 2699ms
Lane Isolation.Failing Ai Lane Does Not Delay Analytics ✅ 5405ms
Required Headers.Has Authorization Bearer Header ✅ 2746ms
Required Headers.Has Content Type Json ✅ 2761ms
Required Headers.Has Posthog Sdk Info Format ✅ 2718ms
Required Headers.Has Posthog Attempt Header ✅ 2772ms
Required Headers.Has Posthog Request Id ✅ 2747ms
Required Headers.Has Posthog Request Timestamp ✅ 2755ms
Required Headers.Has User Agent ✅ 397ms
Body Format.Body Has Created At And Batch ✅ 2850ms
Body Format.No Api Key In Body ✅ 2670ms
Body Format.No Sent At In Body ✅ 2740ms
Event Format.Event Has Required Root Fields ✅ 2863ms
Event Format.Event Uuid Is Valid ✅ 2908ms
Event Format.Event Timestamp Is Rfc3339 ✅ 2765ms
Event Format.Non Utc Event Timestamp Is Converted To Utc ✅ 2802ms
Event Format.Distinct Id Is String ✅ 2671ms
Event Format.Distinct Id At Root Not Properties ✅ 2841ms
Event Format.Custom Properties Preserved ✅ 2954ms
Event Format.Set Properties Preserved ✅ 2788ms
Event Format.Set Once Properties Preserved ✅ 2877ms
Event Format.Groups Properties Preserved ✅ 2687ms
Event Format.Sdk Generates Uuid If Not Provided ✅ 2811ms
Event Format.Event Has Required Root Fields Batch ✅ 2946ms
Event Format.Event Uuid Is Valid Batch ✅ 3030ms
Event Format.Event Timestamp Is Rfc3339 Batch ✅ 2720ms
Event Format.Distinct Id Is String Batch ✅ 2845ms
Event Format.Distinct Id At Root Not Properties Batch ✅ 2802ms
Event Format.Custom Properties Preserved Batch ✅ 2802ms
Event Format.Set Properties Preserved Batch ✅ 827ms
Event Format.Set Once Properties Preserved Batch ✅ 3157ms
Event Format.Groups Properties Preserved Batch ✅ 2843ms
Event Format.Sdk Generates Uuid If Not Provided Batch ✅ 2726ms
Batch Behavior.Multiple Events In Single Batch ✅ 3442ms
Batch Behavior.Batch Envelope Smoke ✅ 2852ms
Batch Behavior.Flush At Triggers Batch ✅ 1126ms
Batch Behavior.Created At Reflects Batch Creation Time ✅ 2757ms
Deduplication.Generates Unique Uuids ✅ 3038ms
Deduplication.Different Events Same Content Different Uuids ✅ 2865ms
Deduplication.Preserves Uuid On Retry ✅ 9253ms
Deduplication.Preserves Timestamp On Retry ✅ 9134ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 7861ms
Deduplication.No Duplicate Events In Batch ✅ 2855ms
Header Behavior On Retry.Attempt Header Starts At One ✅ 2737ms
Header Behavior On Retry.Attempt Header Increments On Retry ✅ 16272ms
Header Behavior On Retry.Request Id Preserved On Retry ✅ 9169ms
Header Behavior On Retry.Different Requests Have Different Request Ids ✅ 7440ms
Header Behavior On Retry.Request Timestamp Changes On Retry ✅ 9284ms
Response Format Validation.Success Response Has Uuid Keyed Results ✅ 2814ms
Response Format Validation.Success Response Has Ok For Each Event ✅ 2908ms
Response Format Validation.Success No Retry After When All Ok ✅ 2729ms
Response Format Validation.Success Retry After Present When Retry Events ✅ 2848ms
Response Format Validation.Success No Retry After When Drop Only ✅ 2926ms
Response Format Validation.Response Echoes Request Id ✅ 2764ms
Retry Behavior.Retries On 408 ✅ 9270ms
Retry Behavior.Retries On 500 ✅ 9223ms
Retry Behavior.Retries On 503 ✅ 11681ms
Retry Behavior.Retries On 504 ✅ 5433ms
Retry Behavior.Retries On 404 ✅ 9270ms
Retry Behavior.Retries On 429 ✅ 9163ms
Retry Behavior.Retries On 502 ✅ 9345ms
Retry Behavior.Retryable Errors Have Retry After ✅ 6192ms
Retry Behavior.Respects Retry After On Retryable Error ✅ 10835ms
Retry Behavior.Does Not Retry On 400 ✅ 4725ms
Retry Behavior.Does Not Retry On 401 ✅ 4801ms
Retry Behavior.Does Not Retry On 402 ✅ 4701ms
Retry Behavior.Does Not Retry On 413 ✅ 4864ms
Retry Behavior.Does Not Retry On 415 ✅ 2303ms
Retry Behavior.Non Retryable Errors Have No Retry After ✅ 4778ms
Retry Behavior.Implements Backoff ✅ 17831ms
Partial Batch Handling.Handles 200 Full Success ✅ 4721ms
Partial Batch Handling.Handles 200 With All Ok ✅ 5837ms
Partial Batch Handling.Does Not Retry Dropped Events ✅ 5765ms
Partial Batch Handling.Does Not Retry Warning Events ✅ 5888ms
Partial Batch Handling.Prunes Ok Events On Partial Retry ✅ 7910ms
Partial Batch Handling.Prunes Dropped Events On Partial Retry ✅ 7875ms
Partial Batch Handling.Retries Only Retry Events From Partial ✅ 7835ms
Partial Batch Handling.Partial Retry Preserves Uuids ✅ 7855ms
Partial Batch Handling.Partial Retry Attempt Header Increments ✅ 7785ms
Partial Batch Handling.Partial Retry Request Id Preserved ✅ 7835ms
Partial Batch Handling.Respects Retry After On Partial ✅ 7815ms
Partial Batch Handling.Unknown Result Treated As Terminal ✅ 5882ms
Partial Batch Handling.Mixed Ok Drop Warning No Retry ✅ 5950ms
Compression.Sends Gzip Content Encoding ✅ 2709ms
Compression.No Content Encoding When Disabled ✅ 385ms
Compression.Compressed Body Is Decompressible ✅ 2836ms
Error Handling.Does Not Retry On Unknown 4Xx ✅ 4869ms
Event Options.Cookieless Mode Override ✅ 2854ms
Event Options.Disable Skew Correction Override ✅ 2793ms
Event Options.Process Person Profile Override ✅ 358ms
Event Options.Product Tour Id Override ✅ 2790ms
Event Options.Unset Options Omitted ✅ 2751ms
Event Options.Options Override In Batch ✅ 2852ms
Event Options.Unknown Option Passes Through ✅ 392ms
Event Options.Option Value Is Not Converted ✅ 393ms
Event Options.Lenient Bool Option Values Are Not Converted ✅ 2726ms
Event Options.Option Wins Over Legacy Property ✅ 2764ms
Event Options.Legacy Property Fills Unset Option ✅ 2748ms
Event Options.Null Option Falls Back To Legacy Property ✅ 2841ms
Event Size.Event Over Ceiling Is Not Sent ✅ 7163ms
Event Size.Over Ceiling Drop Is Reported Or Logged Without Content ✅ 2691ms
Event Size.Batches Close Before Byte Target ✅ 8342ms
Geoip And Historical Migration.Geoip Disable Injected Into Properties ✅ 2700ms
Geoip And Historical Migration.Historical Migration Absent By Default ✅ 2735ms
Property Layers.Caller Property Beats Registered Property ✅ 2698ms
Property Layers.Before Send Runs Last ✅ 2848ms
Fail Open.Empty Api Key Sends Nothing ✅ 1319ms
Fail Open.Personal Api Key Sends Nothing ✅ 1289ms

Feature_Flags Tests

✅ 17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 2676ms
Request Payload.Flags Request Uses V2 Query Param ✅ 2717ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 2743ms
Request Payload.Flags Request Omits Authorization Header ✅ 2736ms
Request Payload.Token In Flags Body Matches Init ✅ 2744ms
Request Payload.Groups Round Trip ✅ 2822ms
Request Payload.Groups Default To Empty Object ✅ 2802ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 2800ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 2828ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 2878ms
Request Lifecycle.No Flags Request On Init Alone ✅ 88ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 2781ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 5628ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 2874ms
Retry Behavior.Retries Flags On 502 ✅ 2872ms
Retry Behavior.Retries Flags On 504 ✅ 2891ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 3080ms

@dustinbyrne dustinbyrne 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.

The filtering restores identity/profile operations under inherited personless registration while preserving explicit call and hook overrides. Equivalent base/head tests confirm the intended change. Two non-blocking notes: synchronize the shared specification and qualify the API docstrings.

AI-assisted review.

Comment thread PostHog/PostHogSDK.swift Resolved
Comment thread PostHog/PostHogSDK.swift Resolved
Comment thread MIGRATION.md Resolved
@eli-r-ph

Copy link
Copy Markdown

Flutter on Windows and Linux doesn't pick this up: the Dart core still applies registered options to $identify, $create_alias, $groupidentify and $set (posthog_core.dart _withRegisteredOptions at :421, :671, :729, :1295). A desktop app that registers process_person_profile: false would still lose its identity events. Can posthog-flutter get the same change before 6.0?

@turnipdabeets

Copy link
Copy Markdown
Contributor Author

Can posthog-flutter get the same change before 6.0?

Yes, in PostHog/posthog-flutter#730.

@turnipdabeets
turnipdabeets merged commit c10b7b9 into chore/v4-remove-deprecated Nov 13, 2026
45 checks passed
@turnipdabeets
turnipdabeets deleted the fix/v4-identity-person-processing branch November 13, 2026 19:31
turnipdabeets added a commit that referenced this pull request Nov 13, 2026
…tructure

Brings in #1067. Its migration-guide change moves into the reordered
guide: "Fix identity calls" becomes "Check registered person processing",
since a registered `$process_person_profile` no longer reaches identity
events.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@turnipdabeets turnipdabeets mentioned this pull request Nov 13, 2026
6 of 18 tasks
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.

3 participants