source: Klonkt/package.json@ a7bcf66

main
Last change on this file since a7bcf66 was ad10715, checked in by Robin <roboburr@…>, 7 weeks ago

Feature: web push slice 1, VAPID keys + subscription store

The foundation for background notifications (docs/webpush-design.md).

  • Dependency (approved): web-push for RFC 8292 VAPID JWTs and RFC 8291 payload encryption. Lazy import so a canary that autofollows before npm ci never crashes on boot (same pattern as @simplewebauthn/server).
  • VAPID keys: env (VAPID_PUBLIC_KEY/VAPID_PRIVATE_KEY/VAPID_SUBJECT) wins, else auto-generated once into storage/.vapid (0600), never regenerated while the file exists: new keys would invalidate every subscription. Subject: PUBLIC_BASE_URL, else mailto from SMTP_FROM.
  • push_subscriptions table: one row per device, client keys for encrypted payloads, per-type alert preferences (follow/reply on, like/boost off, dm on by default), self-pruning on 404/410 in the send path.
  • notifyUser/notifySite: honour alert prefs, cap title/body length, fire-and-forget at call sites (slice 3 wires the triggers).

Changed files:
package.json, package-lock.json

  • web-push@3.6.7

src/config/database.js

  • push_subscriptions table (additive)

src/routes/posts.js

  • RESERVED_SLUGS: add 'push' (and the missing 'paid') so a post can't shadow the mounted routes

New file:
src/services/PushService.js

  • VAPID key resolve/persist, subscription CRUD, encrypted send with pruning, notifyUser/notifySite

test/push.test.js

  • key autogen (0600, persists, served=stored), subscription CRUD, upsert-not-duplicate, refuse incomplete payloads

-robo
Co-Authored-By: Claude Opus 4.8 <noreply@…>

  • Property mode set to 100644
File size: 1.2 KB
RevLine 
[7bc636b]1{
[7007d4c]2 "name": "klonkt",
[d49b60b]3 "version": "1.6.0-dev",
[5a4c0b0]4 "description": "Klonkt — self-hosted multi-site music & blog platform (solo, hub or circles). Node + SQLite + htmx.",
5 "license": "AGPL-3.0-or-later",
[7bc636b]6 "type": "module",
7 "main": "src/server.js",
8 "scripts": {
9 "start": "node src/server.js",
10 "dev": "node --watch src/server.js",
[8398935]11 "test": "node --test",
[9e27d64]12 "migrate": "node src/db/migrate.js",
[3e86f1c]13 "reset-admin": "node scripts/reset-admin.mjs",
14 "backfill:durations": "node scripts/backfill-durations.mjs"
[7bc636b]15 },
16 "dependencies": {
[69815b2]17 "@resvg/resvg-js": "^2.6.2",
[9e9e6f9]18 "@simplewebauthn/browser": "^13.3.0",
19 "@simplewebauthn/server": "^13.3.2",
[7bc636b]20 "bcryptjs": "^2.4.3",
21 "better-sqlite3": "^11.3.0",
22 "body-parser": "^1.20.2",
23 "dotenv": "^16.3.1",
24 "ejs": "^3.1.9",
25 "express": "^4.18.2",
26 "express-rate-limit": "^7.4.1",
27 "express-session": "^1.17.3",
28 "ffmpeg-static": "^5.2.0",
29 "fluent-ffmpeg": "^2.1.3",
30 "helmet": "^7.1.0",
31 "htmx.org": "1.9.12",
32 "marked": "^11.1.1",
33 "multer": "^1.4.5-lts.1",
[ecbfa41]34 "node-webpmux": "^3.2.1",
[9e27d64]35 "nodemailer": "^6.9.15",
[7bc636b]36 "sanitize-html": "^2.17.3",
[ad10715]37 "uuid": "^9.0.1",
38 "web-push": "^3.6.7"
[7bc636b]39 },
40 "engines": {
41 "node": ">=20"
42 }
43}
Note: See TracBrowser for help on using the repository browser.