Stale push subscription can block verification of a new one

Issue Description

hi, we hit this on stalwart v0.16.13 with a jmap android client (sterna mail) using unifiedpush through ntfy. push worked after the first setup, then the user deleted and recreated the subscription and the new one stayed stuck on connecting to WebPush. ntfy itself was working fine, another app on the same phone was still receiving pushes.

Expected Behavior

when a new PushSubscription is created, stalwart should send its verification request even if the account still has an older unverified subscription.

Actual Behavior

the push manager goes through subscriptions oldest first, but last_verify is shared for the whole account. an old invalid registration takes the verification slot, then the newer valid registration is skipped as too many requests and never gets its verification. in our case the old key was malformed, so it failed before any HTTP post. after removing the stale registrations, the newest subscription verified right away.

Reproduction Steps

  1. create a PushSubscription and leave it unverified (an invalid p256dh key makes the problem easy to see)
  2. keep that old subscription on the account
  3. create a second valid PushSubscription for the same account
  4. the old subscription is selected first and updates the account verification timer
  5. the new subscription is skipped because of pushVerifyTimeout and never receives the verification request

Stalwart Version

v0.16.x

Installation Method

Docker

Database Backend

PostgreSQL

Blob Storage

S3-compatible

Search Engine

Internal

Directory Backend

Internal

Additional Context

looks like the issue is in crates/services/src/state_manager/push.rs. the rate limit is per account and subscriptions are processed oldest first.

i made a small tested patch that keeps the account rate limit but gives the slot to the newest unverified subscription:

full jmap test suite passes with a regression test, including 309/309 compliance checks. feel free to take the fix directly, mostly just reporting this so it can be fixed upstream.

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

This isn’t covered in the current docs. A community member or staff member will follow up.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Fixed in v0.16.14 (not yet released).