docs(19.1-04): record webpush-go v1.4.0 for Herald before import
Pin github.com/SherClockHolmes/webpush-go v1.4.0 (MIT, jwt/v5 share, Options.HTTPClient = *fetchguard.Client Do). The in-tree flare module is the rejected alternative (push.* keys, websockets:generate-vapid-keys). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
30
.planning/notes/2026-10-18-webpush-go.md
Normal file
30
.planning/notes/2026-10-18-webpush-go.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Decision: webpush-go for Herald Web Push
|
||||
|
||||
**Date:** 2026-10-18
|
||||
**Status:** Accepted
|
||||
**Context:** Phase 19.1 plan 04 (`sm-herald-plugin`), D-09 / D-10 / D-12, 19.1-RESEARCH.md Pitfall 7 and Pitfall 8
|
||||
|
||||
## Decision
|
||||
|
||||
`sm-herald-plugin` depends on `github.com/SherClockHolmes/webpush-go` at **v1.4.0** (2025-01-02, MIT, Go 1.13) for VAPID (RFC 8292) and aes128gcm (RFC 8291) Web Push. Confirmed this session: `go list -m -versions github.com/SherClockHolmes/webpush-go` lists v1.4.0 as current.
|
||||
|
||||
- The frozen PHP plugin (`golem15/herald` @ a749f83) sends through Minishlink WebPush. The Go port needs the same record encryption, VAPID JWT, TTL and urgency — not a hand-rolled AES-GCM / ES256 stack (HKDF, subscription-key decode, RFC 8291 padding).
|
||||
- The library is MIT, maintained, and already shares `github.com/golang-jwt/jwt/v5` with the framework (`go.mod` pins jwt/v5 v5.3.1). Transitive: jwt/v5 and `golang.org/x/crypto`.
|
||||
- `Options.HTTPClient` is the `Do(*http.Request) (*http.Response, error)` interface. `fetchguard.Client.Do` matches it (`modules/fetchguard/client.go`), so `*fetchguard.Client` is passed as `Options.HTTPClient` directly. Pitfall 8: no adapter type, no `http.Client{Transport: …}` wrapper.
|
||||
- Send uses `fetchguard.NewClient` with `PublicOnlyMode` (HTTPS only; private and reserved IPs refused at dial time). Subscribe validates the same policy. There is no `EndpointGuard` type.
|
||||
- PHP defaults carry over: TTL **2419200** (4 weeks) and urgency **normal**, both overridable per send. The worker prunes rows on HTTP **404** and **410**.
|
||||
- VAPID keys are config keys `golem15.herald.vapid.{subject,public_key,private_key}` (PHP env names `VAPID_SUBJECT` / `VAPID_PUBLIC_KEY` / `VAPID_PRIVATE_KEY`). This note does not generate keys.
|
||||
|
||||
The in-tree Web Push module (`modules/flare`) is **not** used as the sender. It already implements RFC 8291/8292, but its config keys are `push.*`, its command is `websockets:generate-vapid-keys`, and it takes `*http.Client` rather than the `HTTPClient` Do interface. D-09 locks webpush-go so Herald keeps PHP's `golem15.herald.vapid.*` keys and `herald:vapid-generate` command name.
|
||||
|
||||
## Related dependencies
|
||||
|
||||
- `fetchguard` (in-tree) is the SSRF boundary: PublicOnly at subscribe and send. Tests inject `fetchguard.WithTransport` — no extra Doer type.
|
||||
- `github.com/golang-jwt/jwt/v5` is already a framework dependency; webpush-go's VAPID JWT uses the same module. Herald does not add a second JWT library.
|
||||
- `modules/flare` stays the framework Web Push package for other callers. Herald never imports it.
|
||||
|
||||
## Consequences
|
||||
|
||||
- `sm-herald-plugin/go.mod` requires `github.com/SherClockHolmes/webpush-go v1.4.0` only **after** this note exists. The importer is the plugin sender (`classes/sender.go`); `Options.HTTPClient` is the PublicOnly `*fetchguard.Client`.
|
||||
- `summer herald:vapid-generate` calls `webpush.GenerateVAPIDKeys` and prints `VAPID_PUBLIC_KEY=` / `VAPID_PRIVATE_KEY=` lines. The private key is never written to slog, payloads, or README examples.
|
||||
- Swapping the library later is a local sender change (D-09 reversibility). A later bump still needs a note confirming `HTTPClient` stays the Do interface so fetchguard continues to pass through without an adapter.
|
||||
Reference in New Issue
Block a user