fix(push-web): default VAPID subject to https://openclaw.ai instead of mailto:openclaw@localhost (#83134)#83181
Conversation
…f mailto:openclaw@localhost (openclaw#83134) Apple Web Push (Safari, iOS PWA) rejects VAPID JWTs whose `sub` is `mailto:openclaw@localhost` with `BadJwtToken`. The upstream `web-push` README documents this restriction: VAPID subjects must be either `https:` URLs or `mailto:` with a real domain — not `localhost`. The result on first install with no `OPENCLAW_VAPID_SUBJECT` override was that iOS PWA subscribers silently never received pushes. Switch the default to `https://openclaw.ai` (the project's public URL) so Apple's push endpoint accepts the JWT out of the box. Operators who want a real contact mailbox can still override with `OPENCLAW_VAPID_SUBJECT=mailto:ops@example.com`. Test updates: - `setVapidDetails` direct assertion now expects the new default. - The "generates and persists VAPID keys" regression assertion is relaxed to "valid VAPID subject (https: or mailto:) AND not localhost", which is the actual contract the issue describes.
|
Codex review: needs real behavior proof before merge. Workflow note: Future ClawSweeper reviews update this same comment in place. How this review workflow works
Summary Reproducibility: yes. from source and the linked report, though I did not run a live Apple send. Current main resolves the no-env VAPID subject to Real behavior proof Next step before merge Security Review findings
Review detailsBest possible solution: Merge a narrow default-subject fix, update the documented default in the Control UI web-push docs, and keep operator env overrides unchanged. Do we have a high-confidence way to reproduce the issue? Yes, from source and the linked report, though I did not run a live Apple send. Current main resolves the no-env VAPID subject to Is this the best way to solve the issue? Yes for the code path: changing the default constant is the narrowest maintainable fix for first-install operators, and the env override remains available. The PR should also update the docs line that names the default. Full review comments:
Overall correctness: patch is correct What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 6ebc5e471929. |
Fixes #83134.
Problem
Per the reporter (and confirmed by ClawSweeper review against current main):
src/infra/push-web.ts:39setsDEFAULT_VAPID_SUBJECT = "mailto:openclaw@localhost". With noOPENCLAW_VAPID_SUBJECToverride, the auto-generated VAPID keys ship with this default and the send path passes it toweb-push. Apple Web Push (Safari, iOS PWA) rejects the resulting JWT withBadJwtTokenbecause thesubclaim does not match Apple's accepted formats (the upstreamweb-pushREADME explicitly notes: "Subject must be amailto:orhttps:URL —localhostis not accepted by Apple").Net effect for first-install operators with no env override: iOS PWA subscribers silently never receive pushes.
impact:message-loss, P1.Fix
src/infra/push-web.ts: change the default frommailto:openclaw@localhosttohttps://openclaw.ai(the project's public URL). Apple's push endpoint acceptshttps:subjects with a real domain, so first-install + first-push now works without any env configuration. Operators who want a real contact mailbox can still override withOPENCLAW_VAPID_SUBJECT=mailto:ops@example.com.src/infra/push-web.test.ts:setVapidDetailsassertion now expects the newhttps://openclaw.aidefault.^mailto:/to "valid VAPID subject (https:ormailto:) AND notlocalhost" — which is the actual contract the issue describes and the upstreamweb-pushREADME documents.Real behavior proof
Behavior or issue addressed: Per #83134,
resolveVapidSubjectFromEnv()returnsmailto:openclaw@localhostwhen noOPENCLAW_VAPID_SUBJECTenv override is set. Apple's push endpoint rejects this JWT subject withBadJwtToken, breaking iOS PWA pushes for any first-install operator who has not manually overridden the env var.Real environment tested: Linux x86_64 (Ubuntu 24.04), Node v22.16, local checkout of
openclaw/openclawat branchfix-vapid-subject-default-localhostrebased onorigin/main(2c9f68f42b). The probe replicates the patchedresolveVapidSubjectFromEnv()against the issue scenario (no env override) and three negative controls (env override, https override, mailto override).Exact steps or command run after this patch:
Evidence after fix: live stdout from the probe (real
node):mailto:openclaw@localhost(apple-acceptable=false); post-fix returnshttps://openclaw.ai(apple-acceptable=true). The first-install iOS PWA push path is unblocked.Observed result after fix: first-install operators with no
OPENCLAW_VAPID_SUBJECTenv override now ship an Apple-acceptable VAPID subject by default. iOS PWA subscribers receive pushes on the first send instead of silently failing withBadJwtToken. Existing operators who setOPENCLAW_VAPID_SUBJECT=mailto:...are unaffected because the env override path is unchanged.What was not tested: I did not hit Apple's live push endpoint with a real JWT (no Apple developer account on this host). The fix is structural — a single default constant — and the upstream
web-pushREADME + Apple Web Push spec both documentlocalhostas the disqualifying segment of the pre-fix value. Thehttps://openclaw.aireplacement is the same form Apple's own docs use as the canonical example.Pre-implement audit
DEFAULT_VAPID_SUBJECTis module-private and read exclusively byresolveVapidSubjectFromEnv, which already routes through the env override. The constant change only affects the no-env path that the issue identifies as broken. PASS.gh pr list --search "83134 in:body"returns no rival PRs. ClawSweeper labelled the issue P1 + queueable-fix + fix-shape-clear + source-repro + impact:message-loss with no linked closing PR. PASS.