QR Code Login Architecture (Pre-Rewrite Reference)
Overview
Documents the QR code-based WhatsApp linking flow as of 2026-03-16, preserved before the planned rewrite to eliminate QR codes.
Flow
User clicks "Connect" → POST /api/connect
→ Gateway creates VPN tunnel (vpnUp)
→ Gateway provisions Docker container (provisionSlice)
→ Container starts with CHROME_PROXY env var
→ Gateway calls POST /slice:PORT/api/status/initialize
→ Slice starts headless Chrome with whatsapp-web.js
→ Chrome navigates to web.whatsapp.com
→ WhatsApp shows QR code → SSE → frontend renders QR
→ User scans with phone → authenticated → ready
Key Components
Backend (per-slice container)
- WhatsAppService.ts: Chrome launch with
--proxy-server, QR event handling - statusController.ts:
/api/status/initializeand/api/status/state - WebSocketService.ts:
wa:qr,wa:ready,wa:disconnectedevents
Frontend
- SaasLoginPage.tsx: QR display with health-driven expiry
- QRCode.tsx: Pure pass-through renderer (no timers)
- ConnectionContext.tsx: SSE-driven connection state
Gateway
- connect.ts: Provisions slice with VPN
- sse.ts: Proxies SSE events from slice to frontend
VPN Two-Phase System
- Phase 1 (VPN): New user gets per-slice VPN tunnel. Chrome connects through SOCKS5 proxy for QR scanning.
- Phase 2 (IPv6): After linking + data collection, container recreated without proxy on native IPv6.
Session Persistence
- Chrome session stored in
/data/slices/{N}/session/(Docker volume mount) - Survives container restarts — no re-scan needed unless explicitly wiped