Skip to content

iOS: add APNs registration and notification signing config#20308

Merged
mbelinky merged 3 commits intomainfrom
mb/pr-ios-apns-signing
Feb 18, 2026
Merged

iOS: add APNs registration and notification signing config#20308
mbelinky merged 3 commits intomainfrom
mb/pr-ios-apns-signing

Conversation

@mbelinky
Copy link
Contributor

@mbelinky mbelinky commented Feb 18, 2026

Summary

  • register for remote notifications in iOS app lifecycle
  • add APNs entitlements/signing/plist wiring across iOS targets
  • align bundle-id placeholders for watch/extension targets for signing consistency

Testing

  • not run in this PR prep flow

Greptile Summary

This PR adds APNs (Apple Push Notification service) registration to the iOS app, along with signing/entitlements configuration and bundle ID variable alignment for watch targets.

  • APNs registration: Adds OpenClawAppDelegate that registers for remote notifications on launch, forwards device tokens to NodeAppModel, which persists them in UserDefaults and sends a push.apns.register event to the gateway on connect. Includes sandbox/production environment detection.
  • Entitlements: New OpenClaw.entitlements file with aps-environment capability, wired in project.yml.
  • Signing config: Adds default bundle ID variables for watch app/extension targets in Config/Signing.xcconfig, with corresponding overrides in LocalSigning.xcconfig.example.
  • Bundle ID alignment: Replaces hardcoded bundle IDs in watch Info.plist files and project.yml with xcconfig variables for signing consistency across all targets.
  • WatchConnectivity fix: Moves replyHandler call outside of Task { @MainActor } in WatchConnectivityReceiver, fixing a potential crash where the reply handler could be called after the system timeout.
  • Share extension: Adds movie support (NSExtensionActivationSupportsMovieWithMaxCount) and adds info.properties in project.yml for XcodeGen.
  • SwiftLint: Raises type_body_length limits to accommodate NodeAppModel growth.
  • Version bump: All targets updated to 2026.2.18.

Confidence Score: 4/5

  • This PR is generally safe to merge with one timing concern to consider in the app delegate wiring.
  • The changes are well-structured: APNs registration follows standard iOS patterns, bundle ID variables improve maintainability, and the WatchConnectivity replyHandler fix addresses a real correctness issue. The one concern is a potential race condition where the APNs device token callback could fire before appModel is wired to the delegate (since it's set in a .task modifier), which could silently drop the token on first launch or warm re-registration. This is mitigated by the token usually arriving after view appearance and by the best-effort nature of push registration, but it would be more robust to wire the model in didFinishLaunchingWithOptions or buffer the token in the delegate.
  • apps/ios/Sources/OpenClawApp.swift - potential race between APNs token delivery and appModel wiring

Last reviewed commit: 0c6ba66

@openclaw-barnacle openclaw-barnacle bot added app: ios App: ios size: S maintainer Maintainer-authored PR labels Feb 18, 2026
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

12 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +14 to +15
{
application.registerForRemoteNotifications()
Copy link
Contributor

Choose a reason for hiding this comment

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

Race between APNs callback and appModel wiring

registerForRemoteNotifications() is called in didFinishLaunchingWithOptions (line 15), but appDelegate.appModel is only set later inside a .task modifier (line 52) when the SwiftUI view appears. If didRegisterForRemoteNotificationsWithDeviceToken fires before the view body renders, appModel is still nil and the token is silently dropped via optional chaining (line 21). Since updateAPNsDeviceToken is the only path that persists the token to UserDefaults, a subsequent registerAPNsTokenIfNeeded on gateway connect would also find no token.

In practice, the APNs network round-trip makes this unlikely, but on a warm re-registration (where the OS may have a cached token) it could happen. Consider wiring the appModel in didFinishLaunchingWithOptions instead, or storing the device token in the delegate and forwarding it once appModel is assigned.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/ios/Sources/OpenClawApp.swift
Line: 14:15

Comment:
**Race between APNs callback and `appModel` wiring**

`registerForRemoteNotifications()` is called in `didFinishLaunchingWithOptions` (line 15), but `appDelegate.appModel` is only set later inside a `.task` modifier (line 52) when the SwiftUI view appears. If `didRegisterForRemoteNotificationsWithDeviceToken` fires before the view body renders, `appModel` is still `nil` and the token is silently dropped via optional chaining (line 21). Since `updateAPNsDeviceToken` is the only path that persists the token to `UserDefaults`, a subsequent `registerAPNsTokenIfNeeded` on gateway connect would also find no token.

In practice, the APNs network round-trip makes this unlikely, but on a warm re-registration (where the OS may have a cached token) it could happen. Consider wiring the `appModel` in `didFinishLaunchingWithOptions` instead, or storing the device token in the delegate and forwarding it once `appModel` is assigned.

How can I resolve this? If you propose a fix, please make it concise.

@mbelinky mbelinky force-pushed the mb/pr-ios-apns-signing branch from 0c6ba66 to 6141800 Compare February 18, 2026 19:36
@mbelinky mbelinky merged commit c2d12b7 into main Feb 18, 2026
9 checks passed
@mbelinky mbelinky deleted the mb/pr-ios-apns-signing branch February 18, 2026 19:37
@mbelinky
Copy link
Contributor Author

Merged via squash.

Thanks @mbelinky!

anschmieg pushed a commit to anschmieg/openclaw that referenced this pull request Feb 19, 2026
…20308)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 6141800
Co-authored-by: mbelinky <[email protected]>
Co-authored-by: mbelinky <[email protected]>
Reviewed-by: @mbelinky
@albeebe
Copy link

albeebe commented Feb 20, 2026

lgtm

HenryChenV pushed a commit to HenryChenV/openclaw that referenced this pull request Feb 20, 2026
…20308)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 6141800
Co-authored-by: mbelinky <[email protected]>
Co-authored-by: mbelinky <[email protected]>
Reviewed-by: @mbelinky
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: ios App: ios maintainer Maintainer-authored PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments