diff --git a/README.md b/README.md index fb596c7..db240d9 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ go run ./cmd/anchor -bind 127.0.0.1:17339 # Terminal 2 — peer A go run ./cmd/daemon -alias alice -data-dir /tmp/waste-alice -ipc-port 17337 -anchor ws://127.0.0.1:17339/ws -# Terminal 3 — peer B +# Terminal 3 — peer B (or use --join with an invite from peer A) go run ./cmd/daemon -alias bob -data-dir /tmp/waste-bob -ipc-port 17341 -anchor ws://127.0.0.1:17339/ws ``` @@ -98,16 +98,29 @@ Everything is newline-delimited JSON. You can test with `nc 127.0.0.1 17337`. {"type":"join_network","network_name":"friends"} {"type":"leave_network"} {"type":"send_message","room":"general","body":"hi"} +{"type":"send_message","room":"dm:","body":"hey","to":""} {"type":"get_state"} +{"type":"generate_invite"} ``` **Events the daemon pushes:** ```jsonc -{"type":"state_snapshot","local_peer":{...},"connected_peers":[...]} -{"type":"peer_connected","peer":{...}} -{"type":"session_ready","peer_id":"","nick":"alice"} -{"type":"message_received","message":{"from":"","body":"hi","room":"general"}} -{"type":"peer_disconnected","peer_id":""} +// Sent immediately on connect and in response to get_state +{"type":"state_snapshot","local_peer":{"id":"<64-hex>","alias":"alice","public_key":"<64-hex>","created_at":"..."},"connected_peers":[...],"rooms":["general"]} + +// Peer lifecycle +{"type":"peer_connected","peer":{"id":"<64-hex>","alias":"bob",...}} +{"type":"session_ready","peer_id":"<64-hex>","nick":"bob"} +{"type":"peer_disconnected","peer_id":"<64-hex>"} + +// Incoming message — mid is a 32-hex dedup token, to is set for DMs +{"type":"message_received","message":{"mid":"<32-hex>","from":"<64-hex>","to":"<64-hex>","room":"general","body":"hi","sent_at":"..."}} + +// Invite generation response +{"type":"invite_generated","invite":"waste:"} + +// Error +{"type":"error","error_message":"..."} ``` ## Crypto choices @@ -125,6 +138,28 @@ Replaces WASTE's original Blowfish/PCBC (broken cipher mode) + RSA. > Peer IDs are 64-char lowercase hex (Ed25519 public key). Existing `identity.json` files > on disk are unaffected — only the over-the-wire representation changed from base64url. +## Onboarding a new peer + +Alice is already on the network and wants to add Bob. + +**Alice generates an invite** (from the TUI with `Ctrl+I`, or via IPC directly): +```bash +echo '{"type":"generate_invite"}' | nc 127.0.0.1 17337 +# → {"type":"invite_generated","invite":"waste:eyJhbmNob3IiOiJ3czovL..."} +``` + +**Bob starts his daemon using the invite** — the `--join` flag sets the anchor URL and auto-joins the network: +```bash +go run ./cmd/daemon -alias bob -data-dir ~/.waste-bob --join 'waste:eyJhbmNob3IiOiJ3czovL...' +``` + +**Bob opens the TUI** — `--join` also accepts the invite to skip the `-network` flag: +```bash +go run ./cmd/tui --join 'waste:eyJhbmNob3IiOiJ3czovL...' +``` + +The invite encodes the anchor URL and network name as a `waste:` URI. Share it over Signal, email, or any side channel — the anchor never sees plaintext messages, so the invite leaking to a third party only lets them join the same network (which is by design: same network = mutual trust). + ## Terminal UI Start the daemon first (see Getting started above), then: @@ -137,7 +172,8 @@ Options: | Flag | Default | Description | |---|---|---| -| `-network` | *(required)* | Network name to join on startup | +| `-network` | *(required unless -join)* | Network name to join on startup | +| `-join` | — | `waste:` invite string — sets the network name automatically | | `-ipc` | `17337` | Daemon IPC port | **Layout:** @@ -153,7 +189,7 @@ Options: ╰─────────────────────────────────────────────────────────────╯ ``` -**Key bindings:** `Tab` / `Shift+Tab` — switch rooms · `PgUp` / `PgDn` — scroll · `Enter` — send · `Ctrl+C` — quit +**Key bindings:** `Tab` / `Shift+Tab` — switch rooms · `PgUp` / `PgDn` — scroll · `Enter` — send · `Ctrl+I` — generate invite · `Esc` — close invite overlay · `Ctrl+C` — quit ## Testing