Specfork

@specfork/notifications

Per-user notification inbox with read, archive and snooze, per-type channel preferences, email delivery and digests.

basemessaging Version 0.1.1 15 requirements Licence CC-BY-4.0 Specfork/notifications

Notifications

A base spec: requiring specs define notification types and who receives them; this spec stores, shows and delivers them. Designed from patterns shared by Plane, Chatwoot, Vikunja and wger; no source text or code used.

Area Prefix Covers
notifications.md NTFY Inbox, grouping, read/archive/snooze, preferences, email, digests, retention

Notifications

Status: Draft · Prefix: NTFY

Purpose

One inbox per user for everything requiring specs want to tell them, delivered in-app and by email.

Requirements

ID Requirement Verified by
NTFY-1 Notification: {id, user, type, subject {kind, id}, actor?, title (≤ 200), body? (≤ 2,000), count, created_at, updated_at, read_at?, archived_at?, snoozed_until?}. type values and their recipients come from the requiring spec. type unknown to the requiring spec → refused
NTFY-2 At most one unread notification per (user, type, subject): a new event updates it (count + 1, latest actor, updated_at) instead of adding another. two comments on one item → one notification, count 2
NTFY-3 The actor is never notified about their own action. user comments on own item → no notification
NTFY-4 Inbox: newest updated_at first; filters unread, archived, snoozed; cursor pagination, 50 per page; unread count shown. 120 unread → 3 pages, count 120
NTFY-5 Mark read or unread, mark all read, archive and unarchive; archived notifications leave the inbox but stay searchable. mark all read → unread count 0
NTFY-6 Snooze until a time (in the user's @specfork/auth:AUTH-1 time zone): hidden until then, then back on top as unread. snooze to 09:00 tomorrow → reappears 09:00 unread
NTFY-7 Preferences per (type, channel), channels in_app and email; defaults set by the requiring spec; types it marks required can't be turned off in-app. email off for type → no email, still in app
NTFY-8 Email per type: off, instant (sent within 1 minute) or daily (one digest per local day at digest_time, default 08:00, skipped when nothing is new). daily: 3 notifications → one email at 08:00
NTFY-9 Every email has a one-click unsubscribe (RFC 8058) that turns off email for that type only. unsubscribe → that type email off, others on
NTFY-10 A failed email is retried after 1, 5 and 30 minutes, then marked failed; in-app delivery never depends on email. mail server down → 3 retries, still in app
NTFY-11 Open sessions see new notifications and the unread count within 5 seconds, with no reload. notification created → badge updates ≤ 5 s
NTFY-12 Retention: read and archived notifications are deleted after 90 days, unread after 365. read 91 days ago → gone
NTFY-13 When the subject is deleted, its notifications are deleted; when a user loses access to it, they are hidden. item deleted → its notifications gone
NTFY-14 The inbox can be filtered by type and by a scope the requiring spec defines (e.g. project); unread counts are available per type and per scope. filter project A → only A's notifications
NTFY-15 Mark read for a subject: every notification of the user about that subject becomes read; requiring specs call it when the user opens the subject. open item → its notifications read

Out of scope

  • Mobile and web push, SMS, chat integrations: later channels.
  • Per-subject subscribe/unsubscribe (watching): the requiring spec decides recipients.

Decisions

  • Grouping by (user, type, subject) keeps busy items from flooding the inbox.
  • Email digests are per type so urgent types can stay instant.

From Specfork/notifications at e3b60ec, licence CC-BY-4.0.