feat: register native APNs/FCM device token on push.native (P2 push, slice 3a — mobile) - #8
feat: register native APNs/FCM device token on push.native (P2 push, slice 3a — mobile)#8saucam wants to merge 1 commit into
Conversation
…slice 3a — mobile) Completes slice 3a's mobile half. When the daemon advertises push.native (transport native/relay — it sends via APNs/FCM directly), the client now registers this device's NATIVE push token (getDevicePushTokenAsync) instead of the Expo token. Expo transport (capability "push") is unchanged. - push-protocol.ts: PUSH_NATIVE_CAPABILITY = "push.native". - push.ts registerForPush: pick the token type by the advertised capability — native (raw APNs/FCM token, no EAS projectId) for push.native, Expo for push; register nothing if neither is advertised. Backward-compatible. Verified: tsc + eslint clean; expo export (web) bundles 1020 modules. Device e2e (real APNs/FCM delivery) needs a dev build + a daemon running transport native with your .p8 + Firebase creds. Signed-off-by: Yash Datta <saucam@gmail.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
There was a problem hiding this comment.
🔮 Oracle Review
🎯 Start Here
src/lib/push-protocol.ts (~20 min) — Security changes in push-protocol.ts
📋 PR Summary
What this PR does: Completes the mobile half of self-hosted native push by allowing clients to register raw APNs/FCM tokens when the daemon advertises the push.native capability.
Key changes:
- Added PUSH_NATIVE_CAPABILITY constant to the protocol shim.
- Implemented conditional token registration in registerForPush to select native tokens for push.native or Expo tokens for standard push.
- Maintained backward compatibility with existing Expo-based daemon configurations.
Areas affected: Push notification registration logic, Protocol definitions
Testing notes: Full end-to-end verification requires an EAS dev build and a daemon running with native transport configuration.
🔍 Code Review
This is a well-structured implementation that cleanly integrates native push support without disrupting existing Expo workflows. The capability-driven approach effectively abstracts the token selection logic, making the code easy to maintain and extend.
What's good:
- ✨ The capability-based routing logic is a strong pattern that ensures clear separation between protocol detection and implementation.
- ✨ Smart use of the protocol shim to decouple from the unreleased @codeoid/protocol package.
Generated by Oracle - Highflame's AI Code Reviewer
| ); | ||
| let token: string; | ||
| if (wantsNative) { | ||
| // Raw APNs (iOS) / FCM (Android) device token — the self-hosted daemon or |
There was a problem hiding this comment.
Defensive type coercion may be unnecessary
Expo's getDevicePushTokenAsync() returns Promise<DevicePushToken> where data is typed as string. The defensive type check typeof device.data === 'string' ? device.data : String(device.data) is reasonable but unnecessary given the type contract. However, it doesn't cause harm and provides runtime safety if the API contract changes.
Suggested fix:
| // Raw APNs (iOS) / FCM (Android) device token — the self-hosted daemon or | |
| Consider simplifying to `token = device.data;` if you're confident in Expo's type contract, or keep as-is for defense in depth. |
What
Slice 3a — mobile half. Completes self-hosted native push: when the daemon advertises
push.native(itsnative/relaytransport sends via APNs/FCM directly — see codeoid #261), the client registers this device's native APNs/FCM token instead of an Expo token.Change
push-protocol.ts:PUSH_NATIVE_CAPABILITY = "push.native".push.tsregisterForPush: picks the token type by what the daemon advertises —push.native→getDevicePushTokenAsync()(raw APNs/FCM token; no EAS projectId needed),push→getExpoPushTokenAsync()(unchanged, slice 2),Backward-compatible: a daemon on Expo still advertises
push; a daemon onnative/relayadvertisespush.native. The registration wire message (push.register { token, platform }) is unchanged —platformalready tells the daemon/relay whether to send via APNs or FCM.Verification
tsc+eslintclean;expo export --platform webbundles 1020 modules. Device e2e (real APNs/FCM delivery + tap) needs an EAS dev build + a daemon runningtransport: nativewith your.p8+ Firebase service account — the one step that can't run headlessly.Follow-ups
push-protocol.tsshim and importpush.*+ capabilities from@codeoid/protocolonce a release ships them (both slices used the shim to decouple from the unreleased protocol).src/relayin codeoid) when the multi-user/hosted path is needed — mobile needs no further change (it already registers native tokens forrelaytoo).🤖 Generated with Claude Code