~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain-ios

1 collaborator
0
1

Push registers with registerPush, falling back on servers without it

Merged
Merged chadtmiller.com asked to merge into main from grain.social/grain-ios:push/register-push

What changes

The app registers its APNs token with social.grain.notification.registerPush, and withdraws it with social.grain.notification.unregisterPush. Both take the input of Bluesky's app.bsky.notification.registerPush: serviceDid (did:web:grain.social), token (the hex APNs token, as before), platform (ios) and appId (social.grain.grain).

When the server answers 404, 501, or an XRPC error named MethodNotImplemented or MethodNotFound, PushManager sends the older registerToken / unregisterToken call exactly as it is sent today ({token, platform: "apns"} and {token}). Any other failure, such as a 401 or a 400 InvalidRequest, is the answer: it is logged and swallowed as before, and the older call is not tried.

Auth is unchanged: the new call goes through the same client and auth context as the old one. The triggers are unchanged too (token arrival after sign-in and on account switch, unregister on sign-out and on switching away).

Why

The Rust server serves only registerPush / unregisterPush, shaped as Bluesky's. Production still runs the old server until cutover, and that has no registerPush (it answers 404 today), so the app has to work against both until then.

How it was checked

NetworkSideEffectTests covers:

  • the registerPush and unregisterPush request: path, POST, JSON content type, and a body of exactly the four fields;
  • falling back to registerToken and to unregisterToken on each of 404, 501, 400 MethodNotImplemented and 400 MethodNotFound, with the old body exactly as before;
  • no fallback on 401, 400 InvalidRequest or 500, for both register and unregister;
  • PushManager.isMethodMissing on its own.

Ran NetworkSideEffectTests and AppLifecycleTests locally on the iPhone 17 Pro Max simulator: 25 tests, 0 failures. swiftformat and swiftlint are clean on the touched files.

Shortcomings

  • The repo has no knotless workflow that builds or tests the app; nothing ran on the runner. The full suite was not run, only the two classes above.
  • Not tried on a device against production or the new server, so real APNs delivery through registerPush is untested.
  • appId is the constant social.grain.grain, not Bundle.main.bundleIdentifier, so a development build under another bundle id still registers as the shipping app.
  • On the void client's DPoP-nonce retry path a failure carries no body, so a MethodNotImplemented 400 seen only after a nonce retry would not fall back. 404 and 501 do in every path, and production answers 404.

🤖 Generated with Claude Code

chadtmiller.com added 1 commit
Approved

This switches APNs registration and withdrawal to social.grain.notification.registerPush and unregisterPush. It falls back to the old registerToken and unregisterToken calls only when PushManager.isMethodMissing sees a 404, a 501, or a MethodNotImplemented or MethodNotFound error. I found nothing that must change.

  • Fallback and error handling: other failures, such as a 401 or a 400 InvalidRequest, are logged and swallowed without a retry. The old payloads are unchanged.
  • Tests: they cover the request shape and each fallback and non-fallback case for both register and unregister, plus isMethodMissing on its own.
  • Known gaps: the body states the gaps itself. The constant appId and the lost body on the DPoP nonce-retry path are acceptable for now. A development build under another bundle id will register as the shipping app, so revisit that once the new server is the only one.

I only read the diff. I did not run the tests, and the PR notes that no workflow builds or tests the app.

chadtmiller.com added 1 commit
Approved

Carried forward: the change this pull makes at 9b73f8213dfba1580fa2ad4e2a94c563e1a1d60b is the one reviewed at 68116de9d8b0469c2a90b413ca524f5910da335f, so that review stands. What is new comes from its base.

chadtmiller.com added 1 commit
Approved

Carried forward: the change this pull makes at eeaa856dc2450c659e9efc1114249c5426be57d4 is the one reviewed at 9b73f8213dfba1580fa2ad4e2a94c563e1a1d60b, so that review stands. What is new comes from its base.

Merged as 1bf97ec