Not entirely sure what changed between iOS 14 & 15, but initializing the push registry with a custom queue (non-main) seems to fix the problem:
PKPushRegistry(queue: self.voipQueue)
Really confusing that the public-facing PushKit API hasn't changed between these releases, but something under-the-hood was tweaked enough to cause these issues. That being said, there is a small note in the PushKit docs that lead me to this answer: "It is recommended that you specify a serial queue for this parameter". Maybe this point should be emphasized more 😆