Linear: https://linear.app/engineereddev/issue/ENG-255
What's in this PR:
webpush/sender.ts: subscribes to the event buspushevent. For everywebdevice with a subscription, except the source, and only the target when there is one, it enqueues a send. Payload{ t: "push", push }when the UTF-8 JSON is ≤ 3,000 bytes, else{ t: "ref", id }. TTL 86,400 s, urgencyhigh.- Queue: 1,000 waiting entries (drop oldest + warn), 4 workers, 10 s timeout per send; never awaited by the request path. Pushes from the 30 s reconcile notify once (10 min dedupe by push id).
- 404/410 clears the device's
webPush(persisted through the registry); other errors warn without endpoint URLs or keys. - The VAPID keypair still comes from
webpush/vapid.ts(ENG-250); the subject is read from config at send time. DeviceRegistry.getWebPush(): registry DTOs omit subscriptions, so the sender reads them through this accessor.
Verify (lead, rebased on 3594894):
pnpm install --frozen-lockfile→ exit 0mise run check:server→ exit 0 (Tests 229 passed (229))mise run e2e:server→ exit 0 (5 files, 15 tests; includes a sender e2e)- No
pneumo-e2e-*containers left.
Deviations:
- A VAPID subject that isn't
https:/mailto:(e.g. the http devPUBLIC_URL) disables delivery with one sanitized warning, instead of failing boot or push creation..env.examplenow showsVAPID_SUBJECT=mailto:owner@example.test(commented, fake). devices/registry.tsgainsgetWebPush()(outside the issue's Touches).
🤖 Generated with Claude Code