Add the Web Push sender for the push channel (Feature 19)
CI / ci (push) Successful in 5m23s
CI / ci (pull_request) Successful in 5m25s

push.Sender implements notify.Sender for the "push" channel with
webpush-go and the VAPID key pair: it sends {title, body, url, tag} to
every stored subscription with a TTL of 12 hours, one request each.
Per subscription, an accepted notification records last_success_at, any
failure increments failure_count, and a 404 or 410 deletes the
subscription. Send succeeds when one device accepted it or when there
are no subscriptions (logged as nothing to send); otherwise it returns
an error so the outbox retries. Errors and logs name subscriptions by
id; a transport *url.Error is unwrapped so the endpoint is never quoted.

A mailto: VAPID subject is passed to webpush-go as its bare address,
since webpush-go prefixes mailto: itself.

The server registers the sender with the notify service.

Maestro task 32a1a4ad-9221-46de-8468-3ffce19b108c.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-09 13:13:15 -04:00
co-authored by Claude Opus 5.5
parent 104396da55
commit 8fe68659bd
8 changed files with 910 additions and 0 deletions
+24
View File
@@ -18,3 +18,27 @@ RETURNING *;
-- name: DeletePushSubscription :execrows
DELETE FROM push_subscriptions
WHERE endpoint = ?;
-- name: ListPushSubscriptions :many
-- Every stored subscription with its keys, for the push sender, oldest
-- first.
SELECT id, endpoint, p256dh, auth
FROM push_subscriptions
ORDER BY created_at, id;
-- name: RecordPushSuccess :exec
-- Records that the push service accepted a notification for a subscription.
UPDATE push_subscriptions
SET last_success_at = ?
WHERE id = ?;
-- name: RecordPushFailure :exec
-- Counts a delivery to a subscription that the push service did not accept.
UPDATE push_subscriptions
SET failure_count = failure_count + 1
WHERE id = ?;
-- name: DeletePushSubscriptionByID :exec
-- Removes a subscription the push service reports gone (404 or 410).
DELETE FROM push_subscriptions
WHERE id = ?;