fix: preserve native purchase payloads across SDKs - #252
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
Important Review skippedNo new commits to review since the last review. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis PR standardizes generated purchase payload preservation across SDK bridges, adds parity auditing, updates platform serialization and normalization, changes deferred subscription handling, preserves transaction identifiers, and expands regression coverage across multiple integrations. ChangesCross-SDK payload integrity
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
libraries/react-native-iap/src/vega-adapter.ts (1)
1029-1053: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
includeSuspendedoption is now a dead no-op.
getAvailablePurchases's filter (Lines 1033-1037) only excludes cancelled receipts and never readsoptions?.android?.includeSuspended, yetrestorePurchases(Line 1546) still passes{android: {includeSuspended: false}}. SincemapReceiptnow always setsisSuspendedAndroid: false, this option currently has no effect anywhere — it silently misleads future readers into believing suspended purchases are excluded from restore.Either drop the stale option from the
restorePurchasescall, or restore real suspended-state filtering if that semantic is still needed.🧹 Proposed cleanup
async restorePurchases(): Promise<void> { - const purchases = await getAvailablePurchases({ - android: {includeSuspended: false}, - }); + const purchases = await getAvailablePurchases(); purchases.forEach(emitPurchaseUpdated); },Also applies to: 1544-1549
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libraries/react-native-iap/src/vega-adapter.ts` around lines 1029 - 1053, Remove the stale android.includeSuspended option from the restorePurchases call and its getAvailablePurchases invocation, since getAvailablePurchases does not implement suspended-purchase filtering and mapReceipt always sets isSuspendedAndroid to false. Preserve the existing purchase restoration behavior and type filtering.libraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.kt (1)
1222-1229: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winRestore graceful fallback for malformed iOS purchase payloads.
decodePurchasePayloadIOScatches parsing failures and returnsnull, so malformed purchase updates can disappear frompurchaseUpdatedListenerand related consumers. Add legacy alias/default recovery insidenormalizePurchasePayloadIOS, and/or wrapPurchaseIOS.fromJsoninrunCatchingwith a fallback construction path before relying on strict generated fields.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.kt` around lines 1222 - 1229, Update convertAnyToPurchaseIOS and the underlying normalizePurchasePayloadIOS flow to preserve malformed iOS purchase updates instead of returning null. Add the legacy alias/default recovery in normalizePurchasePayloadIOS and wrap PurchaseIOS.fromJson with runCatching, constructing a fallback PurchaseIOS before accessing strict generated fields.
🧹 Nitpick comments (2)
packages/docs/src/pages/docs/updates/releases.tsx (1)
184-197: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueStale id/key still says "flutter-purchase-payload-fix" after the cross-SDK reword.
The object
id(line 186),key/AnchorLink id(lines 190, 194) still reference the old Flutter-only note, even though the heading and body were reworded to "Cross-SDK native payload integrity patches." Since this note is still "(planned)" and unreleased, renaming to something likecross-sdk-payload-integrity-planned-2026-07-24would avoid a misleading permalink without breaking any published anchor.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/docs/src/pages/docs/updates/releases.tsx` around lines 184 - 197, Rename the release note identifier consistently from the Flutter-specific value to a Cross-SDK payload-integrity identifier, such as cross-sdk-payload-integrity-planned-2026-07-24, in the object id, rendered div key, and AnchorLink id. Keep the planned date and heading unchanged.libraries/expo-iap/ios/onside/OnsideIapModule.swift (1)
586-607: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSuffix the new Onside-only helpers with
IOS.Rename these helpers to
formatPriceIOSandsubscriptionPeriodComponentsIOS, then update their call sites.As per coding guidelines, “iOS functions must end with
IOS.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libraries/expo-iap/ios/onside/OnsideIapModule.swift` around lines 586 - 607, Rename the Onside-only helpers formatPrice and subscriptionPeriodComponents to formatPriceIOS and subscriptionPeriodComponentsIOS, respectively, and update every call site to use the new names.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@libraries/expo-iap/ios/onside/OnsideIapModule.swift`:
- Around line 483-490: The introductory offer mapping in the product dictionary
currently collapses all non-zero prices to “empty.” Update the
introductoryPricePaymentModeIOS assignment in the introductoryPrice block to
preserve the provider/SDK payment mode when available, using “empty” only as an
explicit fallback while retaining “free-trial” for zero-priced offers; add
regression coverage for paid pay-as-you-go and pay-up-front offers.
In
`@libraries/kmp-iap/library/src/androidUnitTest/kotlin/io/github/hyochan/kmpiap/BillingPurchasePayloadMappingTest.kt`:
- Around line 20-21: Update the raw billing payload in
BillingPurchasePayloadMappingTest to use the string state "purchased" for
purchaseState, ensuring the roundtrip matches the mapper’s accepted billing
states and getActiveSubscriptionsHandler’s PURCHASED behavior.
---
Outside diff comments:
In
`@libraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.kt`:
- Around line 1222-1229: Update convertAnyToPurchaseIOS and the underlying
normalizePurchasePayloadIOS flow to preserve malformed iOS purchase updates
instead of returning null. Add the legacy alias/default recovery in
normalizePurchasePayloadIOS and wrap PurchaseIOS.fromJson with runCatching,
constructing a fallback PurchaseIOS before accessing strict generated fields.
In `@libraries/react-native-iap/src/vega-adapter.ts`:
- Around line 1029-1053: Remove the stale android.includeSuspended option from
the restorePurchases call and its getAvailablePurchases invocation, since
getAvailablePurchases does not implement suspended-purchase filtering and
mapReceipt always sets isSuspendedAndroid to false. Preserve the existing
purchase restoration behavior and type filtering.
---
Nitpick comments:
In `@libraries/expo-iap/ios/onside/OnsideIapModule.swift`:
- Around line 586-607: Rename the Onside-only helpers formatPrice and
subscriptionPeriodComponents to formatPriceIOS and
subscriptionPeriodComponentsIOS, respectively, and update every call site to use
the new names.
In `@packages/docs/src/pages/docs/updates/releases.tsx`:
- Around line 184-197: Rename the release note identifier consistently from the
Flutter-specific value to a Cross-SDK payload-integrity identifier, such as
cross-sdk-payload-integrity-planned-2026-07-24, in the object id, rendered div
key, and AnchorLink id. Keep the planned date and heading unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 82ac1d09-238f-41d2-8b8b-30342c41f7bc
📒 Files selected for processing (47)
knowledge/_claude-context/context.mdknowledge/internal/04-platform-packages.mdlibraries/expo-iap/ios/ExpoIapHelper.swiftlibraries/expo-iap/ios/onside/OnsideIapModule.swiftlibraries/expo-iap/src/ExpoIapModule.tslibraries/expo-iap/src/__tests__/ExpoIapModule.test.tslibraries/expo-iap/src/__tests__/native-log-redaction.test.jslibraries/expo-iap/src/__tests__/vega-adapter.test.tslibraries/expo-iap/src/vega-adapter.tslibraries/flutter_inapp_purchase/android/src/main/kotlin/io/github/hyochan/flutter_inapp_purchase/AndroidInappPurchasePlugin.ktlibraries/flutter_inapp_purchase/ios/flutter_inapp_purchase/Sources/flutter_inapp_purchase/FlutterInappPurchasePlugin.swiftlibraries/flutter_inapp_purchase/lib/errors.dartlibraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dartlibraries/flutter_inapp_purchase/lib/helpers.dartlibraries/flutter_inapp_purchase/macos/flutter_inapp_purchase/Sources/flutter_inapp_purchase/FlutterInappPurchasePlugin.swiftlibraries/flutter_inapp_purchase/test/errors_unit_test.dartlibraries/flutter_inapp_purchase/test/flutter_inapp_purchase_active_subscriptions_test.dartlibraries/flutter_inapp_purchase/test/flutter_inapp_purchase_channel_test.dartlibraries/flutter_inapp_purchase/test/helpers_unit_test.dartlibraries/flutter_inapp_purchase/test/iapkit_base_url_bridge_test.dartlibraries/flutter_inapp_purchase/test/ios_methods_test.dartlibraries/godot-iap/Example/tests/test_types_only.gdlibraries/kmp-iap/library/build.gradle.ktslibraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/Helper.ktlibraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.ktlibraries/kmp-iap/library/src/androidUnitTest/kotlin/io/github/hyochan/kmpiap/BillingPurchasePayloadMappingTest.ktlibraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.ktlibraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerIOS.ktlibraries/kmp-iap/library/src/iosTest/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerTestIOS.ktlibraries/maui-iap/src/OpenIap.Maui/Platforms/Android/OpenIapAndroid.cslibraries/maui-iap/tests/OpenIap.Maui.Tests/RecordJsonTests.cslibraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.ktlibraries/react-native-iap/ios/RnIapHelper.swiftlibraries/react-native-iap/src/__tests__/index.test.tslibraries/react-native-iap/src/__tests__/utils/type-bridge.test.tslibraries/react-native-iap/src/__tests__/vega-adapter.test.tslibraries/react-native-iap/src/index.tslibraries/react-native-iap/src/specs/RnIap.nitro.tslibraries/react-native-iap/src/utils/type-bridge.tslibraries/react-native-iap/src/vega-adapter.tspackages/docs/src/pages/docs/updates/releases.tsxpackages/google/openiap/src/amazon/java/dev/hyo/openiap/OpenIapModule.ktpackages/google/openiap/src/testAmazon/java/dev/hyo/openiap/AmazonSubscriptionGroupMappingTest.ktpackages/google/openiap/src/testPlay/java/dev/hyo/openiap/utils/BillingPurchasePayloadMappingTest.ktscripts/audit-non-godot-parity.mjsscripts/audit-purchase-payload-parity.mjsscripts/audit-purchase-payload-parity.test.mjs
|
Addressed the remaining review-body findings in fffeb10: malformed optional KMP iOS metadata can no longer suppress a valid purchase update, legacy iOS identity aliases are recovered with core-identity guards, Vega restore no longer passes an unsupported suspension option and has deferred-plan regression coverage, the planned release anchor is cross-SDK, and the Onside helpers follow the IOS naming rule. The Android raw purchase-state fixture remains numeric for the BillingClient reason documented in the inline reply. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
libraries/kmp-iap/library/src/iosTest/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerTestIOS.kt (1)
56-57: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winApply the required
IOSsuffix to the new test functions.These iOS-specific Kotlin functions currently end with descriptive text instead of
IOS. Rename them to identifiers ending inIOSto follow the repository naming rule.As per coding guidelines, iOS functions in
*.ktfiles must end withIOS.Also applies to: 101-102, 125-126, 137-138, 157-158, 185-186, 203-204
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libraries/kmp-iap/library/src/iosTest/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerTestIOS.kt` around lines 56 - 57, Rename the iOS-specific test functions in ProductPayloadNormalizerTestIOS, including preserves canonical purchase metadata before generated decoding and the other referenced tests, so each identifier ends with the required IOS suffix. Preserve their test behavior and annotations.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@libraries/kmp-iap/library/src/iosTest/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerTestIOS.kt`:
- Around line 56-57: Rename the iOS-specific test functions in
ProductPayloadNormalizerTestIOS, including preserves canonical purchase metadata
before generated decoding and the other referenced tests, so each identifier
ends with the required IOS suffix. Preserve their test behavior and annotations.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: da5854d2-eceb-47ba-93dd-7364208ad5e3
📒 Files selected for processing (8)
libraries/expo-iap/ios/onside/OnsideIapModule.swiftlibraries/expo-iap/src/__tests__/native-log-redaction.test.jslibraries/kmp-iap/library/src/androidUnitTest/kotlin/io/github/hyochan/kmpiap/BillingPurchasePayloadMappingTest.ktlibraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerIOS.ktlibraries/kmp-iap/library/src/iosTest/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerTestIOS.ktlibraries/react-native-iap/src/__tests__/vega-adapter.test.tslibraries/react-native-iap/src/vega-adapter.tspackages/docs/src/pages/docs/updates/releases.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
- libraries/expo-iap/src/tests/native-log-redaction.test.js
- libraries/kmp-iap/library/src/androidUnitTest/kotlin/io/github/hyochan/kmpiap/BillingPurchasePayloadMappingTest.kt
- packages/docs/src/pages/docs/updates/releases.tsx
- libraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerIOS.kt
- libraries/expo-iap/ios/onside/OnsideIapModule.swift
- libraries/react-native-iap/src/vega-adapter.ts
- libraries/react-native-iap/src/tests/vega-adapter.test.ts
|
Reviewed the final CodeRabbit IOS-suffix nitpick and am intentionally not renaming these test display names. The naming SSOT scopes the function rule to iOS functions in packages/apple, while the KMP convention applies platform suffixes to public types and fields. These are private Kotlin test display names under iosTest, and neighboring IosConnectionLifecycleTest and IosErrorMappingTest use the same unsuffixed style. The focused ProductPayloadNormalizerTestIOS suite passes, so no code change is appropriate for this suggestion. |
fffeb10 to
e4f9a86
Compare
Fail closed for unavailable Onside APIs and preserve Onside and Vega subscription metadata without routing through the wrong store runtime.
Carry explicit transaction identity and renewal metadata through Nitro while retaining Vega deferred plan updates and orderless Play semantics.
Preserve generated purchase and provider verification results, support Horizon verification, normalize nested bridge maps, and retain typed platform errors.
Keep Google, Amazon, KMP, and MAUI purchase payloads faithful to their native sources, including subscription transitions, transaction identity, and listener diagnostics.
Derive purchase-field expectations from generated SSOT and fail on canonical-order, alternative-store, or cross-wrapper payload drift.
Record the planned SDK patch releases and add generated-payload preservation guidance to the platform and compiled AI documentation.
Link the stacked cross-SDK implementation PR from the planned payload-integrity release note.
af8f66f to
e8a3c0c
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
libraries/expo-iap/ios/ExpoIapHelper.swift (1)
67-82: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winFallback for unrecognized
typediverges from the RN helper.
RnIapHelper.parseProductQueryTypereturns.inAppfor both empty and unrecognized inputs, butExpoIapHelper.parseProductQueryTypereturns.allfor any non-empty unrecognized value. For cross-SDK parity, match RN and return.inAppin thedefaultcase.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libraries/expo-iap/ios/ExpoIapHelper.swift` around lines 67 - 82, Update ExpoIapHelper.parseProductQueryType so its default case returns .inApp for unrecognized non-empty values, matching RnIapHelper behavior while preserving the existing handling of recognized values and empty input.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@libraries/expo-iap/ios/ExpoIapHelper.swift`:
- Around line 67-82: Update ExpoIapHelper.parseProductQueryType so its default
case returns .inApp for unrecognized non-empty values, matching RnIapHelper
behavior while preserving the existing handling of recognized values and empty
input.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 0e1ceb79-84c9-4013-9b7e-e16fc257bfbb
📒 Files selected for processing (49)
.github/workflows/ci.ymlknowledge/_claude-context/context.mdknowledge/internal/04-platform-packages.mdlibraries/expo-iap/ios/ExpoIapHelper.swiftlibraries/expo-iap/ios/onside/OnsideIapModule.swiftlibraries/expo-iap/src/ExpoIapModule.tslibraries/expo-iap/src/__tests__/ExpoIapModule.test.tslibraries/expo-iap/src/__tests__/native-log-redaction.test.jslibraries/expo-iap/src/__tests__/vega-adapter.test.tslibraries/expo-iap/src/vega-adapter.tslibraries/flutter_inapp_purchase/android/src/main/kotlin/io/github/hyochan/flutter_inapp_purchase/AndroidInappPurchasePlugin.ktlibraries/flutter_inapp_purchase/ios/flutter_inapp_purchase/Sources/flutter_inapp_purchase/FlutterInappPurchasePlugin.swiftlibraries/flutter_inapp_purchase/lib/errors.dartlibraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dartlibraries/flutter_inapp_purchase/lib/helpers.dartlibraries/flutter_inapp_purchase/macos/flutter_inapp_purchase/Sources/flutter_inapp_purchase/FlutterInappPurchasePlugin.swiftlibraries/flutter_inapp_purchase/test/errors_unit_test.dartlibraries/flutter_inapp_purchase/test/flutter_inapp_purchase_active_subscriptions_test.dartlibraries/flutter_inapp_purchase/test/flutter_inapp_purchase_channel_test.dartlibraries/flutter_inapp_purchase/test/helpers_unit_test.dartlibraries/flutter_inapp_purchase/test/iapkit_base_url_bridge_test.dartlibraries/flutter_inapp_purchase/test/ios_methods_test.dartlibraries/godot-iap/Example/tests/test_types_only.gdlibraries/kmp-iap/library/build.gradle.ktslibraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/Helper.ktlibraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.ktlibraries/kmp-iap/library/src/androidUnitTest/kotlin/io/github/hyochan/kmpiap/BillingPurchasePayloadMappingTest.ktlibraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.ktlibraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerIOS.ktlibraries/kmp-iap/library/src/iosTest/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerTestIOS.ktlibraries/maui-iap/src/OpenIap.Maui/Platforms/Android/OpenIapAndroid.cslibraries/maui-iap/tests/OpenIap.Maui.Tests/RecordJsonTests.cslibraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.ktlibraries/react-native-iap/ios/RnIapHelper.swiftlibraries/react-native-iap/src/__tests__/index.test.tslibraries/react-native-iap/src/__tests__/utils/type-bridge.test.tslibraries/react-native-iap/src/__tests__/vega-adapter.test.tslibraries/react-native-iap/src/index.tslibraries/react-native-iap/src/specs/RnIap.nitro.tslibraries/react-native-iap/src/utils/type-bridge.tslibraries/react-native-iap/src/vega-adapter.tspackages/docs/src/pages/docs/updates/releases.tsxpackages/google/openiap/src/amazon/java/dev/hyo/openiap/OpenIapModule.ktpackages/google/openiap/src/testAmazon/java/dev/hyo/openiap/AmazonSubscriptionGroupMappingTest.ktpackages/google/openiap/src/testPlay/java/dev/hyo/openiap/utils/BillingPurchasePayloadMappingTest.ktpackages/gql/src/generated-sync-manifest.test.mjsscripts/audit-non-godot-parity.mjsscripts/audit-purchase-payload-parity.mjsscripts/audit-purchase-payload-parity.test.mjs
🚧 Files skipped from review as they are similar to previous changes (39)
- libraries/kmp-iap/library/src/androidUnitTest/kotlin/io/github/hyochan/kmpiap/BillingPurchasePayloadMappingTest.kt
- packages/google/openiap/src/testPlay/java/dev/hyo/openiap/utils/BillingPurchasePayloadMappingTest.kt
- libraries/react-native-iap/src/specs/RnIap.nitro.ts
- libraries/flutter_inapp_purchase/lib/errors.dart
- libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt
- packages/google/openiap/src/testAmazon/java/dev/hyo/openiap/AmazonSubscriptionGroupMappingTest.kt
- libraries/flutter_inapp_purchase/lib/helpers.dart
- libraries/godot-iap/Example/tests/test_types_only.gd
- libraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.kt
- libraries/flutter_inapp_purchase/test/helpers_unit_test.dart
- libraries/react-native-iap/src/index.ts
- knowledge/internal/04-platform-packages.md
- libraries/flutter_inapp_purchase/macos/flutter_inapp_purchase/Sources/flutter_inapp_purchase/FlutterInappPurchasePlugin.swift
- libraries/expo-iap/src/tests/native-log-redaction.test.js
- libraries/flutter_inapp_purchase/test/flutter_inapp_purchase_channel_test.dart
- libraries/react-native-iap/src/tests/index.test.ts
- libraries/kmp-iap/library/build.gradle.kts
- libraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/Helper.kt
- libraries/flutter_inapp_purchase/test/errors_unit_test.dart
- libraries/flutter_inapp_purchase/test/ios_methods_test.dart
- libraries/expo-iap/src/tests/vega-adapter.test.ts
- knowledge/_claude-context/context.md
- libraries/flutter_inapp_purchase/android/src/main/kotlin/io/github/hyochan/flutter_inapp_purchase/AndroidInappPurchasePlugin.kt
- libraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.kt
- libraries/react-native-iap/src/utils/type-bridge.ts
- packages/docs/src/pages/docs/updates/releases.tsx
- libraries/flutter_inapp_purchase/test/iapkit_base_url_bridge_test.dart
- libraries/expo-iap/src/vega-adapter.ts
- libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart
- libraries/expo-iap/src/ExpoIapModule.ts
- libraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerIOS.kt
- libraries/maui-iap/tests/OpenIap.Maui.Tests/RecordJsonTests.cs
- libraries/react-native-iap/src/tests/utils/type-bridge.test.ts
- packages/google/openiap/src/amazon/java/dev/hyo/openiap/OpenIapModule.kt
- libraries/expo-iap/src/tests/ExpoIapModule.test.ts
- libraries/react-native-iap/src/vega-adapter.ts
- libraries/kmp-iap/library/src/iosTest/kotlin/io/github/hyochan/kmpiap/ProductPayloadNormalizerTestIOS.kt
- scripts/audit-non-godot-parity.mjs
- libraries/react-native-iap/src/tests/vega-adapter.test.ts
|
Fixed the latest CodeRabbit product-query fallback finding in 53b1ca4. Expo iOS now fails closed to ProductQueryType.inApp for unrecognized non-empty values, matching React Native, with source-contract regression coverage. Focused and full Expo tests, plugin tests, TypeScript checks, lint, formatting, and the repository parity audit pass. |
Summary
Stack normalization
PR #251 has merged into
main. This branch was rebased from the reviewed #251 head onto its squash merge commit with an identical resulting Git tree. Files changed now contains only this follow-up payload-preservation work.Changes
Version and release scope
2.4.2, the minimum of openiap-apple2.4.2and openiap-google2.5.0.2.5.1, react-native-iap15.6.1, expo-iap4.7.1, flutter_inapp_purchase9.6.1, KMP2.7.1, and OpenIap.Maui1.4.1.Validation
bun audit:parity,bun audit:docs,bun audit:release-stategit diff --checkPreview
No visual recording is applicable. This change affects native payload transport, event mapping, and executable audit coverage without changing a user-facing screen. The automated tests, platform builds, and parity fault matrix are the relevant proof.
Related
Summary by CodeRabbit