notify: only "the app is gone" deletes a device row
reported from the field on the first real push: it failed with BadDeviceToken and the server deleted the registration. the build was production-signed and the row said sandbox — a configuration mismatch, with the device and the app both perfectly fine. pruning there destroys the evidence. the phone re-registers on next launch, the row comes back looking healthy, and the next send fails identically; you can lose a day to that loop without ever seeing what is actually wrong. so the one set becomes three. Unregistered/UNREGISTERED/NOT_FOUND prune — apple and google are saying the app is uninstalled. BadDeviceToken, DeviceTokenNotForTopic, TopicDisallowed, INVALID_ARGUMENT and SENDER_ID_MISMATCH are OURS: the row is kept and the log says what to check. everything else is transient and still counts toward three strikes. INVALID_ARGUMENT was the sharpest one. it is how fcm reports a malformed MESSAGE — including a non-string in `data`, which is the mistake this codebase is most likely to make and already has a test for. deleting on it meant one bug in the payload builder would wipe every android device from the registry on a single send, presenting as "android push stopped working" with nothing left to explain why. misconfigured is also not counted as a strike. not deleting is not enough on its own — a persistent mismatch would reach three failures and delete the row anyway, which is the same bug with a slower fuse. the apns log now names the mismatch rather than the reason code, since the code alone sends people to look at the device: it prints the row's environment and topic and says to check the SHIPPED artefact rather than the intermediate build, which is exactly where this one hid.
This commit is contained in:
@@ -138,6 +138,10 @@ export type SidecarEvent =
|
||||
// and `seq` is its cursor id there; officer relays it verbatim. No `seq` means it is not durable —
|
||||
// an `assistant:delta` (superseded by the text that follows) or a message whose write failed.
|
||||
| { type: 'claude:message'; sessionKey: string; msg: TurnMessage; seq?: number }
|
||||
// A lightweight, non-durable ping for notification delivery — deliberately NOT part of
|
||||
// chat_session_events/TurnMessage. Officer decides whether to actually notify (preference lookup +
|
||||
// fan-out to the browser); this only says "something notify-worthy just happened for this session."
|
||||
| { type: 'claude:notify'; sessionKey: string; userId: number; kind: 'turn-ended' | 'input-needed' }
|
||||
| { type: 'claude:result'; id: string; result: ClaudeCodeResult }
|
||||
| { type: 'claude:error'; id: string; error: string }
|
||||
| { type: 'claude:killed'; id: string }
|
||||
|
||||
Reference in New Issue
Block a user