| 21-chat-foundation |
03 |
api |
| express |
| drizzle-orm |
| postgres |
| rest-api |
| chat |
| cursor-pagination |
| soft-delete |
|
| phase |
provides |
| 21-chat-foundation/21-01 |
chat_conversations and chat_messages Drizzle schema tables |
|
|
| chatService factory with 7 CRUD methods (createConversation, listConversations, getConversation, updateConversation, softDeleteConversation, listMessages, addMessage) |
| chatRoutes factory with 7 REST endpoints mounted on Express app |
| Chat schema validators exported from @paperclipai/shared |
|
| 21-04 (chat panel UI needs these REST endpoints) |
| 21-05 (conversation list sidebar uses listConversations pagination) |
| 22+ (agent integration adds messages via addMessage) |
|
| added |
patterns |
|
|
| chatService(db) factory pattern matching documentService, activityService conventions |
| cursor-based pagination using limit+1 trick with hasMore boolean |
| soft-delete via deletedAt IS NULL filter in WHERE clause |
| auto-title idempotency: WHERE title IS NULL guard on UPDATE |
|
|
| created |
modified |
| server/src/services/chat.ts |
| server/src/routes/chat.ts |
| server/src/__tests__/chat-service.test.ts (replaced stubs) |
| server/src/__tests__/chat-routes.test.ts (replaced stubs) |
|
| server/src/app.ts |
| packages/shared/src/index.ts |
|
|
| Pitfall 3 (updatedAt bump): addMessage always updates chatConversations.updatedAt after inserting — ensures conversation list sort order stays correct |
| Pitfall 5 (auto-title idempotency): WHERE title IS NULL guard makes auto-title set safe to call multiple times |
| Missing export fix: createConversationSchema/updateConversationSchema/createMessageSchema were in validators/chat.ts but not re-exported from shared/src/index.ts |
|
| Route factory pattern: function chatRoutes(db: Db): Router |
| Service factory pattern: function chatService(db: Db) returning methods object |
| Cursor pagination: fetch limit+1, slice to limit, set hasMore=true if extra row found |
|
| CHAT-04 |
| CHAT-05 |
| CHAT-06 |
| HIST-05 |
|
6min |
2026-04-01 |