Privacy

Oblivious HTTP

Every call about you is sealed in your browser, carried by a relay that can't read it and opened by a gateway that can't see who sent it.

YOUR BROWSERAppScreens and ticketsStatic: no app serverWallet workerZcash's wallet in WASMSync, proofs, sendsEngineSizes, rests, timing,and the leak meterVenue adaptersFour venues andNEAR 1Click quotesVaultKeys and wallet list,encrypted on deviceCLOUDFLARERelay/relay/ohttpSees IP, not contentNo IP or cookies sentVERCEL · DUBLINGatewayOpens each requestSees content, not IPNo logs of its ownHolds Polymarket'sBuilder secret; signsonly Deposit Walletrelayer callsALLOWLIST ONLYUpstreamsZcash light serversNEAR Intents 1ClickPolymarket APIsPolymarket Perps APIHyperliquid APIJupiter, Solana RPCPolygon RPCGeckoTerminalDURABLE OBJECTLive feed/relay/live/*One socket per venue,market channels onlyno user channelsPUBLICVenue feedsHyperliquidPolymarketPolymarket PerpsImage proxy/relay/imgPublic, cached 24 hImage fetchChecked on every hopHeld assets: sealedImage hostsLogos and picturesSealed with Oblivious HTTP: every call about youPublic market data and pictures: the relay sees whichYOUR BROWSER · UMBRA TRADE.XYZAppScreens, charts, order ticketsWallet workerZcash's wallet in WASM: sync, proofsEngineSizes, rest rules, timing, leak meterVenue adaptersPolymarket, Perps, Hyperliquid, SolanaVaultKeys and wallet list, encryptedOHTTP · sealedCLOUDFLARE WORKERRelaySees your IP, not the contentNo IP, cookies or agent passed onsame sealed bytesVERCEL FUNCTION · DUBLINGatewaySees the content, not your IPWrites no logs of its ownSigns only Deposit Wallet callsHTTPS, from IrelandALLOWLIST ONLYUpstreamsZcash light servers, NEAR 1ClickPolymarket, Polymarket PerpsHyperliquid, Jupiter, Solana RPCPolygon RPC, GeckoTerminalPUBLIC DATA · NOT SEALEDLive feed and pictures/relay/live/*: one WebSocket per venue,market channels only/relay/img: public pictures, 24 h cachePictures of what you hold go sealedSealed (Oblivious HTTP)Public data, not sealed
Every call about you takes the vermilion path. The relay knows who is asking, the gateway knows what is asked, and neither knows both.
The same map the README shows. Every user call takes the sealed path.

The client

StandardRFC 9458 Oblivious HTTP
SuiteDHKEM(X25519, HKDF-SHA256), HKDF-SHA256, AES-128-GCM; a fresh HPKE context per request
KeyThe gateway's key configuration is pinned in the app (packages/net/src/constants.ts), so the relay can't swap in its own
Inner requestcredentials: omit, no-referrer; up to 8 MiB
EndpointPOST /relay/ohttp on the same origin, content type message/ohttp-req

The relay: knows who, not what

A Cloudflare Worker (mitoshi-web) with Cloudflare's targeted placement near AWS eu-west-1, and its logs off.

  • Forwards only the sealed body to the gateway, with a fresh header set: no IP, cookies, user agent, referrer or language.
  • Answers only /relay/ohttp, /relay/img and the three live feeds; anything else is a 404.
  • Holds one live WebSocket per venue (Hyperliquid, Polymarket, Polymarket Perps) in a Durable Object and shares it with everyone watching. Only public market channels are allowed: a subscription that names a user is refused. The Polymarket Perps tickers channel is skipped (about 700 updates a second for all markets); statistics gives the price, sent at most once a second. If a feed is unavailable, the relay answers 503 with Retry-After: 60 and the app backs off for a minute: live ticks pause, while prices and history still load over Oblivious HTTP.

The gateway: knows what, not who

A Vercel Function in Dublin (dub1, AWS eu-west-1). It accepts only messages that carry the relay's token, opens each one, and calls only an allowlist of 14 API hosts with exact methods and path prefixes (pictures go through a separate, checked image fetch, below):

UpstreamWhat for
zcash-mainnet.chainsafe.dev, zcash-testnet.chainsafe.devSix lightwalletd methods
1click.chaindefuser.comNEAR Intents quotes, deposits, status (the partner key is added here; the browser never sees it)
api.hyperliquid.xyzMarkets, accounts, signed orders
gamma-api, clob, relayer-v2, data-api, bridge.polymarket.comEvents, books, orders, gasless wallets, positions, the bridge
api.perpetuals.polymarket.comPolymarket Perps
polygon.drpc.orgRead-only Polygon calls, no sends
lite-api.jup.ag, api.geckoterminal.com, api.mainnet-beta.solana.comSolana swaps, charts, balances and the trip home

Every upstream request leaves with the same browser-like user agent for everyone and drops cookie, origin, referrer, user-agent and forwarding headers. Redirects aren't followed. A public answer may be cached and shared between users for seconds up to a few minutes; anything carrying a credential never is. Polymarket's event listings are trimmed to the fields the app reads before they are sealed back (one evening of sports markets can otherwise pass 10 MB); a single event is never trimmed (services/gateway/src/shape.ts).

Why the gateway isn't on Cloudflare

Tests on 2026-10-22 showed that a Cloudflare Worker passes the visitor's own country on to every Cloudflare-hosted site it calls, and Polymarket, 1Click and Jupiter sit behind Cloudflare. From Vercel's Dublin region, every request leaves from Ireland.

Pictures

PicturePathWho sees what
Public ones (market and token lists)GET /relay/img?u=…, cached a dayThe relay sees which public picture, like any public price
Pictures of what you hold (positions, orders)inside an OHTTP message to img.mitoshi.internalThe relay can't see which; the gateway fetches it without knowing who asked, and the browser gets a blob

The image fetch accepts only HTTPS, refuses local and internal hosts and literal IP addresses, re-checks each of up to three redirects, and takes PNG, JPEG, WebP, GIF, AVIF or SVG up to 2 MiB.

The builder signer

Polymarket's gasless Deposit Wallets need builder headers. The gateway holds that secret and signs only four relayer paths; on /submit it signs only WALLET-CREATE and WALLET requests to the Deposit Wallet factory. Anything else gets a 403. Through OHTTP it sees which wallet asks, never who.

On this page