Push Notifications

Overview

Cloudillo implements Web Push notifications using the VAPID (Voluntary Application Server Identification) protocol. Push notifications are sent when users receive actions while offline or not connected via WebSocket.

Web Push Standards

The implementation follows these RFCs:

RFC Title Purpose
RFC 8292 VAPID for Web Push Server identification
RFC 8188 Encrypted Content-Encoding for HTTP Payload encryption
RFC 8291 Message Encryption for Web Push End-to-end encryption

VAPID Keys

Each tenant has a VAPID key pair for authenticating with push services. The private key is stored in the database; the public key is shared with clients. Keys are automatically generated on first request if they don’t exist.

Subscription Flow

sequenceDiagram
    participant C as Client
    participant SW as Service Worker
    participant S as Cloudillo Server
    participant PS as Push Service

    C->>S: GET /api/auth/vapid
    S-->>C: {vapidPublicKey: "BM5..."}

    C->>SW: pushManager.subscribe({userVisibleOnly: true, applicationServerKey})
    SW->>PS: Subscribe request
    PS-->>SW: PushSubscription
    SW-->>C: PushSubscription

    C->>S: POST /api/notifications/subscription {subscription}
    S-->>C: {id: 12345}

Push Delivery

When an action is received for an offline user:

sequenceDiagram
    participant A as Action Sender
    participant S as Cloudillo Server
    participant PS as Push Service
    participant B as User's Browser

    A->>S: POST /api/inbox {action}
    S->>S: Process action
    S->>S: Check if recipient is online

    alt User is online (WebSocket connected)
        S->>B: WebSocket message
    else User is offline
        S->>S: Load push subscriptions
        S->>S: Encrypt payload with user's public key
        S->>PS: POST {encrypted payload}
        PS->>B: Push notification
        B->>B: Display notification
    end

Notification Types

Users can configure which notification types they receive:

Setting Default Description
notify.push.message true New direct messages
notify.push.mention true Mentioned in content
notify.push.reaction false Reactions to your content
notify.push.connection true Connection requests
notify.push.follow true New followers

Settings are stored per-user and checked before sending notifications.

Encryption

Push notification payloads are encrypted end-to-end using the client’s P-256 key pair and a shared secret. The push service cannot read the encrypted data.

Parameter Description
p256dh Client’s P-256 public key
auth 16-byte authentication secret
content-encoding aes128gcm

Payload Structure

{
  "type": "action",
  "actionType": "MSG",
  "issuer": "alice@example.com",
  "preview": "New message from Alice",
  "actionId": "a1~xyz789..."
}
Field Description
type Notification type (action, system)
actionType Action token type (MSG, CONN, FLLW)
issuer Action issuer identity
preview Short preview text
actionId Action ID for deep linking

Subscription Management

Users can have multiple push subscriptions (one per device/browser). Each subscription has a unique ID, and all active subscriptions receive notifications.

Push subscriptions can expire when the browser reports expiration, the push service responds with HTTP 410 Gone, or the user manually unsubscribes. Expired subscriptions are removed automatically.

Error Handling

Push Service Response Action
201 Created Success
400 Bad Request Log error, don’t retry
410 Gone Remove subscription
429 Too Many Requests Retry with backoff
5xx Server Error Retry with backoff

See Also