Files
flit/PLAN.md

97 lines
4.0 KiB
Markdown
Raw Permalink Normal View History

# flit
Self-hosted, ephemeral, end-to-end encrypted file transfer between your own
devices — regardless of architecture. Think "AirDrop, but self-hosted and
cross-platform," built on the WebRTC/Ed25519 plumbing already proven out in
waste-go.
## Why
[Zipline](https://github.com/diced/zipline) already covers persistent,
link-based "upload once, share via URL" — good for sharing *to others* or
storing semi-long-term. This tool is different: ad hoc, point-to-point
transfer between *your own* devices (dev box → homelab box → laptop →
phone), without anything landing on a server's disk if it can be avoided.
Two use cases to design for:
1. **Desktop ↔ desktop** — browser tab or small CLI on each end.
2. **Desktop ↔ mobile (Android)** — the share-sheet flow is the whole point.
No iOS constraint — Android + desktop only. This drops a meaningful chunk of
complexity (no Safari/PWA quirks, no manual-code fallback needed for pairing).
## How
You can take a look at ../waste-go for inspiration, it does parts of this already.
## Non-goals
- No persistent storage, no accounts, no link sharing with third parties.
- Not a Zipline replacement — strictly "get a file from my hand to my other
hand."
## Architecture
**Transport**: WebRTC data channels for the actual file bytes, P2P whenever
NAT traversal allows it.
- A lightweight **signaling server** (self-hosted, homelab) exchanges
SDP/ICE candidates between peers. Stateless, ephemeral rooms, no file data
ever touches it.
- A **TURN relay fallback** (coturn, self-hosted) for when direct P2P fails
— common on mobile networks/CGNAT. Data stays E2E encrypted across the
relay, so it just shovels encrypted bytes.
**Identity & security**: reuse the Ed25519 keypair model from waste-go. Each
device has a long-lived identity key; pairing two devices derives a session
key (X25519 ECDH) so transfers are E2E encrypted even across the TURN relay.
No accounts, no passwords.
**Pairing UX**: QR code as the default everywhere, since there's no need to
support a browser that handles it poorly (no iOS).
- Generate an ephemeral room code / QR code on the sending device.
- Scan it on the receiving device to join the WebRTC session.
- Once paired, drag-and-drop (desktop) or native share sheet (Android) to
send.
**Clients**:
- **PWA** — covers desktop browsers and Android. Installable on Android home
screen, registered as a **Web Share Target** so "Share → flit" works
directly from any app's OS share sheet (Photos, Files, browser downloads,
anything). This is the primary mobile flow, not a fallback.
- **Go CLI** — for headless machines (homelab boxes, servers without a GUI),
reusing waste-go's transport/identity code directly. `flit send file.tar.gz`
prints a code/QR for the other end to scan.
## Build plan
1. **Scaffold the repo.** Reuse waste-go's Ed25519 identity + WebRTC
handshake code as a starting library if cleanly extractable; otherwise
port the logic.
2. **Signaling server** — minimal Go service, WebSocket-based room exchange
(peer A creates room, gets code; peer B joins with code; server relays
SDP/ICE only, then gets out of the way). Deploy alongside Zipline in the
homelab.
3. **PWA client** — file picker + drag-drop, QR code generation/scanning
(camera access for scan), Web Share Target manifest entry, WebRTC data
channel transfer with progress UI.
4. **Go CLI** — thin wrapper sharing core logic with the
signaling/transport layer, for headless homelab boxes.
5. **TURN fallback** — coturn instance, only invoked when direct P2P ICE
candidates fail.
6. **Stretch**: chunked transfer + resume for large files over flaky mobile
connections; multi-file/folder zip-on-the-fly.
## Open question
Host the PWA under goonk.se (e.g. `/flit`, alongside Pitwall/Delve as a
public-facing sub-site with a project badge) or keep it standalone on a
homelab subdomain as a personal tool rather than a portfolio piece? This
decides whether the implementing work also touches the goonk.se repo's
project content collection.