Files
wisp/README.md
Fredrik Johansson 8fd73155bd Initial design: async single-retrieval encrypted file drop
README covers the pitch and how this differs from flit (synchronous,
zero server storage) and zipline (persistent hosting). IMPLEMENTATION
covers the crypto scheme (key-in-fragment, same primitives as
flit/waste-go), storage shape, and the deletion-race problem —
delete-on-first-byte-served is the wrong default (see Firefox Send's
history with this exact bug); confirm-then-delete with a TTL backstop
is the fix.

No code yet — design stage.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-09 17:58:17 +02:00

50 lines
2.1 KiB
Markdown

# wisp
Short-lived, end-to-end encrypted file sharing. Send a file to someone who
isn't online right now — they get a link, they get the file once, and then
it's gone. The server never has the ability to read what it's holding.
## Why
`flit` already does encrypted file transfer between devices, but it's
synchronous — both sides have to be online at the same time for the WebRTC
handshake. That's fine for "send this to my other laptop right now," and
wrong for "here's a file for you, grab it whenever."
wisp is the asynchronous counterpart: upload once, the recipient retrieves
later, on their own schedule. That async gap is the one thing flit's
architecture (zero server storage, direct P2P) structurally can't do — it
requires the server to actually hold ciphertext for a while, which is new
territory for this project family, not a variant of something already built.
## What it isn't
- **Not zipline.** Zipline is persistent link/screenshot hosting — you keep
the URL, the file stays. wisp is the opposite: single retrieval, then the
file is unrecoverable, by design.
- **Not flit.** Flit needs both peers online simultaneously and never stores
anything server-side. wisp is deliberately async and requires temporary
server-side ciphertext storage.
## Core model
1. Sender encrypts the file client-side (symmetric, libsodium secretbox —
same primitive flit's browser client already uses).
2. Ciphertext uploads to the server. The encryption key never leaves the
sender's browser except inside the URL fragment (`#key=...`), which
browsers never transmit in HTTP requests. The server only ever sees
opaque bytes.
3. Sender shares the link through any channel they like.
4. Recipient opens the link, downloads the ciphertext, decrypts client-side.
5. On successful decrypt, the client sends a short confirmation to the
server. Only then does the server delete the blob.
6. A TTL (default: a few days) is the backstop for links nobody ever opens,
so nothing sits on disk forever.
Full design, including why "delete on first byte served" is the wrong
default, is in [IMPLEMENTATION.md](./IMPLEMENTATION.md).
## Status
Design only. No code yet.