Repository navigation
Ring linked devices (iPad) by attaching them to the push relay - #52
Merged
Merged
Conversation
A linked iPad never received relay pings, so incoming calls (and message notifications) didn't arrive while Radar was backgrounded or the iPad was locked. Signal's own APNs pushes can't reach Radar's bundle ID, leaving the relay as the only wake-up path. The relay works by the primary provisioning a phantom linked device, but the chat server only issues device-provisioning codes to the primary. On a linked device runEnsure registered its APNs token with the relay and then failed at requestDeviceProvisioningCode() on every launch (also spending the account's device-provisioning rate limit). Linked devices now take a separate path (runEnsureAttached): 1. register their APNs token with the relay (POST /devices), 2. attach that registration to the account's existing relay device (POST /attach), signed with the account's ACI identity key over "RadarPushRelayAttach-v1\n<aci>\n<device_id>\n<relay_token>\n<ts_ms>", 3. keep the relay's copy of the APNs token current. The device's own Signal credentials are never sent to the relay. The attachment is re-checked via /status (`attached`) and redone if the relay dropped it. A relay without /attach answers 404, which is logged and retried on the next launch, so app and relay can ship in either order. Primary devices are unchanged. Requires radar-labs/radar-push-relay#1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
m-radar
approved these changes
Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On iPad, calls don't ring while Radar is in the background or the iPad is locked. Message notifications don't arrive either. On iPhone, both work.
com.cakelabs, so Signal's APNs pushes can't reach Radar.RadarPushRelayis the only thing that wakes the app.runEnsureregistered its APNs token with the relay, then failed atrequestDeviceProvisioningCode()on every launch.The call stack itself is fine. RingRTC and the
Signal/Callscode are unchanged from upstream. Calls never arrived because the app was never woken.Change
One file:
Signal/Notifications/RadarPushRelay.swift.runEnsureAttached:POST /devices), as before;POST /attach, added in radar-labs/radar-push-relay#1). The relay then pings this device whenever it pings the primary;signed_messagein the relay. The relay's tests check it against signatures made with libsignal./status(attached) and redone if the relay dropped it. A relay that has forgotten the token (404) triggers re-registration./attachanswers 404. The app logs that and retries on the next launch or token update, so the app and relay can ship in either order.Blast radius (per CLAUDE.md)
ensure/setEnabled→RelayWorker→runEnsure. That's called fromAppDelegate(launch),PushRegistrationManager(APNs token received),NotificationSettingsViewController(toggle), andaskIfNeeded(registration and linking prompts). All of these are unchanged; the new branch only runs when!registrationState.isRegisteredPrimaryDevice.isEnabledand APNs-token checks, so a linked device with the relay disabled still does nothing.isAttachedkey in theRadarPushRelayKV collection, defaulting to false.tearDownclears it.Testing
Signalscheme, Debug, Xcode 27. BUILD SUCCEEDED, andRadarPushRelay.swiftcompiled with no warnings or errors.mainand are unrelated to this PR. See the note below.RadarPushRelay: attached linked device to account relay.Note:
maindoesn't build with Xcode 27Unrelated to this PR, but anyone moving to Xcode 27 will hit these:
NoUseUnstructuredThrowingTask,ImplicitStrongCapture), andProject.xcconfigturns warnings into errors. Workaround:Config/User.xcconfigfrom the sample.ConcurrentTaskQueue.run { … }/KeyedConcurrentTaskQueue.run { … }call with a non-throwing closure. Adding@_disfavoredOverloadto the throwingrun<T>(_ block: () async throws -> T)overloads in both files fixes it without changing behaviour. I applied that only locally for the compile check.xcodebuild -downloadComponent MetalToolchain.🤖 Generated with Claude Code