release: 2.2.4 — re-introduce SKAN on top of v2.2.1 baseline - #102
release: 2.2.4 — re-introduce SKAN on top of v2.2.1 baseline#102JakubMrozek wants to merge 16 commits into
Conversation
Begin the 2.2.4 line from the known-good production tag v2.2.1 and add a placeholder changelog heading. SKAN code will be re-introduced on top of this, reviewed incrementally. Content to follow. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cross the server skanSupported gate (Flutter >= 2.2.2) so the ad server sends signed skan payloads. Only the version line changes; the Flutter constraint (>=3.24.0) and flutter_lints (^5.0.0) are intentionally kept at their v2.2.1 values. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kSdkVersion is sent as the reported SDK version in the preload request (api.dart, use_preload_ads.dart). The ad server gates skanSupported on sdk-flutter >= 2.2.2, so this must be >= 2.2.2 for signed skan payloads to be returned. Set to 2.2.4 to match pubspec. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The SKAN native code (SKAdNetworkManager, SKStoreProductManager, SKOverlayManager) imports StoreKit. Declare it explicitly in s.frameworks so it links reliably now that SKAN is actually activated, rather than relying on Swift implicit auto-linking. Deployment target intentionally kept at iOS 12.0 (SKAN APIs are runtime-gated with @available). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port the 2.2.2 privacy manifest: NSPrivacyTracking=false, clear tracking domains, DeviceID declared as AppFunctionality/non-tracking (matches sdk-swift), and add the UserDefaults required-reason API (CA92.1). SystemBootTime (8FFB.1) is intentionally retained: the Flutter native AppInfoPlugin reads kp_proc.p_starttime, which sdk-swift does not — so the manifests correctly differ on that one entry. Manifest reflects the Flutter binary's actual API usage. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port the tested 2.2.2 Skan/Bid model onto the 2.2.1 base: adds Skan.toJson() (consumed by the SKOverlay/SKStoreProduct services), ImpressionTrigger, and fidelities in Skan equality/hashCode. Additive and non-breaking (superset of the 2.2.1 public API). Extend bid_test.dart with 20 new tests covering the additions: impressionTrigger parsing/defaults, Skan.toJson (required-only, null omission, optionals, fidelities), Skan equality incl. fidelities, and AttributionFidelity parse/equality. Full file: 50 tests, all passing. Note: bid.dart:221 still reads json['akk'] (should be 'aak') — an AAK-only bug, irrelevant to SKAN; left as-is for the SKAN-focused 2.2.4. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring the tested 2.2.2 SKAN wiring onto the 2.2.1 base as a single compile-coupled + method-channel-coupled change: - ad_format.dart: click -> fidelity-1 -> SKStoreProduct (else browser), impressionTrigger timing (immediate on ad-done / component on modal), pass full skan to the services, remove the message-driven skstoreproduct path. Excludes the non-SKAN '; null' evaluateJavascript tweak (kept at v2.2.1, consistent with kontext_webview.dart). - types.dart: drop the skstoreproduct OpenIframeComponent value. - interstitial_modal.dart: drop skstoreproduct message handling. - sk_overlay_service / sk_store_product_service: send skan.toJson(). - Native plugins/managers read the skan payload; field mapping matches the production-proven KontextKit (SKOverlay + SKStoreProduct verified). - SKAdNetworkManager: aligned with KontextKit — resolve nonce/timestamp/signature upfront (top-level else fidelity-0), validate all six required fields, guard-let instead of force-unwraps, drop parseFidelities, fail cleanly with MISSING_ARGUMENTS. Flutter SKAN was never live in production, so KontextKit is the source of truth. - Port coupled 2.2.2 tests (ad_format_test, types_test). flutter analyze: clean. Full test suite: green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cover the two previously-untested SKAN services via injectable isIOS + mocked method channels: platform gating (non-iOS -> false, no channel call), correct channel args (skan.toJson(); overlay nests under 'skan' with position/dismissible, store-product sends the skan map directly), return-value handling, the overlay itunesItem.isEmpty guard, and PlatformException/UNSUPPORTED_IOS handling. 17 tests, all passing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…o app Show publishers the required SKAN setup: our ad-network id (mp7rpxwdrx.skadnetwork) must be present in the host app's Info.plist SKAdNetworkItems for Apple to allow SKAN attribution. Example-only; does not affect the published SDK. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire the AdsProvider onEvent callback to print each ad event (filled/no-fill/render-started/completed/viewed/clicked/error) with its key fields — a ready reference for publishers on consuming SDK events. Example-only; does not affect the published SDK. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mbuckalew-kontext
left a comment
There was a problem hiding this comment.
Automated review focused on correctness, silent failures, and store-compliance. Verified against the actual source at the PR head (not just the diff). Two items I'd treat as blocking (privacy manifest, silent StoreKit attribution loss); the rest are either quick fixes or need a decision/answer from the backend team. Note: the native refactor here is a net crash-safety improvement — SKAdNetworkManager drops its old force-unwraps for a guarded binding — so none of the items below are crashes.
🤖 Generated with Claude Code
Integrators must add mp7rpxwdrx.skadnetwork to their own app's Info.plist SKAdNetworkItems or SKAN attribution silently never fires (ads still serve). Addresses PR #102 review feedback; the example app's plist serves as the working reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A non-numeric timestamp previously became 0 via 'Int(...) ?? 0', producing an invalid signature and silent attribution loss. Parse it in fidelity1Values (NSNumber or numeric string, else nil -> SKAN params skipped, sheet still presents), mirroring SKOverlayManager and KontextKit. Unreachable from our server (signs String(Date.now()) and the wire schema enforces strings), but a DSP could theoretically send a non-numeric string. Addresses PR #102 review feedback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…toreProduct applySkanParams was void — on any invalid field it silently skipped the SKAN params, the sheet still presented, and completion(true) suppressed the Dart browser fallback: the store page opened unattributed with no error surfaced. It now returns Bool and present() errors with ATTRIBUTION_FAILED, which the existing Dart path turns into a browser fallback — no Dart change needed. Mirrors KontextKit (identical error semantics) and SKOverlayManager. Addresses PR #102 blocking review. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…state Minimal-delta decision: 2.2.1 is the proven production baseline and the manifest is unrelated to the SKAN activation this release ships. Drops the 2.2.2 manifest sync (and its changelog line) so the file no longer appears in the release diff. The Swift-SDK-aligned manifest can be revisited separately. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make isIOS injectable (same pattern as the other two SKAN services) and add unit tests for the full impression lifecycle: payload field names, arming only on successful init, start/end gated on readiness, error swallowing (never throws), dispose disarming, call ordering, and slow native responses resolving correctly — the Dart layer is latency-proof regardless of when Apple's async completion returns. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
All commits from this PR are now on |
Why
Production Chai runs v2.2.1 (known-good). SKAN never activated on production, and the version that turns it on (2.2.2 → 2.2.3-rc) is blocked behind an Android WebView
init-iframeissue Chai reported. Rather than ship the accumulated 2.2.2/2.2.3 changes, we restart the release from the known-goodv2.2.1tag and re-introduce the minimal SKAN code, reviewed line by line, to minimize regression surface on Chai's fragile WebView setup.Base
This PR is intentionally based on
v2.2.4-base— a branch pinned at exactlyv2.2.1— so the diff shows only what we add on top of production, not the 2.2.2/2.2.3 history. (A PR intomainwould misleadingly show 2.2.2's changes as reverted.)Scope of this PR (so far)
v2.2.4created fromv2.2.1## 2.2.4(content to follow)pubspec.yamlversion to2.2.4(must be ≥ 2.2.2 to cross the serverskanSupportedgate)Plan reference
Notion log: SDK Flutter v2.2.4.
🤖 Generated with Claude Code