feat: real-time alerts via WebSocket push notifications

- Add ws WebSocket server (port 3001) with JWT auth and user-socket mapping
- Add WebSocket client with exponential backoff reconnection and heartbeat
- Add useRealtimeAlerts hook with toast notifications and unread badge
- Add alert.publisher service (WS → push → email fallback)
- Integrate publisher into DarkWatch, VoicePrint, HomeTitle, SpamShield, RemoveBrokers
- Update Navbar with connection status indicator and unread count
- Add comprehensive tests (14 passing) for server, client, and publisher
This commit is contained in:
2026-05-25 17:58:47 -04:00
parent 3a8e329f02
commit c02457c66a
16 changed files with 1197 additions and 26 deletions

View File

@@ -14,6 +14,7 @@ import {
type DetectedChange,
type SnapshotData,
} from "./hometitle/change.detector";
import { publishAlert } from "~/server/services/alert.publisher";
import {
geocodeAddress,
fetchCountyRecords,
@@ -433,7 +434,7 @@ async function generateAlert(
critical: "CRITICAL",
};
await db
const [normalized] = await db
.insert(normalizedAlerts)
.values({
source: "HOME_TITLE",
@@ -454,5 +455,15 @@ async function generateAlert(
})
.returning();
publishAlert(sub.userId, {
id: alert.id,
title,
message,
severity: change.severity,
source: "HOME_TITLE",
category: "HOME_TITLE",
createdAt: alert.createdAt,
}).catch((err) => console.error("[hometitle] Failed to publish alert:", err));
return alert;
}