Skip to content

v0.5.0 (2026-09-05)

Theme: Email channel completion + object storage + observability

v0.5.0 clears the entire v0.4.0 email design debt, promotes object storage from ADR to production code, and adds observability for the cron worker. The security domain completes login rate-limit consolidation, session device management, and a Passkey pilot.

Email Channel

  • Digest folding: a user's notifications merge into one email; same-type groups of ≥3 fold into a single "N × type" line, details capped at 5 with an overflow count.
  • Retry & dead-letter: a single user's send failure no longer aborts the whole run; retry counters accumulate per notification and after 3 attempts the notification is dead-lettered (excluded from the queue) for manual inspection.
  • Real-time delivery: security alerts, team invites, role changes, and successful payments send immediately at event time (preference-gated, with sent receipts); the cron digest acts as the retry fallback.
  • Timezone staggering: the digest only sends to users whose local time is 08:00 (hourly external cron recommended); missing/invalid timezones fall back to Asia/Shanghai.
  • Marketing channel: double opt-in (toggle → confirmation email → click to confirm), public confirm/unsubscribe routes with tokens, and a mandatory unsubscribe footer on every marketing email.

Object Storage

  • StorageDriver abstraction with two drivers: Supabase Storage by default (zero config), Aliyun OSS when all four OSS_* variables are present (SDK loaded dynamically, not bundled by default).
  • Server-relayed uploads: images up to 2MB, content-type whitelist, extensions derived from the whitelist to prevent path traversal.
  • Avatar upload (profile edit) and project cover (project settings) are wired.

Observability

  • Appark APM: lightweight first-party wrapper (no vendor SDK), off by default; enabled when both env vars are present. Checkout and cron runs are instrumented.
  • Worker run records: every digest run persists pulled/sent/failed/duration.
  • Backlog alert: Sentry report when pending notifications exceed 500.

Auth Security

  • Rate-limit consolidation: email dimension (5 failures / 15 min) plus a new IP dimension (20 / 15 min), unified in the rate-limit keyed sliding window.
  • Session devices: device list (UA/IP/last active) + per-device revocation; sessions register automatically via the auth callback and a dashboard heartbeat.
  • Passkey pilot: registration/verification loop behind the NEXT_PUBLIC_FEATURE_PASSKEY flag (default off); session issuance awaits native Supabase support.

Performance & Quality

  • Tailwind v4 native theme: @config bridge and tailwind.config.ts removed in favor of @theme inline / @custom-variant / @utility (ADR-013).
  • TanStack Query cache consolidation: single-source query keys + three cache presets across 8 call sites.
  • Coverage gates: branches 78% → 85% (measured 85.7%); unit tests 556 → 668.

Upgrade Notes

  • Run migrations 016–019 (marketing subscriptions / worker runs / session devices / passkey credentials).
  • Change the external digest cron to hourly (for timezone staggering).
  • Optional enablements: OSS_* (storage switch), NEXT_PUBLIC_APPARK_* (APM), NEXT_PUBLIC_FEATURE_PASSKEY=true (passkeys).

See CHANGELOG.md in the repo root for the complete list.

基于 MIT 协议开源