Notifications & Events
Purpose
The Notifications module handles fan-out, retries, and external delivery (webhooks and email) with failure semantics that are fully isolated from the control plane. A delivery failure — webhook timeout, SMTP bounce, dead endpoint — must never propagate back to the file commit path or any synchronous user operation.
Data owned
| Table | Purpose |
|---|---|
subscriptions |
Tenant webhook endpoint registrations, event filter config |
webhook_endpoints |
Endpoint URL, HMAC signing secret, status |
notifications |
Per-user in-app notification records |
delivery_state |
Per-event × per-endpoint delivery attempts, next retry time, status |
Internal API
Notify.* gRPC methods:
| Method | Description |
|---|---|
Notify.Subscribe |
Register a webhook endpoint for one or more event types |
Notify.Unsubscribe |
Remove a subscription |
Notify.ListSubscriptions |
List a tenant’s active subscriptions |
Notify.GetDeliveryStatus |
Query delivery status for a given event + endpoint |
Event consumption and fan-out
The notifier worker subscribes to all domain event subjects on NATS JetStream. For each consumed event it fans out to every matching subscription for the originating tenant:
flowchart LR
J{{"NATS JetStream<br/>(all domain subjects)"}}
NT["Notifier worker"]
WH[("Tenant webhook endpoints")]
EM[("SMTP / email")]
IN[("In-app notifications DB")]
J -->|at-least-once| NT
NT -->|signed HTTP POST| WH
NT -->|SMTP| EM
NT -->|insert| IN
Delivery guarantees
- At-least-once delivery with exponential backoff.
- Retry schedule: immediate → 1 min → 5 min → 30 min → 2 h → 24 h (configurable).
- Dead-letter queue (DLQ): after the final retry, the event is moved to the DLQ. Operators can inspect and replay from the DLQ.
- Poison message detection: an event that repeatedly causes the worker to crash (rather than a delivery failure) is quarantined to the DLQ after a configurable crash threshold.
Webhook security
- Signed payloads: every webhook POST includes an
X-BitVault-Signatureheader containing an HMAC-SHA256 signature over the raw payload body using the endpoint’s registered secret. - Tenants verify the signature on receipt to confirm authenticity and detect tampering.
- Signing secrets are stored encrypted at rest; never returned via the API after initial registration.
Email notifications
SMTP is used for user-facing notifications:
- Invitation emails (new user added to a tenant).
- Share alert emails (a file was shared with the user).
- Security alerts (new device registered, password changed).
Email delivery uses the same at-least-once retry model as webhooks.
:::note Failure isolation: Notification delivery failures must never propagate back to the control plane. The async plane is isolated from the control plane by design — the event bus and the notifier worker are the boundary. A broken webhook endpoint or a full SMTP queue is a notifier concern, not a file-commit concern. :::