chore: Identity verification rebase on main#1661
Conversation
chore: add github-to-asana workflows
* Adds the following new public methods: - OneSignal.Debug.addLogListener - OneSignal.Debug.removeLogListener * These new methods provide a way to capture all SDK log entires at runtime, allowing the app developer to store these and/or send them to their server. * The log listener is independent of logLevel, all message are always sent to listeners. * Use the new `OSCopyOnWriteSet`: it is possible for someone to add or remove a log listener within the `onLogEvent` callback, thus modifying the set of listeners as the set is being enumerated. @synchronized is a recursive lock, so it would not be sufficient. Locking the entire set of listeners would result in deadlock. * This mimics the Android implementation which uses the built-in `CopyOnWriteArraySet`
feat(logging): add public log listener methods
Xcode warns: *** -[NSKeyedUnarchiver decodeObjectForKey:]: value for key (requestSuccessful) is not an object. This will become an error in the future.
* The optional cast directly to a protocol always failed, and this intermediate step of casting to Any/AnyObject was necessary.
fix: live activities uncaches correctly
Fix calculation of one day in seconds. This bug had no side effects except keeping old irrelevant data too long.
* Let's arbitrarily keep receive requests up to 30 days. If these requests can't be sent for 30 days, let's drop them. Typically, they will be removed from cache when the request is successful, or fail with un-retryable error.
* Listen for `contentUpdates` as a way to know the live activity has been updated via a notification or "in app". This asynchronous sequence is triggered for all PTS, PTU, and live activities that are started and updated "in app". * We will check for notification ID to know if this change was generated from a notification and track the receive receipt.
Chore: fix Xcode project navigator files reference
The `testRemoveUpdateTokenWithSuccessfulRequest` should use `OSRequestRemoveUpdateToken` instead of `OSRequestRemoveStartToken`, fix small bug.
* Add a basic tests for the request * Add this type to the the uncaching test
* It seems that when creating a new string with stringWithFormat, copying the `localizedDescription` can raise an `NSInvalidArgumentException`. Not reproducible, but reported by users. * This matches other calls to the client where we log the error returned. Example stacktrace: Fatal Exception: NSInvalidArgumentException 0 CoreFoundation 0x... __exceptionPreprocess 1 libobjc.A.dylib 0x... objc_exception_throw 2 CoreFoundation 0x... +[NSObject(NSObject) _copyDescription] 3 CoreFoundation 0x... ___forwarding___ 4 CoreFoundation 0x... _CF_forwarding_prep_0 5 OneSignalInAppMessages 0x... __77-[OSMessagingController attemptFetchWithRetries:rywData:attempts:retryLimit:]_block_invoke.90 + 320 (OSMessagingController.m:320) 6 OneSignalCore 0x... -[OneSignalClient handleJSONNSURLResponse:data:error:isAsync:withRequest:onSuccess:onFailure:] + 214 (OneSignalClient.m:214) 7 OneSignalCore 0x... __54-[OneSignalClient executeRequest:onSuccess:onFailure:]_block_invoke + 110 (OneSignalClient.m:110)
…receipts Feat: live activities receive receipts
…tion_errors Fix: Prevent exception when copying an error's localizedDescription
On `macos-latest-largest`, use xcode 16.3+
…version chore(ci): Update runner image
Release 5.2.15
- Remove stale v5 feature parity warning now that v5 is stable. Replace with concise migration guide reference. - Fix image embedding to use GitHub-hosted URL - Update documentation links - Update supported iOS versions
…nges (#1641) Fix crash in -[OSInAppMessageViewController dismissCurrentInAppMessage:withVelocity:] The crash occurred when setInAppMessagingPaused:YES was called while the IAM's view hierarchy was in an inconsistent state (e.g., during orientation change). The code attempted to modify Auto Layout constraints on a messageView that was no longer a subview of self.view, causing an NSLayoutConstraint exception. Added a guard check to return out early if messageView.superview != self.view.
* mark OSMacros.h header private to avoid warning - Changed OSMacros.h visibility from Public to Private so the header won't be included in the public Headers folder during the build process - fix warning saying: "umbrella header for module 'OneSignalCore' does not include header 'OSMacros.h'" * use conventional quoted imports for private headers Conventionally correct: Quoted imports (#import "OSMacros.h") are the standard pattern for private/internal headers, now that the OSMacros has been marked from public to private
* chore: bump version to 5.4.1 * chore: build binaries * chore: update Swift package --------- Co-authored-by: github-actions[bot] <noreply@onesignal.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Migrate workflow references from sdk-actions to sdk-shared
* initial commit of new example app OneSignalSwiftUIExample * Generate app using screenshots * Do any small tweaking as needed * Add notification examples * make consent a toggle * add app icon assets * Update new example app * add live activities to new demo * add build prompt * chore: run swiftlint
* feat: send unattributed sessions to /outcomes/measure
When the SDK was migrated from the player model, the /players/{id}/on_focus call was split into two requests: session time via Update User and session duration outcomes via `/outcomes/measure`. The outcomes half was only wired up for attributed sessions, so unattributed sessions never sent to `/outcomes/measure`. However, to get unattributed session data in the dashboard, unattributed sessions needed to be sent to `/outcomes/measure` as well.
- Remove END_SESSION guard in OSFocusTimeProcessorFactory that prevented creating an unattributed processor for session-end events
- Add sendSessionEndOutcomes call to OSUnattributedFocusTimeProcessor alongside sendSessionTime, matching the old model where both were always sent together
* test: add unit tests for OSRequestSendSessionEndOutcomes request builder
Verify the request parameters for unattributed (notification_ids omitted,
direct: false), attributed direct (direct: true), and attributed indirect
(direct: false) influence types.
When using badge type "Increase", the cached badge value (ONESIGNAL_BADGE_KEY) in shared UserDefaults was not explicitly reset to zero in clearBadgeCount:fromClearAll:. If the swizzled badge setter did not fire, the NSE would read the stale cached value and increment from it, producing an incorrect badge count.
* chore: bump version to 5.4.2 * chore: build binaries * chore: update Swift package --------- Co-authored-by: github-actions[bot] <noreply@onesignal.com>
* feat: enhance manual integration support and swizzling control - Added APIs for manual notification handling and lifecycle observation when swizzling is disabled. - Introduced a new constant for controlling swizzling via Info.plist. * dev app: setup to test swizzle disabled * return early from manual APIs if swizzling is enabled * address PR feedback * thread safety * rename a method for clarity * remove ios 9 and 10 checks minimum is ios 12
* getting started doc for iOS * added more screenshots --------- Co-authored-by: AR Abdul Azeez <abdul@onesignal.com>
* chore: bump version to 5.5.0 * chore: build binaries * chore: update Swift package --------- Co-authored-by: github-actions[bot] <noreply@onesignal.com>
* demo: update getting started doc and screenshot * start IAMs as paused * add clear all notifications button to demo * demo app: fix bug with enabled toggle
…droid SDK (#1655) * Align iOS session duration reporting with Android SDK behavior Both attributed and unattributed focus time processors now behave like the Android SDK: session time accumulates silently across background events, and both the user property update and the outcomes/measure call are sent together only after a 30-second timer fires (confirming the user has left). If the user returns within 30 seconds, the timer is cancelled and no calls are made. Changes to OSAttributedFocusTimeProcessor: - Move sendSessionTime from sendOnFocusCall to the actual send method so it only fires when the 30s timer fires or the session ends, sending the full accumulated total instead of each interval Changes to OSUnattributedFocusTimeProcessor: - Add 30s NSTimer delay before sending to outcomes/measure - Send immediately (no delay) when session ends via influence change - Implement cancelDelayedJob to invalidate timer on foreground return - Clear unsent time only on outcomes success (retry on failure) - Move sendSessionTime to the actual send method (same as attributed) - Reduce min session threshold from 60s to 1s to match attributed Made-with: Cursor * Remove unused min session time threshold Both processors now use a unified `< 1` guard in sendOnFocusCallWithParams: instead of the old getMinSessionTime/hasMinSyncTime dispatch through the base class.
* chore: bump version to 5.5.1 * chore: build binaries * chore: update Swift package --------- Co-authored-by: github-actions[bot] <noreply@onesignal.com>
ci: [SDK-4493] use GH_PUSH_TOKEN for project workflow
…_release # Conflicts: # OneSignal.podspec # OneSignalXCFramework.podspec # Package.swift # iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.h # iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.m # iOS_SDK/OneSignalDevApp/OneSignalDevApp/Base.lproj/Main.storyboard # iOS_SDK/OneSignalDevApp/OneSignalDevApp/SwiftTest.swift # iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj # iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalCommonDefines.h # iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalLog.h # iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalLog.m # iOS_SDK/OneSignalSDK/OneSignalInAppMessages/Controller/OSMessagingController.h # iOS_SDK/OneSignalSDK/OneSignalInAppMessages/Controller/OSMessagingController.m # iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSIdentityOperationExecutor.swift # iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSPropertyOperationExecutor.swift # iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSSubscriptionOperationExecutor.swift # iOS_SDK/OneSignalSDK/OneSignalUser/Source/OneSignalUserManagerImpl.swift # iOS_SDK/OneSignalSDK/OneSignalUserTests/Executors/UserExecutorTests.swift # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework.zip # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/Info.plist # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/_CodeSignature/CodeDirectory # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/_CodeSignature/CodeRequirements-1 # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/_CodeSignature/CodeSignature # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64/OneSignalCore.framework/Headers/OneSignalCommonDefines.h # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64/OneSignalCore.framework/Headers/OneSignalLog.h # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64/OneSignalCore.framework/OneSignalCore # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64/OneSignalCore.framework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64/dSYMs/OneSignalCore.framework.dSYM/Contents/Resources/DWARF/OneSignalCore # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64/dSYMs/OneSignalCore.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalCore.yml # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalCore.framework/Versions/A/Headers/OneSignalCommonDefines.h # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalCore.framework/Versions/A/Headers/OneSignalLog.h # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalCore.framework/Versions/A/OneSignalCore # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalCore.framework/Versions/A/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalCore.framework.dSYM/Contents/Resources/DWARF/OneSignalCore # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalCore.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalCore.yml # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalCore.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalCore.yml # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-simulator/OneSignalCore.framework/Headers/OneSignalCommonDefines.h # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-simulator/OneSignalCore.framework/Headers/OneSignalLog.h # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-simulator/OneSignalCore.framework/OneSignalCore # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-simulator/OneSignalCore.framework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalCore.framework.dSYM/Contents/Resources/DWARF/OneSignalCore # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalCore.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalCore.yml # iOS_SDK/OneSignalSDK/OneSignal_Core/OneSignalCore.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalCore.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalCore.yml # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework.zip # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/_CodeSignature/CodeDirectory # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/_CodeSignature/CodeRequirements-1 # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/_CodeSignature/CodeSignature # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/ios-arm64/OneSignalExtension.framework/OneSignalExtension # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/ios-arm64/dSYMs/OneSignalExtension.framework.dSYM/Contents/Resources/DWARF/OneSignalExtension # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/ios-arm64/dSYMs/OneSignalExtension.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalExtension.yml # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalExtension.framework/Versions/A/OneSignalExtension # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalExtension.framework.dSYM/Contents/Resources/DWARF/OneSignalExtension # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalExtension.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalExtension.yml # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalExtension.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalExtension.yml # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalExtension.framework.dSYM/Contents/Resources/DWARF/OneSignalExtension # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalExtension.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalExtension.yml # iOS_SDK/OneSignalSDK/OneSignal_Extension/OneSignalExtension.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalExtension.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalExtension.yml # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework.zip # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/Info.plist # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/_CodeSignature/CodeDirectory # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/_CodeSignature/CodeRequirements-1 # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/_CodeSignature/CodeSignature # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/ios-arm64/OneSignalInAppMessages.framework/OneSignalInAppMessages # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/ios-arm64/dSYMs/OneSignalInAppMessages.framework.dSYM/Contents/Resources/DWARF/OneSignalInAppMessages # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/ios-arm64/dSYMs/OneSignalInAppMessages.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalInAppMessages.yml # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/ios-arm64_x86_64-simulator/OneSignalInAppMessages.framework/OneSignalInAppMessages # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalInAppMessages.framework.dSYM/Contents/Resources/DWARF/OneSignalInAppMessages # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalInAppMessages.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalInAppMessages.yml # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalInAppMessages.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalInAppMessages.yml # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/ios-x86_64-maccatalyst/OneSignalInAppMessages.framework/Versions/A/OneSignalInAppMessages # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/ios-x86_64-maccatalyst/dSYMs/OneSignalInAppMessages.framework.dSYM/Contents/Resources/DWARF/OneSignalInAppMessages # iOS_SDK/OneSignalSDK/OneSignal_InAppMessages/OneSignalInAppMessages.xcframework/ios-x86_64-maccatalyst/dSYMs/OneSignalInAppMessages.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalInAppMessages.yml # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework.zip # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/_CodeSignature/CodeDirectory # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/_CodeSignature/CodeRequirements-1 # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/_CodeSignature/CodeSignature # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-arm64/OneSignalLiveActivities.framework/OneSignalLiveActivities # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-arm64/OneSignalLiveActivities.framework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-arm64/dSYMs/OneSignalLiveActivities.framework.dSYM/Contents/Resources/DWARF/OneSignalLiveActivities # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-arm64/dSYMs/OneSignalLiveActivities.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalLiveActivities.yml # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalLiveActivities.framework/Versions/A/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-arm64_x86_64-simulator/OneSignalLiveActivities.framework/OneSignalLiveActivities # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-arm64_x86_64-simulator/OneSignalLiveActivities.framework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalLiveActivities.framework.dSYM/Contents/Resources/DWARF/OneSignalLiveActivities # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalLiveActivities.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalLiveActivities.yml # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalLiveActivities.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalLiveActivities.yml # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-x86_64-maccatalyst/OneSignalLiveActivities.framework/Versions/A/Modules/OneSignalLiveActivities.swiftmodule/x86_64-apple-ios-macabi.abi.json # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-x86_64-maccatalyst/OneSignalLiveActivities.framework/Versions/A/OneSignalLiveActivities # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-x86_64-maccatalyst/dSYMs/OneSignalLiveActivities.framework.dSYM/Contents/Resources/DWARF/OneSignalLiveActivities # iOS_SDK/OneSignalSDK/OneSignal_LiveActivities/OneSignalLiveActivities.xcframework/ios-x86_64-maccatalyst/dSYMs/OneSignalLiveActivities.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalLiveActivities.yml # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework.zip # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/Info.plist # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/_CodeSignature/CodeDirectory # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/_CodeSignature/CodeRequirements-1 # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/_CodeSignature/CodeSignature # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/ios-arm64/OneSignalLocation.framework/OneSignalLocation # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/ios-arm64/dSYMs/OneSignalLocation.framework.dSYM/Contents/Resources/DWARF/OneSignalLocation # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/ios-arm64/dSYMs/OneSignalLocation.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalLocation.yml # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalLocation.framework.dSYM/Contents/Resources/DWARF/OneSignalLocation # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalLocation.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalLocation.yml # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalLocation.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalLocation.yml # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/ios-x86_64-maccatalyst/OneSignalLocation.framework/Versions/A/OneSignalLocation # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/ios-x86_64-maccatalyst/dSYMs/OneSignalLocation.framework.dSYM/Contents/Resources/DWARF/OneSignalLocation # iOS_SDK/OneSignalSDK/OneSignal_Location/OneSignalLocation.xcframework/ios-x86_64-maccatalyst/dSYMs/OneSignalLocation.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalLocation.yml # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework.zip # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/Info.plist # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/_CodeSignature/CodeDirectory # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/_CodeSignature/CodeRequirements-1 # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/_CodeSignature/CodeSignature # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/ios-arm64/OneSignalNotifications.framework/OneSignalNotifications # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/ios-arm64/dSYMs/OneSignalNotifications.framework.dSYM/Contents/Resources/DWARF/OneSignalNotifications # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/ios-arm64/dSYMs/OneSignalNotifications.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalNotifications.yml # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalNotifications.framework/Versions/A/OneSignalNotifications # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalNotifications.framework.dSYM/Contents/Resources/DWARF/OneSignalNotifications # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalNotifications.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalNotifications.yml # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalNotifications.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalNotifications.yml # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalNotifications.framework.dSYM/Contents/Resources/DWARF/OneSignalNotifications # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalNotifications.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalNotifications.yml # iOS_SDK/OneSignalSDK/OneSignal_Notifications/OneSignalNotifications.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalNotifications.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalNotifications.yml # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework.zip # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/Info.plist # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/_CodeSignature/CodeDirectory # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/_CodeSignature/CodeRequirements-1 # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/_CodeSignature/CodeSignature # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64/OneSignalOSCore.framework/Modules/OneSignalOSCore.swiftmodule/arm64-apple-ios.abi.json # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64/OneSignalOSCore.framework/Modules/OneSignalOSCore.swiftmodule/arm64-apple-ios.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64/OneSignalOSCore.framework/OneSignalOSCore # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64/OneSignalOSCore.framework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64/dSYMs/OneSignalOSCore.framework.dSYM/Contents/Resources/DWARF/OneSignalOSCore # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64/dSYMs/OneSignalOSCore.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalOSCore.yml # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalOSCore.framework/Versions/A/Modules/OneSignalOSCore.swiftmodule/x86_64-apple-ios-macabi.abi.json # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalOSCore.framework/Versions/A/Modules/OneSignalOSCore.swiftmodule/x86_64-apple-ios-macabi.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalOSCore.framework/Versions/A/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-simulator/OneSignalOSCore.framework/Modules/OneSignalOSCore.swiftmodule/arm64-apple-ios-simulator.abi.json # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-simulator/OneSignalOSCore.framework/Modules/OneSignalOSCore.swiftmodule/arm64-apple-ios-simulator.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-simulator/OneSignalOSCore.framework/Modules/OneSignalOSCore.swiftmodule/x86_64-apple-ios-simulator.abi.json # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-simulator/OneSignalOSCore.framework/Modules/OneSignalOSCore.swiftmodule/x86_64-apple-ios-simulator.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-simulator/OneSignalOSCore.framework/OneSignalOSCore # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-simulator/OneSignalOSCore.framework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalOSCore.framework.dSYM/Contents/Resources/DWARF/OneSignalOSCore # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalOSCore.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalOSCore.yml # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalOSCore.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalOSCore.yml # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-x86_64-maccatalyst/OneSignalOSCore.framework/Versions/A/Headers/OneSignalOSCore-Swift.h # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-x86_64-maccatalyst/OneSignalOSCore.framework/Versions/A/OneSignalOSCore # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-x86_64-maccatalyst/dSYMs/OneSignalOSCore.framework.dSYM/Contents/Resources/DWARF/OneSignalOSCore # iOS_SDK/OneSignalSDK/OneSignal_OSCore/OneSignalOSCore.xcframework/ios-x86_64-maccatalyst/dSYMs/OneSignalOSCore.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalOSCore.yml # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework.zip # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/_CodeSignature/CodeDirectory # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/_CodeSignature/CodeRequirements-1 # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/_CodeSignature/CodeSignature # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64/OneSignalOutcomes.framework/OneSignalOutcomes # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64/dSYMs/OneSignalOutcomes.framework.dSYM/Contents/Resources/DWARF/OneSignalOutcomes # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64/dSYMs/OneSignalOutcomes.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalOutcomes.yml # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalOutcomes.framework/Versions/A/OneSignalOutcomes # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalOutcomes.framework.dSYM/Contents/Resources/DWARF/OneSignalOutcomes # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalOutcomes.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalOutcomes.yml # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalOutcomes.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalOutcomes.yml # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64_x86_64-simulator/OneSignalOutcomes.framework/OneSignalOutcomes # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalOutcomes.framework.dSYM/Contents/Resources/DWARF/OneSignalOutcomes # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalOutcomes.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalOutcomes.yml # iOS_SDK/OneSignalSDK/OneSignal_Outcomes/OneSignalOutcomes.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalOutcomes.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalOutcomes.yml # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework.zip # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/_CodeSignature/CodeDirectory # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/_CodeSignature/CodeRequirements-1 # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/_CodeSignature/CodeSignature # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64/OneSignalUser.framework/Headers/OneSignalUser-Swift.h # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/arm64-apple-ios.abi.json # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/arm64-apple-ios.private.swiftinterface # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/arm64-apple-ios.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/arm64-apple-ios.swiftinterface # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64/OneSignalUser.framework/OneSignalUser # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64/OneSignalUser.framework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64/dSYMs/OneSignalUser.framework.dSYM/Contents/Resources/DWARF/OneSignalUser # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64/dSYMs/OneSignalUser.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalUser.yml # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalUser.framework/Versions/A/Modules/OneSignalUser.swiftmodule/x86_64-apple-ios-macabi.private.swiftinterface # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalUser.framework/Versions/A/Modules/OneSignalUser.swiftmodule/x86_64-apple-ios-macabi.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalUser.framework/Versions/A/Modules/OneSignalUser.swiftmodule/x86_64-apple-ios-macabi.swiftinterface # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalUser.framework/Versions/A/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/Headers/OneSignalUser-Swift.h # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/arm64-apple-ios-simulator.abi.json # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/arm64-apple-ios-simulator.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/arm64-apple-ios-simulator.swiftinterface # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/x86_64-apple-ios-simulator.abi.json # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/x86_64-apple-ios-simulator.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/Modules/OneSignalUser.swiftmodule/x86_64-apple-ios-simulator.swiftinterface # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/OneSignalUser # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/OneSignalUser.framework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalUser.framework.dSYM/Contents/Resources/DWARF/OneSignalUser # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalUser.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalUser.yml # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalUser.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalUser.yml # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-x86_64-maccatalyst/OneSignalUser.framework/Versions/A/Headers/OneSignalUser-Swift.h # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-x86_64-maccatalyst/OneSignalUser.framework/Versions/A/Modules/OneSignalUser.swiftmodule/x86_64-apple-ios-macabi.abi.json # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-x86_64-maccatalyst/OneSignalUser.framework/Versions/A/OneSignalUser # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-x86_64-maccatalyst/dSYMs/OneSignalUser.framework.dSYM/Contents/Resources/DWARF/OneSignalUser # iOS_SDK/OneSignalSDK/OneSignal_User/OneSignalUser.xcframework/ios-x86_64-maccatalyst/dSYMs/OneSignalUser.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalUser.yml # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework.zip # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/_CodeSignature/CodeDirectory # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/_CodeSignature/CodeRequirements-1 # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/_CodeSignature/CodeSignature # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64/OneSignalFramework.framework/Modules/OneSignalFramework.swiftmodule/arm64-apple-ios.abi.json # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64/OneSignalFramework.framework/Modules/OneSignalFramework.swiftmodule/arm64-apple-ios.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64/OneSignalFramework.framework/OneSignalFramework # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64/dSYMs/OneSignalFramework.framework.dSYM/Contents/Resources/DWARF/OneSignalFramework # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64/dSYMs/OneSignalFramework.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalFramework.yml # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalFramework.framework/Versions/A/Modules/OneSignalFramework.swiftmodule/arm64-apple-ios-macabi.abi.json # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalFramework.framework/Versions/A/Modules/OneSignalFramework.swiftmodule/arm64-apple-ios-macabi.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalFramework.framework/Versions/A/Modules/OneSignalFramework.swiftmodule/x86_64-apple-ios-macabi.abi.json # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalFramework.framework/Versions/A/Modules/OneSignalFramework.swiftmodule/x86_64-apple-ios-macabi.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-maccatalyst/OneSignalFramework.framework/Versions/A/OneSignalFramework # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalFramework.framework.dSYM/Contents/Resources/DWARF/OneSignalFramework # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalFramework.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalFramework.yml # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/OneSignalFramework.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalFramework.yml # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-simulator/OneSignalFramework.framework/Modules/OneSignalFramework.swiftmodule/arm64-apple-ios-simulator.abi.json # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-simulator/OneSignalFramework.framework/Modules/OneSignalFramework.swiftmodule/arm64-apple-ios-simulator.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-simulator/OneSignalFramework.framework/Modules/OneSignalFramework.swiftmodule/x86_64-apple-ios-simulator.abi.json # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-simulator/OneSignalFramework.framework/Modules/OneSignalFramework.swiftmodule/x86_64-apple-ios-simulator.swiftdoc # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-simulator/OneSignalFramework.framework/OneSignalFramework # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-simulator/OneSignalFramework.framework/_CodeSignature/CodeResources # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalFramework.framework.dSYM/Contents/Resources/DWARF/OneSignalFramework # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalFramework.framework.dSYM/Contents/Resources/Relocations/aarch64/OneSignalFramework.yml # iOS_SDK/OneSignalSDK/OneSignal_XCFramework/OneSignalFramework.xcframework/ios-arm64_x86_64-simulator/dSYMs/OneSignalFramework.framework.dSYM/Contents/Resources/Relocations/x86_64/OneSignalFramework.yml
…Server - IAMIntegrationTests.swift: replace main's getFromServer(subscriptionId) call with the branch's no-arg getInAppMessagesFromServer(). - OSMessagingControllerUserStateTests.swift: rewrite the 3 tests to verify behavior (whether the IAM network request fires) instead of KVC-ing the removed shouldFetchOnUserChangeWithSubscriptionID property. The unified shouldRetryGetInAppMessagesOnUserChange flag is file-static and not directly observable, so behavior is the testable surface.
The branch added OSLoggable as a requirement of OSOperationExecutor, but OSCustomEventsExecutor came in from main and predates that requirement. Mirror the logSelf() implementation used by the other executors so the class conforms.
Mirrors the JWT-aware pattern of OSPropertyOperationExecutor so custom events behave consistently with the other user-scoped executors: - Executor init now takes jwtConfig: OSUserJwtConfig and subscribes as an OSUserJwtConfigListener. - uncacheDeltas / uncacheRequests drop entries whose identity model has no externalId when JWT is required, and load pendingAuthRequests from the new persistence key. - processDeltaQueue is gated on jwtConfig.isRequired being known, and drops in-flight deltas for JWT-required users without externalId. - executeRequest checks addJWTHeaderIsValid; on failure it pends the request via pendRequestUntilAuthUpdated. 401 responses trigger handleUnauthorizedError, which invalidates the JWT and pends the request for retry when the JWT updates. - onRequiresUserAuthChanged drops invalid in-flight deltas/requests when auth turns on; onJwtUpdated re-queues this externalId's pending requests. Request-level: OSRequestCustomEvents.prepareForExecution no longer checks JWT inline (now handled by the executor before prepareForExecution), matching the OSRequestUpdateProperties shape. Renamed the call from the non-existent addPushSubscriptionIdToAdditionalHeaders to the branch's addPushSubscriptionToAdditionalHeaders. Adds OS_CUSTOM_EVENTS_EXECUTOR and OS_CUSTOM_EVENTS_EXECUTOR_PENDING_QUEUE_KEY constants. Updates OneSignalUserManagerImpl to pass jwtConfig at init, and the test mock to do likewise. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| @available(iOS 16.2, *) | ||
| private static func listenForContentUpdates<Attributes: OneSignalLiveActivityAttributes>(_ activityType: Attributes.Type, activity: Activity<Attributes>) { | ||
| Task { | ||
| for await content in activity.contentUpdates { | ||
| // Don't track a live activity started / updated "in app" without a notification | ||
| if let notificationId = activity.content.state.onesignal?.notificationId { | ||
| OneSignalLiveActivitiesManagerImpl.addReceiveReceipts(notificationId: notificationId, activityType: "\(activityType)", activityId: activity.attributes.onesignal.activityId) | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🔴 The new listenForContentUpdates loop iterates for await content in activity.contentUpdates but the body reads activity.content.state.onesignal?.notificationId instead of the yielded content.state.onesignal?.notificationId — the iteration variable is unused. Under rapid back-to-back content updates, activity.content can advance to the next snapshot before the body runs, so iteration N reads iteration N+1's notificationId; the duplicate is then deduped by the receiveReceipts RequestCache (keyed by notificationId), silently dropping the earlier update's receipt. Fix: if let notificationId = content.state.onesignal?.notificationId.
Extended reasoning...
The bug. OneSignalLiveActivitiesManagerImpl.swift:332-342 introduces listenForContentUpdates, which iterates the async sequence as for await content in activity.contentUpdates but never reads the bound content value — it instead reads activity.content.state.onesignal?.notificationId. The iteration variable is unused, which is the smoking gun: per Apple's ActivityKit docs, Activity<>.contentUpdates yields each ActivityContent snapshot as it arrives, while Activity<>.content is the current/latest snapshot the system has applied to the activity. The sibling loop directly above (lines 322-327) correctly uses the bound pushToken variable, so this looks like a copy-paste oversight rather than an intentional choice.\n\nWhy existing code doesn't prevent it. for await processes iterations sequentially; if a second contentUpdate yields while the body of iteration N is still running, activity.content has already advanced to the newer snapshot by the time the body's activity.content.state.onesignal?.notificationId read executes. There's nothing pinning the read to the value that was yielded.\n\nStep-by-step proof. Suppose two content updates arrive in rapid succession with notificationId values N_A then N_B (e.g., two backend pushes back-to-back):\n\n1. The async sequence yields ActivityContent(state.onesignal.notificationId = N_A). The loop binds this to content (unused).\n2. Before the body of iteration 1 runs, the system applies the second update, so activity.content.state.onesignal.notificationId == N_B.\n3. Iteration 1's body reads activity.content.state.onesignal?.notificationId → gets N_B. Calls addReceiveReceipts(notificationId: N_B, …), which enqueues an OSRequestLiveActivityReceiveReceipts keyed by N_B into the receiveReceipts cache.\n4. Iteration 2 starts. The yielded content would be ActivityContent(state.onesignal.notificationId = N_B), but the body again reads activity.content → still N_B. Calls addReceiveReceipts(notificationId: N_B, …) again.\n5. In OSLiveActivitiesExecutor.append, the cache's add uses updateValue(_, forKey: request.key) where key == notificationId. The second N_B request just overwrites the first in the dictionary — deduped.\n\nNet result: N_A is never reported (the iteration that should have read it read N_B instead), and the duplicate N_B collapses to a single request. The receipt for the earlier content update is silently dropped.\n\nImpact. This produces silent under-reporting of receive-receipts whenever content updates land in close succession (multiple background pushes, or a server update arriving while the prior body is still in flight). It directly undermines the accuracy of the new receive-receipts feature this loop was added to support. The bug is also hard to diagnose: there's no error or crash, just missing analytics events. iOS does rate-limit live activity push updates, which narrows the window in practice, but the issue is a real correctness problem in PR-introduced code with a trivial one-line fix.\n\nFix.\n\nswift\nfor await content in activity.contentUpdates {\n if let notificationId = content.state.onesignal?.notificationId {\n OneSignalLiveActivitiesManagerImpl.addReceiveReceipts(notificationId: notificationId, activityType: "\(activityType)", activityId: activity.attributes.onesignal.activityId)\n }\n}\n\n\nThis is also the idiomatic AsyncSequence iteration pattern, and matches listenForActivityPushToUpdate directly above which correctly uses its loop-bound variable.
| + (void)didReceiveRemoteNotification:(NSDictionary*)userInfo completionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { | ||
| if (![self isSwizzlingDisabled]) { | ||
| [OneSignalLog onesignalLog:ONE_S_LL_WARN message:@"OneSignal: didReceiveRemoteNotification:completionHandler: ignored because swizzling is active. Remove the manual call or set OneSignal_disable_swizzling to true in Info.plist."]; | ||
| return; | ||
| } | ||
| BOOL startedBackgroundJob = [self processReceivedRemoteNotification:userInfo completionHandler:completionHandler]; | ||
| if (!startedBackgroundJob) { | ||
| completionHandler(UIBackgroundFetchResultNewData); | ||
| } | ||
| } |
There was a problem hiding this comment.
🔴 When swizzling is active, +[OSNotificationsManager didReceiveRemoteNotification:completionHandler:] (lines 938-947) logs a warning and returns without invoking completionHandler, while the sibling willPresentNotificationWithPayload:completion: (lines 675-682) correctly invokes completion([OSNotification new]) on the same misuse path. Per Apple's docs, failing to call the fetch completion handler causes iOS to throttle or suspend future background notification delivery to the app. Fix: invoke completionHandler(UIBackgroundFetchResultNoData) before the early return, matching the willPresent pattern.
Extended reasoning...
What the bug is
The PR introduces a new manual-integration API surface on OSNotificationsManager that lets developers forward UIApplicationDelegate / UNUserNotificationCenterDelegate callbacks to OneSignal when SDK swizzling is disabled. Each new class method has a guard that fires when swizzling is still active (a developer misuse / misconfiguration case): it logs a warning and returns early so the SDK does not double-process the callback.
The sibling +willPresentNotificationWithPayload:completion: at OSNotificationsManager.m:675-682 handles this guard correctly:
if (![self isSwizzlingDisabled]) {
[OneSignalLog onesignalLog:ONE_S_LL_WARN message:@"...ignored because swizzling is active..."];
completion([OSNotification new]); // invokes the caller's completion before bailing
return;
}But +didReceiveRemoteNotification:completionHandler: at OSNotificationsManager.m:938-947 does not:
if (![self isSwizzlingDisabled]) {
[OneSignalLog onesignalLog:ONE_S_LL_WARN message:@"...ignored because swizzling is active..."];
return; // <-- completionHandler is never called
}How it manifests / impact
iOS calls application:didReceiveRemoteNotification:fetchCompletionHandler: for content-available pushes and expects the app to invoke the supplied completion handler in a timely manner. Apple's documentation is explicit that failing to call the handler causes the system to throttle or suspend future background notification delivery to the app (and may terminate the app). The handler must be called exactly once, regardless of how the app routes the work internally.
The trigger scenario the warning itself describes is realistic and is even illustrated by this PR's own Dev App changes:
- A developer enables the manual-integration path, copies the AppDelegate forwarders from
iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.m(which call[OneSignal.Notifications didReceiveRemoteNotification:userInfo completionHandler:completionHandler]), but forgets to setOneSignal_disable_swizzling = truein Info.plist. - Or they are mid-refactor: forwarders are wired up but the plist flag has not been flipped yet.
- Or they hot-swap configurations during testing.
In all of these states, swizzling is still active, the SDK's swizzled wrapper has already run the dev's AppDelegate (which forwards to the SDK), and the dev's AppDelegate trusts the SDK to invoke its completion handler. The SDK swizzled wrapper at UIApplicationDelegate+OneSignalNotifications.m only calls the completion handler itself when forwarder.hasReceiver is false — when a receiver exists, the receiver is expected to invoke it. So the handler never fires, and iOS throttles background pushes for that app. The one-time warning log gives no hint that this is the consequence.
Step-by-step proof
Assume swizzling is active (OneSignal_disable_swizzling unset or false) and the developer has implemented manual forwarders in their AppDelegate:
- iOS delivers a content-available push and calls the dev's swizzled
application:didReceiveRemoteNotification:fetchCompletionHandler:with a non-nilcompletionHandler. - The SDK's swizzled wrapper runs first; because the dev defined the selector,
forwarder.hasReceiveris true, so the SDK invokes the dev's original AppDelegate method and does NOT call the completion handler itself. - The dev's AppDelegate calls
[OneSignal.Notifications didReceiveRemoteNotification:userInfo completionHandler:completionHandler](this is exactly what the PR's Dev App now does). - Inside
+didReceiveRemoteNotification:completionHandler:(line 938),[self isSwizzlingDisabled]returns NO, so the method logs the warning andreturns at line 941 without calling the suppliedcompletionHandler. - Control unwinds. Nobody — not the SDK, not the dev — calls iOS's fetch completion handler.
- iOS waits, observes the handler was not invoked, and applies background-notification throttling to the app going forward.
Contrast with step 4 for the willPresent path: that method calls completion([OSNotification new]) first, so the foreground-presentation flow is at least safe.
Why existing code doesn't prevent it
- The guard exists specifically to catch this misconfiguration, so it is on the expected misuse path.
- The warning log is informational only and does not invoke the handler.
- The swizzled-wrapper-only call to the handler (
forwarder.hasReceiver ? nil : completionHandlerinUIApplicationDelegate+OneSignalNotifications.m) only runs when the dev did not implement the selector at all; here the dev did implement it (to forward to OneSignal), so it is bypassed.
Fix
Call the completion handler before returning, matching the sibling willPresent pattern:
+ (void)didReceiveRemoteNotification:(NSDictionary*)userInfo
completionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
if (![self isSwizzlingDisabled]) {
[OneSignalLog onesignalLog:ONE_S_LL_WARN
message:@"OneSignal: didReceiveRemoteNotification:completionHandler: ignored because swizzling is active. ..."];
completionHandler(UIBackgroundFetchResultNoData); // <-- add this
return;
}
...
}UIBackgroundFetchResultNoData is the safe default since the SDK is intentionally not processing the payload on this path. This is one line and brings the method in line with willPresent's well-handled equivalent guard.
| private func caches(_ block: (RequestCache) -> Void) { | ||
| block(self.startTokens) | ||
| block(self.updateTokens) | ||
| block(self.receiveReceipts) | ||
| block(self.clickEvents) | ||
| } |
There was a problem hiding this comment.
🔴 In OSLiveActivitiesExecutor.onPushSubscriptionDidChange (lines 158-171), the closure passed to self.caches { _ in self.startTokens.markAllUnsuccessful() } ignores its RequestCache parameter and always hard-codes self.startTokens. Since this PR extends caches(_:) at lines 202-207 to iterate four caches (startTokens, updateTokens, receiveReceipts, clickEvents), startTokens.markAllUnsuccessful() now runs 4× while updateTokens / receiveReceipts / clickEvents are never re-marked — so after a push-subscription-id change (login/logout) only start-token requests are resent with the new ID, contradicting the comment on line 163 that says "we need to re-send up all update and start tokens with the new ID." Fix: use the closure parameter, e.g. self.caches { cache in cache.markAllUnsuccessful() }.
Extended reasoning...
What the bug is
In OSLiveActivitiesExecutor.onPushSubscriptionDidChange (file iOS_SDK/OneSignalSDK/OneSignalLiveActivities/Source/Executors/OSLiveActivitiesExecutor.swift, lines 158-171), the code is:
func onPushSubscriptionDidChange(state: OneSignalUser.OSPushSubscriptionChangedState) {
if state.previous.id == state.current.id {
return
}
// when a push subscription id changes, we need to re-send up all update and start tokens with the new ID.
self.requestDispatch.async {
self.caches { _ in
self.startTokens.markAllUnsuccessful()
}
self.pollPendingRequests()
}
}The closure passed to self.caches { ... } ignores its RequestCache parameter (_ in) and unconditionally invokes self.startTokens.markAllUnsuccessful(). Meanwhile, caches(_:) at lines 202-207 invokes the block once per cache:
private func caches(_ block: (RequestCache) -> Void) {
block(self.startTokens)
block(self.updateTokens)
block(self.receiveReceipts) // added in this PR
block(self.clickEvents) // added in this PR
}So the body fires 4 times, but each time it operates on self.startTokens — startTokens.markAllUnsuccessful() is called 4× (idempotent, same as once), and updateTokens, receiveReceipts, and clickEvents are never marked unsuccessful.
Why existing code does not prevent it
pollPendingRequests (line 187) only re-executes requests where !request.requestSuccessful (line 195). Since the bug never flips requestSuccessful = false on the other three caches, those cached requests stay marked successful and are skipped on the next poll. There is no other code path that re-marks them after a subscription-id change.
Why this PR makes it worse
The closure has always hard-coded startTokens, so the update-tokens half of the bug is pre-existing. However, this PR:
- Adds
receiveReceiptsandclickEventsto the iteration incaches(_:)(lines 205-206), so two additional caches now silently miss the retry. - Adds two new request types (
OSRequestLiveActivityReceiveReceipts,OSRequestLiveActivityClicked) that route into those caches viagetCache(_:)(lines 209-219) — strictly more state now leaks.
The comment on line 163 explicitly states the intent: "we need to re-send up all update and start tokens with the new ID." The current implementation does not satisfy that intent for update tokens (pre-existing) and now also does not satisfy it for two newly added request types (regression-adjacent).
Step-by-step proof
- Cold-start with subscription id
sub_A. SDK enqueuesOSRequestSetUpdateToken(key: "activity_1", token: "tok_1"). The request fires successfully againstsub_A, gets cached inupdateTokenswithrequestSuccessful = true. (OSLiveActivitiesExecutorTests.testSendUpdateTokenRequestWithSuccessfulRequestcovers this happy path.) - User logs out → logs in.
onPushSubscriptionDidChangefires withstate.previous.id = sub_A,state.current.id = sub_B. - The dispatched block runs
self.caches { _ in self.startTokens.markAllUnsuccessful() }:- Iteration 1 (cache=startTokens): runs
self.startTokens.markAllUnsuccessful()— fine. - Iteration 2 (cache=updateTokens): runs
self.startTokens.markAllUnsuccessful()again —updateTokens["activity_1"].requestSuccessfulstaystrue. - Iteration 3 (cache=receiveReceipts): same, no-op on the actual receiveReceipts cache.
- Iteration 4 (cache=clickEvents): same, no-op on the actual clickEvents cache.
- Iteration 1 (cache=startTokens): runs
pollPendingRequestsruns ~pollIntervalSecondslater and at line 195 filterscache.items.values.filter({ !$0.requestSuccessful }). ForupdateTokens["activity_1"]the flag is stilltrue, so it is skipped.- Result: the device’s update-token registration is stranded on
sub_Aeven though the device is now subscriptionsub_B. The push service routes update notifications tosub_A’s mapping and the new subscription receives no Live Activity updates until the next time the token actually changes (e.g., system rotates the pushToken).
The two PR-added caches behave identically — any pending receive-receipt or click-event request that failed before the subscription change will never be retried against the new subscription id.
Fix
Use the closure parameter:
self.caches { cache in
cache.markAllUnsuccessful()
}This is the obvious intent from the comment on line 163 and from pollPendingRequests already using self?.caches { cache in ... } correctly on line 194. Fix is one line, and there is unit-test coverage scaffolding in OSLiveActivitiesExecutorTests to confirm.
since this is just for rebasing, we can refactor in followup
513f1a4 to
4904ce4
Compare
no longer used
The workflow stamped response_time_in_business_days into a hidden probot metadata block on each issue. No consumer reads the value.
- .travis.yml: pins Xcode 11.1 / iOS 13.1 from 2019; CI runs on .github/workflows/ci.yml (Xcode 16.4). - issue_template.md: shadowed by .github/ISSUE_TEMPLATE/*.yml form templates, which GitHub prefers. - default: ci.yml writes this file every run, so the committed copy is not load-bearing.
Description
One Line Summary
Merge
origin/main(5.5.1) into the identity verification feature branch so it's current with what shipped to production.Details
Motivation
The identity verification feature branch (
identity_verification_release/identity_verification_beta) was last synced before 5.4.x, leaving itsignificantly behind
main.Scope
This PR is a merge with conflict resolution and minimum-impact fixes;
it intentionally avoids new feature work or large refactors.
Testing
Unit testing
Fixed unit tests - all pass locally
Manual testing
app builds and runs as expected,
Affected code checklist
Checklist
Overview
Testing
Final pass