- Rewrote Drizzle schema: 20 tables with enums, relations, indexes - Generated migration with DROP TABLE records (v1 EAV removal) - Added passkey auth routes (register/login) - Added requireWorkspaceAccess helper - Added seedDefaultData for Personal workspace + welcome note - Updated SSE endpoint for v2 entities + workspace_id filtering - Created recordActivity helper (insert + pg_notify) - Updated sidebar: Graph replaces Reports, removed Analytics - Updated command palette for v2 entities - Created AGENTS.md with locked contract - Created llm-wiki scaffold (5 stubs) - Added inline AGENT INSTRUCTION comments to all 50 API route files - Fixed globals.css border-border class conflict - Updated database.ts stub for v1 compatibility
1.0 KiB
1.0 KiB
Realtime System
Architecture
API Route (write)
│
├── Drizzle INSERT/UPDATE/DELETE
├── Activity feed INSERT (via recordActivity)
└── pg.notify('project_e_events', payload) (via recordActivity)
│
▼
SSE Endpoint (/api/realtime)
│
├── LISTEN project_e_events
├── Filter by workspace_id
└── Push to EventSource
│
▼
Zustand Store (entity slices)
│
├── Receives event: { type, action, id, workspace_id }
├── Re-fetches affected entity
└── Components re-render
SSE Event Format
{
"type": "task",
"action": "created",
"id": "uuid",
"workspace_id": "uuid"
}
Connection
- Endpoint:
GET /api/realtime?workspace_id=uuid - Content-Type:
text/event-stream - Heartbeat:
:pingevery 30 seconds - Reconnection: Client-side exponential backoff
Trigger Pattern
Every write API route calls recordActivity() which handles both the activity feed insert and the pg_notify call.