initial
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# chat-app
|
||||
|
||||
Private, end-to-end encrypted chat app for a small circle. Self-hosted Supabase backend, clients on iOS, Android, macOS, Windows, and Linux.
|
||||
|
||||
Server is zero-knowledge: it only stores ciphertexts and metadata needed to route them.
|
||||
|
||||
## Milestone Roadmap
|
||||
|
||||
1. **Milestone 1 — Text Chat** (current): auth, identity keys, 1:1 encrypted messaging, local history, push.
|
||||
2. **Milestone 2 — Voice Calls**: libsodium-secured WebRTC signaling via Supabase Realtime.
|
||||
3. **Milestone 3 — Video Calls**: same stack, add video tracks + bandwidth handling.
|
||||
4. **Milestone 4 — Desktop Polish**: feature parity with mobile, tray, notifications.
|
||||
5. **Milestone 5 — Groups & Channels**: Discord-like group channels with shared ratchet keys.
|
||||
|
||||
## Repository Layout
|
||||
|
||||
```
|
||||
apps/
|
||||
mobile/ Expo + React Native (iOS / Android)
|
||||
desktop/ Tauri v2 + React + Vite + Tailwind (macOS / Windows / Linux)
|
||||
packages/
|
||||
shared/ Business logic: Supabase client, libsodium crypto, auth, chat
|
||||
db-types/ Generated Supabase database types
|
||||
ui-web/ React web components shared by desktop (not by React Native)
|
||||
infra/
|
||||
supabase/ Self-hosting docs, client env, SQL migrations
|
||||
.github/workflows/ CI + build placeholders
|
||||
```
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Mobile**: Expo SDK 52, Expo Router, expo-secure-store, expo-sqlite, expo-notifications, react-native-libsodium.
|
||||
- **Desktop**: Tauri v2, React 18, Vite, Tailwind, tauri-plugin-stronghold, tauri-plugin-sql, tauri-plugin-notification, Zustand.
|
||||
- **Backend**: Supabase self-hosted (Postgres + GoTrue + PostgREST + Realtime + Storage + Edge Functions) on Hetzner, Caddy reverse proxy.
|
||||
- **Crypto**: X25519 identity keys, XChaCha20-Poly1305 envelopes (libsodium / NaCl).
|
||||
- **Auth**: email magic-link, invite-only.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node **22+** (see `.nvmrc`)
|
||||
- pnpm **9+**
|
||||
- Rust + Cargo (Tauri): https://rustup.rs
|
||||
- Docker + Docker Compose (for running Supabase locally or on the VPS)
|
||||
- Platform toolchain per target:
|
||||
- iOS: Xcode
|
||||
- Android: Android Studio + SDK
|
||||
- macOS/Linux/Windows Tauri: see `apps/desktop/README.md`
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
# 1. Node + pnpm (macOS)
|
||||
brew install pnpm
|
||||
corepack enable
|
||||
|
||||
# 2. Clone + install
|
||||
git clone <this repo>
|
||||
cd chat-app
|
||||
pnpm install
|
||||
|
||||
# 3. Env
|
||||
cp infra/supabase/.env.example apps/mobile/.env
|
||||
cp infra/supabase/.env.example apps/desktop/.env
|
||||
# Fill in SUPABASE_URL and SUPABASE_ANON_KEY from your self-hosted stack.
|
||||
```
|
||||
|
||||
See `infra/supabase/README.md` for spinning up the backend.
|
||||
|
||||
## Common Scripts (run from repo root)
|
||||
|
||||
| Script | Purpose |
|
||||
|--------|---------|
|
||||
| `pnpm dev` | Start every workspace's dev task (Turborepo). |
|
||||
| `pnpm build` | Build every workspace. |
|
||||
| `pnpm lint` | ESLint across workspaces. |
|
||||
| `pnpm typecheck` | TypeScript project-wide type check. |
|
||||
| `pnpm test` | Vitest across workspaces. |
|
||||
| `pnpm format` | Prettier write. |
|
||||
| `pnpm format:check` | Prettier check. |
|
||||
| `pnpm mobile:dev` | `expo start` for the mobile app. |
|
||||
| `pnpm mobile:ios` | Native iOS run. |
|
||||
| `pnpm mobile:android` | Native Android run. |
|
||||
| `pnpm desktop:dev` | `tauri dev` for the desktop app. |
|
||||
| `pnpm desktop:build` | Platform-specific Tauri bundle. |
|
||||
| `pnpm db:types` | Regenerate `@chat-app/db-types` from the running Supabase. |
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
- **Shared-first**: Anything that can run in both React Native and the Tauri WebView lives in `packages/shared` and is imported via `@chat-app/shared/*`. Both hosts pass in adapters for platform-only concerns (secure storage, SQLite, libsodium backend).
|
||||
- **Zero-knowledge server**: Messages are encrypted client-side before insert. The server sees ciphertexts, a conversation id, a sender id, and a timestamp — nothing else.
|
||||
- **Key custody**: X25519 private keys live in platform secure stores only (Keychain/Keystore on mobile, Stronghold on desktop). Public keys live in the `profiles` table.
|
||||
- **Realtime**: Supabase Realtime delivers new ciphertext rows to subscribed clients. Push notifications are silent (data-only) — the client decrypts and composes the visible notification locally.
|
||||
|
||||
## Security Checklist
|
||||
|
||||
- [ ] RLS enabled on every user-facing table
|
||||
- [ ] Invite-only enforced in SQL (invites table + policy)
|
||||
- [ ] No plaintext in push payloads
|
||||
- [ ] Service role key never shipped to a client
|
||||
- [ ] JWT secret rotated on first boot
|
||||
- [ ] TLS via Caddy at the edge
|
||||
Reference in New Issue
Block a user