# PRD: WhatsApp Lead Management for go-crm --- ## Problem Statement Clients using the go-crm platform need to connect their personal WhatsApp number to capture leads. Currently, there is no way for clients to: 1. Authenticate their WhatsApp account via QR code 2. Automatically capture incoming WhatsApp messages (1:1 chats, not groups) as leads in the CRM 3. Manage these leads (CRUD operations) through the platform --- ## Solution Add a "Leads" feature to go-crm that allows clients to: 1. Connect their WhatsApp via QR code scanning from the client list 2. Automatically sync incoming WhatsApp messages (not group chats) as leads in the CRM 3. View, edit, and manage these leads through existing CRUD operations --- ## User Stories 1. As a client, I want to see a "QR Connect" button next to my client name in the client list, so that I can initiate WhatsApp connection 2. As a client, I want to scan a QR code with my WhatsApp app to authenticate, so that my WhatsApp gets connected to my CRM account 3. As a client, I want to see my connected WhatsApp phone number displayed in the client list, so that I know I'm connected 4. As a client, I want my incoming WhatsApp messages (not groups) to automatically appear as leads in the CRM, so that I can manage them 5. As a client, I want my existing WhatsApp contacts to sync as leads when I first connect, so that I have my historical data in the CRM 6. As a client, I want to view all my leads in a dedicated "/leads" page, so that I can see my potential customers 7. As a client, I want to search and filter my leads by name or phone number, so that I can find specific contacts quickly 8. As a client, I want to edit lead details (name, phone, birth date, Instagram) from the Leads page, so that I can keep information up to date 9. As a client, I want to delete a lead, so that I can remove spam or unwanted contacts 10. As a client, I want my lead's phone number to be normalized (with country code), so that data is consistent 11. As a client, I want the system to skip group messages from WhatsApp, so that I only get 1:1 chat leads 12. As a client, if I reconnect my WhatsApp, I want the session to be reused, so that I don't need to scan QR every time 13. As a client, if the WhatsApp background process crashes, I want it to automatically restart, so that I don't lose messages 14. As a client, if I receive a message from an existing lead phone number, I want the system to update the existing record (not create duplicates), so that my data stays accurate 15. As a client, I want my leads to display the phone number I connected with as my own, so that I know which WhatsApp is linked --- ## Implementation Decisions ### Architecture - Go wraps Node.js whatsapp-web.js as a subprocess (spawn-and-keep after connection) - IPC via stdout JSON lines + HTMX polling for frontend - Per-client WhatsApp session folder (`.wwebjs_auth/{client_id}/`) ### Database Schema (clients table) - `whatsapp_number TEXT` — normalized phone number (e.g., `+5521...`) - `whatsapp_connected INTEGER DEFAULT 0` — connection status (0=false, 1=true) ### Route Structure - `GET /leads` — list all leads for the logged-in client's account - `GET /leads/connect?client_id={id}` — QR code display page for connection - `GET /leads/qr?client_id={id}` — polling endpoint for QR/status (returns current QR string or status) ### Node.js Script (whatsapp-leads.js) - Spawned per-client with per-client session folder - Filters group chats (only processes 1:1 messages) - Upserts on duplicate phone number - Syncs historical chats + new incoming messages - Calls Go's existing `POST /customers` endpoint with internal secret header ### Process Lifecycle - Ephemeral spawn for QR connection flow (spawns, waits for READY, then keeps running) - Auto-restart if Node.js process exits unexpectedly ### UI Flow - Client list (`/clients`) shows "Connect" button if `whatsapp_number IS NULL`, otherwise displays connected phone number - Leads page (`/leads`) shows table of leads with edit/delete actions ### Authentication - Node.js → Go uses shared internal secret header (`X-Internal-Secret`) to bypass session auth --- ## Testing Decisions ### Test Philosophy - Tests should verify behavior through public interfaces, not implementation details - Good tests read like specifications: "client can connect WhatsApp" tells you exactly what capability exists - Tests should survive internal refactors — if renaming an internal function breaks tests, those tests were testing implementation ### Modules to Test - Database: Client WhatsApp columns (insert/query) - Handler: Leads page rendering, connection status display - Node.js script: JSON output to stdout, group message filtering ### Prior Art - No existing tests in go-crm to follow; will create new `handlers_test.go` alongside implementation --- ## Out of Scope - Sending messages back to WhatsApp from the CRM (only receiving/syncing) - WhatsApp profile pictures/avatars - Multiple WhatsApp numbers per client (one per client) - Group management features - Message notifications/push to mobile - WhatsApp Web client session restoration across Go server restarts (requires systemd/supervisor) --- ## Further Notes - Phone numbers are stored normalized (with country code) as received from WhatsApp - Historical chat sync happens on first connection (all existing 1:1 chats become leads) - New messages sync in real-time while the Node.js process runs - If WhatsApp session expires/disconnects, client must reconnect via QR