Skip to content

v2.7.0 — PWA, security patch, production hardening

Choose a tag to compare

@X4Applegate X4Applegate released this 12 Apr 23:44
· 233 commits to main since this release

Version 2.7.0 brings installable dashboards (PWA), a security patch for nodemailer, and a pass of production hardening across the whole app.

✨ Highlights

📱 Installable dashboards (PWA)

Per-group dashboards can now be installed to iOS and Android home screens with branded icons, theme colors, and standalone display mode. Just open the dashboard on your phone and use "Add to Home Screen" — the app gets the group's logo, colors, and name.

  • /dashboard/:slug/manifest.json — per-group Web App Manifest
  • /api/icon/:slug — serves the group's logo or auto-generates a branded SVG
  • /sw.js — minimal service worker to unlock installability (no caching, live data stays fresh)

🔒 Security patch

nodemailer bumped 6.10.1 → 8.0.5, closing 4 high-severity advisories:

  • SMTP command injection via envelope.size
  • CRLF injection in transport name (EHLO/HELO)
  • addressparser recursive-call DoS
  • addressparser interpretation conflict (mail to unintended recipients)

`npm audit` now reports 0 vulnerabilities.

🛡️ Production hardening

  • /healthz endpoint with DB ping, wired into Docker HEALTHCHECK
  • Security headers via helmet (HSTS, X-Frame-Options, Referrer-Policy, etc.)
  • Rate limiting on /api/login, /api/setup, /api/change-password
  • Graceful shutdown on SIGTERM/SIGINT — drains SSE streams, closes DB pool
  • Boot-time config validation — refuses to start with default SESSION_SECRET in production
  • Global error handler — no stack traces leak to the browser
  • Session cookies — auto-Secure on HTTPS, sameSite: lax for CSRF defense

🐳 Docker

  • Runs as the non-root node user now
  • npm ci --omit=dev for reproducible builds
  • package-lock.json is committed
  • HEALTHCHECK declared
  • Declares engines.node >= 18

Upgrading

```bash
git pull
docker compose up -d --build
```

No config changes required. If you're running in production, make sure SESSION_SECRET and DB_PASSWORD are both set in your docker-compose.yml — v2.7.0 will refuse to start with the default SESSION_SECRET under NODE_ENV=production.

Full changelog: CHANGELOG.md