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 P-256 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 generated automatically the first time the public key is requested. The server signs a VAPID JWT (ES256, 12-hour expiry, subject mailto:admin@<id_tag>) per push request.
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
notify.push is the master switch. Per-event toggles let users choose which notifications they receive:
| Setting | Default | Event |
|---|---|---|
notify.push.message |
true | Direct messages (MSG) |
notify.push.connection |
true | Connection requests (CONN) |
notify.push.file_share |
true | File shares (FSHR) |
notify.push.comment |
true | Comments on your posts (CMNT) |
notify.push.mention |
true | Mentions in posts |
notify.push.follow |
false | New followers (FLLW) |
notify.push.reaction |
false | Reactions to your posts (REACT) |
notify.push.post |
false | Posts from people you follow (POST) |
An equivalent notify.email.* set controls email notifications (master switch notify.email is off by default). Settings are tenant-scoped and checked before sending.
Encryption
Push payloads are encrypted with the browser subscription’s P-256 public key (p256dh) and auth secret using the ece (Encrypted Content-Encoding, aes128gcm) scheme. The push service relays the ciphertext but cannot read it. The encrypted body already embeds the salt and server public key in its header, and is POSTed with Content-Encoding: aes128gcm and TTL: 86400.
Payload Structure
The encrypted payload is the NotificationPayload serialized as JSON:
| Field | Description |
|---|---|
title |
Notification title |
body |
Notification body text |
path |
URL path to open when clicked (optional) |
image |
Image URL (optional) |
tag |
Tag for grouping notifications (optional) |
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 404/410, or the user manually unsubscribes. Invalid subscriptions are removed automatically.
Error Handling
The push result is classified by the push service’s HTTP status:
| Push Service Response | Result | Action |
|---|---|---|
| 2xx | Success | Counted as delivered |
| 404, 410 Gone | Subscription gone | Delete subscription |
| Other 4xx (incl. 429) | Permanent error | Log, don’t retry |
| 5xx / network error | Temporary error | Log, can retry |
See Also
- Push Notifications API - REST API endpoints
- Settings API - Notification preferences
- WebSocket API - Real-time notifications