- proto: FileEntry, FileListResp types; MsgFileListReq/Resp msg types;
CmdGetFileList + EvtFileList IPC types; Files field on IpcMessage
- mesh: ShareDir field + ScanShareDir(); on DataChannel open, auto-send
MsgFileListReq to new peer; handle MsgFileListReq (scan + reply) and
MsgFileListResp (emit EvtFileList to IPC subscribers)
- ipc: get_file_list command — own list returned immediately; remote peer
list requested via DataChannel (response arrives as EvtFileList event)
- daemon: -share-dir flag wired to mesh.ShareDir
- test scripts: pass -share-dir /home/frejoh/Downloads/{alice,bob,charlie};
test-network.sh verifies each peer's own file list via get_file_list
- FUTURE.md: document per-network share directories and multi-network design
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
125 lines
6.2 KiB
Markdown
125 lines
6.2 KiB
Markdown
# Future Vision
|
||
|
||
WASTE's design philosophy is still sound: small trusted groups, no central server, encrypted everything, equal nodes. That's essentially what Signal's sealed sender and private groups do today, just without a self-hosted option. This gap is worth filling.
|
||
|
||
---
|
||
|
||
## Architecture
|
||
|
||
Two clean layers, connected by the IPC port.
|
||
|
||
### Daemon
|
||
The real application. A long-running background process that handles everything:
|
||
|
||
- Peer mesh and connection management
|
||
- Cryptography and handshake
|
||
- NAT traversal and relay fallback
|
||
- File transfer
|
||
|
||
Exposes a local JSON API over TCP (`127.0.0.1:17337`). Can run headlessly — SSH into a box and the mesh stays alive even with no UI attached.
|
||
|
||
### UI Layer
|
||
Talks to the daemon over the IPC port. The separation means the UI is replaceable without touching the core.
|
||
|
||
Target: a web frontend (React or similar) wrapped in a native binary using a Tauri-style approach — native packaging, OS webview, no Electron weight. Avoids the wxWidgets ugliness of the old wxWASTE fork and the Qt licensing headaches of the VIA fork.
|
||
|
||
#### TUI (near-term)
|
||
A terminal UI is worth building first, as a `cmd/tui` using [Bubble Tea](https://github.com/charmbracelet/bubbletea). Since the IPC contract is already the full boundary, a TUI is just another client — connect to `127.0.0.1:17337`, receive the `state_snapshot`, then funnel incoming events into Bubble Tea's update loop. Incoming mesh events map naturally onto its Elm-style message model.
|
||
|
||
Benefits over jumping straight to a native GUI:
|
||
- Works over SSH; zero packaging complexity
|
||
- Validates the full IPC protocol and message flow end-to-end
|
||
- Useful day-to-day while the native UI is still future work
|
||
|
||
The TUI doesn't replace the long-term GUI — it won't serve non-technical friends — but it's the right first UI milestone.
|
||
|
||
---
|
||
|
||
## Protocol Modernization
|
||
|
||
### NAT Traversal
|
||
The main unsolved problem from the original WASTE — one party always needed an open port.
|
||
|
||
- Try UDP hole punching (STUN) first
|
||
- Fall back to an encrypted relay (DERP-style) when hole punching fails
|
||
- Relay sees only opaque encrypted blobs — end-to-end encryption holds
|
||
- Run the relay on a Hetzner VPS; `waste-relay` already implements the blind-forward model
|
||
|
||
### Bootstrapping & Rendezvous
|
||
No DHT needed at small group scale (10–50 nodes). Keep it simple:
|
||
|
||
- Each peer generates an Ed25519 keypair on first run — the public key **is** their identity
|
||
- Share a small signed invite file (`.waste-invite`) out of band: email, Signal, whatever
|
||
- The invite contains: current IP:port hint + public key + short-lived signature
|
||
- Once two peers connect, they gossip each other's addresses to mutual friends
|
||
- A local known-peers list in the data directory is sufficient at this scale
|
||
|
||
### Identity
|
||
- Persistent Ed25519 keypair, generated once
|
||
- Public key = stable identity, not a mutable nickname
|
||
- No phone number, no central registry — closer to Signal's model than WASTE's original unregistered aliases
|
||
|
||
### Per-Network Share Directories
|
||
|
||
The current `-share-dir` flag is a single global directory. Eventually, each network should have its own independent share set:
|
||
- Alice shares `/home/alice/Downloads/work-files` on the "work" network
|
||
- Alice shares `/home/alice/Music` on the "friends" network
|
||
- Peers on "work" never see Alice's music, and vice versa
|
||
|
||
When multi-network support lands (see below), the `ShareDir` field on `networkCtx` replaces the current global `Mesh.ShareDir`. The IPC `get_file_list` and daemon `-share-dir` flag should move to be per-network configuration — either via a config file or via an IPC command `set_share_dir` scoped to a `network_id`.
|
||
|
||
### Multi-Network Support
|
||
|
||
A single client should be able to participate in multiple networks simultaneously (e.g. "work" and "friends") without leaking that both identities belong to the same person.
|
||
|
||
**Privacy constraint:** if the same Ed25519 keypair is used across networks, any peer who is a member of both networks can trivially correlate you. The anchor also sees the same public key across networks.
|
||
|
||
**Solution — per-network derived identities:**
|
||
- One master Ed25519 seed in `identity.json`
|
||
- Per-network keypair = `HKDF(masterSeed, "yaw2-net", networkHash)`
|
||
- Same master + same network name = same derived keypair (stable identity within a network)
|
||
- Different networks = different peer IDs; correlation is impossible without knowing both network names
|
||
- The anchor sees only the derived public key
|
||
|
||
**Daemon changes:**
|
||
- Replace the single `networkCancel` with a `map[networkID]*networkCtx`
|
||
- Each context holds its own: derived identity, mesh, anchor connection, store (`messages-<netHash>.db`)
|
||
- `join_network` returns a `network_id` token used to scope subsequent commands
|
||
|
||
**IPC changes (breaking):**
|
||
- All commands and events gain a `network_id` field
|
||
- `get_state` returns an array of all joined networks
|
||
- `join_network` responds with `network_joined` carrying the derived peer ID for that network
|
||
|
||
**TUI changes:**
|
||
- Top-level network switcher (e.g. `[work] [friends]`)
|
||
- Rooms and peers are scoped per network underneath
|
||
|
||
### Transport (Long-term)
|
||
Current transport is TCP with custom framing. QUIC is worth revisiting once the core is solid — it gives multiplexing and better NAT traversal behavior essentially for free.
|
||
|
||
---
|
||
|
||
## Roadmap
|
||
|
||
| Priority | Item |
|
||
|---|---|
|
||
| 1 | Deploy `waste-relay` to Hetzner; verify cross-internet NAT traversal |
|
||
| 2 | Invite file format (`.waste-invite`) — solve bootstrapping without manual IP sharing |
|
||
| 3 | Peer gossip — auto-connect to friends-of-friends after initial invite |
|
||
| 4 | File transfer — chunked, encrypted, resumable |
|
||
| 5 | Message persistence — SQLite via `modernc.org/sqlite` |
|
||
| 6 | UI — web frontend consuming the IPC port; native packaging |
|
||
| 7 | UDP hole punching — full STUN implementation in `internal/nat` |
|
||
| 8 | QUIC transport — replace TCP framing for better NAT behavior |
|
||
|
||
---
|
||
|
||
## What to Keep from WASTE
|
||
|
||
- **Small group** — not a public network, not federated, not discoverable
|
||
- **No registration** — no phone number, no email, no central service
|
||
- **Encrypted everything** — at rest and in transit, end to end
|
||
- **Equal nodes** — no peer is "the server"; the relay is dumb infrastructure only
|
||
- **The soul** — a private overlay for people you actually trust
|