Each device generates its own X25519 key pair on login (tweetnacl); the
private key never leaves localStorage or reaches our server. Messages are
encrypted client-side with the recipient's public key before being sent,
so the backend and anyone intercepting traffic only ever see ciphertext.
- src/lib/e2ee.ts: key generation/registration + encrypt/decrypt (NaCl box)
- Chat thread + matches list: encrypt on send, decrypt on receive/preview,
with a graceful fallback when a message can't be decrypted on this device
(e.g. after switching browsers) and full backward compat for legacy
plaintext messages sent before this change
- Privacy settings page explains the guarantee and its one deliberate
trade-off: there is no key backup/escrow, so clearing browser data or
switching devices makes old messages permanently unreadable
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Phone+OTP auth, staged onboarding, admin-approval-gated home screen,
and the full discovery/match/chat UI (swipe deck with drag gestures,
match modal, profile detail, filters, messages/chat) wired to the
real backend, styled after a Figma dating-app UI kit.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>