The architecture behind the privacy claims. For anyone evaluating whether the sandbox does what we say it does.
All conversation content — field values in both directions, and the labels the operator writes to describe those fields — is encrypted in the browser before it hits our servers. The server sees ciphertext, not plaintext, and never handles the keys that could decrypt it.
room_code:field_id:kind:from:version:seq, where
kind
is value
or label
and from
identifies the sending party — so a replayed or mis-routed envelope, or one reclassified by the server as the wrong kind or from the wrong side, fails to decrypt.
text, phone, email, date) — used to pick the right input keyboard and formatting on the visitor's device — and a
timestamp
on each message the operator sends to the visitor (used for the "sent at HH:MM" label that appears on both sides). The actual label text ("SSN", "DOB", etc.) and the message body itself are encrypted. If you're not comfortable with the server knowing the broad category of a field, set every field to text; no category is ever required.
sessionStorage
for the duration of the browser tab, so a page reload mid-session doesn't force a re-handshake. The ECDH private key is
not
persisted — it exists only in memory and dies on reload. When the session ends (either party clicks End, or the server's reaper times it out), the client wipes the cached key from sessionStorage.
ECDH with server-relayed keys is vulnerable to an active server swapping both public keys — a classic man-in-the-middle. The bingo-ball handshake closes that gap with an out-of-band human channel.
A Tunnls session is a memory-only Erlang GenServer process. It exists for the duration of one conversation and dies when the operator ends it, the visitor disconnects, or the reaper timeout fires.
session_events
row per session for free-tier quota accounting. That row contains operator_id, room_code, and a timestamp — nothing about the conversation.
lib/tunnel/session/
if you want to read the implementation.
The entire E2E path — keypair generation, key agreement, HKDF, AES-GCM encryption, bingo-grid derivation — lives in a standalone, MIT-licensed library:
github.com/greghgradwell/tunnls-e2e
The web app pulls it in as a git submodule under assets/vendor/tunnls-e2e/. Nothing in the application code re-implements or overrides the crypto path — what you audit in the repo is what runs in the browser. You don't have to trust us on the encryption claims; audit the library yourself.
Ready to try it?