Skip to content

chore(compliance): audit posthog-ios 4.0 - #187

Merged
turnipdabeets merged 17 commits into
mainfrom
chore/posthog-ios-4-compliance
Nov 11, 2026
Merged

turnipdabeets merged 17 commits into
mainfrom
chore/posthog-ios-4-compliance

Conversation

@turnipdabeets

@turnipdabeets turnipdabeets commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Problem

compliance/posthog-ios.md scores 3.x (f5cbe87c, 2026-10-08, with #924–#934 counted as pending PRs). posthog-ios 4.0 changes several rows, and the README table has five contracts the file doesn't list yet.

Important

Merge after posthog-ios 4.0.0 is published (PostHog/posthog-ios#873). The capture v1 rows are scored against #146 at d387ab79 as if merged; re-check them against #146's final text.

Changes

Audited all 64 rows on the 4.0 release branch chore/v4-remove-deprecated at posthog-ios e27cbe4cb against sdk-specs main 752f899 plus #146 at d387ab79 (capture v1, including #147's AI lane), treated as merged. Every line reference on the page is at e27cbe4cb. #924–#934 are merged there, so nothing is counted as pending. Summary: 38/16/4/6 on 64 rows → 44 ✅ · 14 🟡 · 1 ❌ · 10 ➖ on 69 rows.

Rows that changed:

  • Get Feature Flag Payload 🟡→✅: getFeatureFlagPayload(_:) is removed. The read is getFeatureFlagResult(_:sendFeatureFlagEvent: false)?.payload, which "Payload reads through the flag result getter" (docs(flags): record the mobile majors' getFeatureFlagPayload removal #170) permits. A malformed payload → nil, and bootstrap payloads are decoded once.
  • Get Feature Flag Result 🟡→✅, Feature Flag Cache 🟡→✅: a malformed, empty or whitespace-only payload → nil; an empty variant reads as disabled (docs(flags): read an empty variant as disabled in get-feature-flag-result #193).
  • Is Feature Enabled 🟡→✅: isFeatureEnabled(_:defaultValue:).
  • Capture 🟡→✅: empty event names are dropped; NSNull properties are omitted on the queue and the wire, with $set/$set_once/$group_set nulls kept (PostHog/posthog-ios#1047); the SDK fills its own $lib/$lib_version pair after the caller's properties and before beforeSend, as docs(capture): specify capture v1 delivery for every v1 SDK #146's "Events name their own library" now asks of client SDKs (PostHog/posthog-ios#1050); an empty variant is left out of $active_feature_flags.
  • Capture Exception 🟡→✅: same NSNull fix.
  • Session Replay Privacy ❌→🟡: 4.0 records masked screenshots only, so the wireframe path that leaked ph-no-capture children is gone. SwiftUI's explicit mask still wins over an enclosing postHogNoMask(), the reverse of the spec's precedence.
  • Get Feature Flags, Get Feature Flags And Payloads ❌→🟡: the specs now record getAllFeatureFlags()'s result list as the iOS 4.0 surface. It is still not the canonical map shape.
  • Capture AI ➖→✅: docs(capture): specify capture v1 delivery for every v1 SDK #146 adds iOS 4.0 to Applicability, and the AI lane conforms (own queue started at launch, lane-scoped options including its own compression, 8 MiB + 64 KiB cap with clamping, 5 MiB batches, NSNull cleanup).
  • Exception Steps ✅→🟡: steps are byte-counted, buffered and persisted with NSNull members that the queue and the capture v1 wire strip after #1047, so the representations "Normalize to the wire form once, before processing" requires to be identical differ.
  • New ➖ rows: Experiment Exposure (iOS requests /flags?v=2), AI Datasets, AI Scorers, Offline Evaluations, Emails (server only).

Note-only:

compliance/README.md: the iOS roll-up row, the out-of-cycle refresh paragraph, the iOS gap entries and the iOS non-Pass count (15).

How did you test this code?

🤖 Generated with Claude Code

@turnipdabeets
turnipdabeets requested a review from a team as a code owner November 5, 2026 21:03

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

Please correct the HTTP Client compliance score: compression = .none leaves the AI lane compressed, contrary to the current whole-client requirement. The optional inline notes clarify the draft retry policy and SwiftUI masking precedence. Retain the documented merge-after-iOS-4.0-publication prerequisite.

AI-assisted review.

Comment thread compliance/posthog-ios.md Resolved
Comment thread compliance/posthog-ios.md Resolved
Comment thread compliance/posthog-ios.md Resolved

@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 implementation evidence and conditional baseline are clear, but HTTP Client is counted as fully compliant while the pinned specifications retain an unresolved whole-client compression requirement. Consider retaining Partial or Unknown until that scope is resolved. Preserve the iOS 4.0 publication and final-#146 recheck prerequisites.

AI-assisted review.

Comment thread compliance/posthog-ios.md Resolved
@dustinbyrne
dustinbyrne requested a review from a team November 9, 2026 19:12
turnipdabeets and others added 8 commits November 10, 2026 12:35
Re-audit all 64 posthog-ios rows at 3460e534a (4.0 release branch)
against sdk-specs dd11a6b, add the five rows added to the README table
since the last audit, and update the iOS roll-up and gap entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
compression = .none leaves captureAi requests gzipped through the
separate captureAiCompression setting, so iOS 4.0 has no whole-client
compression opt-out. Roll-up becomes 40/17/1/11 (58%), 18 gaps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Draft #146 already permits the client-SDK durable queue, unlimited
attempts, 1-30 s backoff and multi-event 413 halving for iOS 4.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SwiftUI's postHogMask() wins over an enclosing postHogNoMask(), the
reverse of the spec's unmask-over-mask precedence. It over-masks rather
than leaks. Roll-up becomes 39/18/1/11 (57%), 19 gaps.

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

Re-checks the iOS audit at 1f91c5b2 and sdk-specs 8306698. #1036 keeps
$lib/$lib_version, which now matches #146. Opt In meets the #138 replay
restart requirements. Surveys gains a #102 gap: setSurveySeen moves the
last-seen date on submit and dismiss. HTTP Client goes back to ✅: its
compression gap comes from conflicting http-client and capture-ai rules in
#146, raised on that PR. Tally 40/17/1/11.

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

Scores Capture, Capture AI, Before Send Hook, Event Batcher, HTTP Client and
Retry Queue against #146 at 5c26b9b, treated as merged. The capture v1 wire,
transport and retry policy conform. Capture AI applies to iOS 4.0 and is 🟡
for the same NSNull serialization gap as Capture; starting the AI queue at
setup is what #146 asks of client SDKs. Tally 40/18/1/10.

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…52f899 and #146 d387ab7

Capture, Capture Exception and Capture AI move to Pass now that null-valued
properties are omitted (posthog-ios#1047) and the SDK fills its own $lib pair
after the caller's properties (posthog-ios#1050). On Feature Flags moves to
Pass: loads in flight across reset() are dropped (posthog-ios#1048) and empty
variants are left out of listener flags. HTTP Client is scored Pass on its
merits, since #146 now leaves a lane with its own compression setting out of
the whole-client opt-out. Surveys stays Partial only for the popup-delay
eligibility re-check (SHOULD); posthog-ios#1049 fixed the rest.

Opt In meets the new deferred-crash consent requirement (#199); the empty
variant (#193), variant key rename (#203) and job-retry (#205) changes need no
other status change. Line references move to e27cbe4cb.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@turnipdabeets
turnipdabeets force-pushed the chore/posthog-ios-4-compliance branch from 88f99ae to 9d7f9da Compare November 10, 2026 17:42
The popup-delay and wait-period SHALLs are met since posthog-ios#1049. The
one unmet requirement is a SHOULD (re-check eligibility when the delay
elapses), which is recorded but not scored. Totals become 45/13/1/10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@turnipdabeets
turnipdabeets marked this pull request as ready for review November 10, 2026 18:44

@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 refreshed audit addresses the previous feedback and clearly identifies its release-branch and proposed-specification baselines. The inline exception-step classification suggestion is a nonblocking audit follow-up. Retain the documented release-tag repinning, iOS 4.0 publication and final-#146 recheck prerequisites.

AI-assisted review.

Comment thread compliance/posthog-ios.md Resolved
…zation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread compliance/posthog-ios.md Outdated
| 6 | Capture AI | ➖ | unchanged — Applicability still `server`; the new null-drop requirement/scenario is `@server`; no AI capture in iOS (repo grep for `captureAi`/`capture_ai`/`$ai_generation` → no hits) |
| 7 | Capture Exception | 🟡 | [n5]; partly fixed by [#930](https://github.com/PostHog/posthog-ios/pull/930) |
| 8 | Create Person Profile | ➖ | unchanged — spec Applicability still says only the posthog-js family exposes it; no `createPersonProfile` in iOS (repo grep → no hits) |
| 5 | Capture | ✅ | was 🟡; [n4]; capture v1 wire conforms (#146); empty event names dropped (also after `beforeSend`); `NSNull` properties omitted (#1047); own `$lib` pair filled after caller properties (#1050); empty variant left out of `$active_feature_flags` |

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.

#146 now requires migration guides to show a call option process_person_profile: true as the way to keep identifying under a registered false. The SDK behaves that way, but MIGRATION.md here has no such example until posthog-ios#1053 merges. Capture is 🟡 at this commit, or say it's met once #1053 lands.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 85d4acd — Capture 🟡 until posthog-ios#1053 merges; requirement checked at 15501ca.

@turnipdabeets turnipdabeets Nov 11, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed in 2fd35bd — this audit tracks 4.0 and #1053 targets it, so Capture stays ✅ with a note; we'll recheck when #1053 merges.

Comment thread compliance/README.md Outdated
| posthog-python | 13/64 fully compliant (20%; 30 contracts N/A on a server SDK) | 13 | 16 | 5 | 30 | 0 | 2026-10-12 · `509c8525` | 21 | [posthog-python.md](posthog-python.md) |
| posthog-android | 37/64 fully compliant (58%) | 37 | 16 | 5 | 6 | 0 | 2026-10-19 · `c5e788bd` (targeted re-audit — see file header) | 21 | [posthog-android.md](posthog-android.md) |
| posthog-ios | 38/64 fully compliant (59%) | 38 | 16 | 4 | 6 | 0 | 2026-10-08 · `f5cbe87c` + PostHog/posthog-ios#924–#934 (out-of-cycle refresh, see below) | 20 | [posthog-ios.md](posthog-ios.md) |
| posthog-ios | 44/69 fully compliant (64%) | 44 | 14 | 1 | 10 | 0 | 2026-11-10 · `e27cbe4cb` (4.0 release branch, before 4.0.0 is published; capture v1 rows against #146 at `d387ab79` as merged; see below) | 15 | [posthog-ios.md](posthog-ios.md) |

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 README still says 64 contracts per SDK, but the iOS row is now out of 69, so its percentage doesn't compare with the other rows.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in a50f0e3 — README notes 69 contracts and gives iOS as 43/64 for comparison.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reworded in 720117c — the 69-contract note is now SDK-neutral; each 69-row line also gives its /64 score.

turnipdabeets and others added 7 commits November 10, 2026 18:49
…on guide shows the identity call option

#146 at 15501ca requires migration guides to show a per-call
process_person_profile: true on identity calls; MIGRATION.md at e27cbe4cb
lacks it until PostHog/posthog-ios#1053 merges.

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The identity-call migration-guide example #146 requires lands in 4.0 with
PostHog/posthog-ios#1053, which targets the release branch. This audit
tracks 4.0, so a pending release-branch PR is noted rather than scored as a
gap. Reverts 85d4acd.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The same paragraph lands from both the iOS and Android 4.0 audits, so it
merges cleanly in either order and stays true after both.

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

# Conflicts:
#	compliance/README.md
…ompliance

# Conflicts:
#	compliance/README.md
…ompliance

# Conflicts:
#	compliance/README.md
@turnipdabeets
turnipdabeets merged commit 6f1f14b into main Nov 11, 2026
10 checks passed
@turnipdabeets
turnipdabeets deleted the chore/posthog-ios-4-compliance branch November 11, 2026 01:49
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