feat(notify): Web Push plumbing end-to-end — VAPID key file, subscriptions, sender, service-worker handlers, settings enrollment (#98) #102
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab!102
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/98"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The complete standards Web Push (RFC 8292 VAPID) pipe with no trigger logic — the tracer bullet proving HTTPS, push-gateway egress, and iOS PWA enrollment before any notification source exists. No Apple/Google registration anywhere; lab authenticates to the gateways with its own generated keypair.
What's in the slice
internal/push/key.go, mirroringinternal/vault):--vapid-key-file/LAB_VAPID_KEY_FILE, default<state-dir>/vapid.key; 64-hex P-256 scalar, generated on first start via exclusivelink(2)publish (0600), refuses loose perms or malformed content, never overwrites. The vault's crash-safe write helpers moved to a new sharedinternal/fsxpackage so both key files ride one audited implementation.push_subscriptions(migration 0007 in both dialect trees; parity test green): device-level trust — endpoint UNIQUE, upsert preserves id/created_at, no user FK, survives logout.internal/push/sender.go, webpush-go v1.4.0): fire-and-forget off the caller's goroutine, TTL 24 h, urgency high; gateway 404/410 deletes the row; every other failure — including an airgapped host — logs loudly (component=push, endpoint redacted to host) and never blocks or crashes the caller. This is the seam #99/#100 inject./api/v1/push/*, requireAuth + tree-wide CSRF): public key, subscription list/create/delete, per-device send-test through the real sender; device label derived server-side from User-Agent.pushrenders title/body/tag and always shows a notification (iOS Safari revokes subscriptions of SWs that handle a push silently);notificationclickfocuses-or-opens the payload route. The/api·/agent·probes network-only rule is byte-identical.vapidKeyFileoption, CONTEXT.md glossary, ADR-0039. nixvendorHashbumped for the new dependency.Verification
--list/tsc/eslint; runs in CI/dev).-tags uibinary: first boot generatesvapid.key0600 + logs the public key, restart loads the same key, authenticated subscribe→list→send-test→delete round trip works, test-send returned 202 in 11 ms with the loud host-only error log.nix flake checkgreen (Go suite, golangci-lint, web vitest/eslint/prettier, nixos-module eval).go test ./...green exceptinternal/tmuxx, which fails identically on pristine HEAD in this sandbox (tmux cannot daemonize here) and passes inside the nix check.Closes #98
🤖 Generated with Claude Code
https://claude.ai/code/session_01QH2ooTz1YZRnYhXHBYP1oF