What the signaling server can see
The server atapi.floe.one exists so two devices can find each other. It never touches the file.
It does:
- Put two devices in a room and decide which one sends.
- Pass the connection-setup messages between them.
- Hand out relay credentials, valid for 24 hours, when a relay is configured. They are not tied to you or to an account: on floe.one one credential set is minted from Cloudflare and served to every client until the cached copy is refreshed.
- Map a three-word code to a room id for ten minutes, when a sender asks for one.
- Keep a single running total of bytes transferred, for the counter on the homepage.
- Receive, store, or inspect file data.
- Keep room or peer information past the session. The only thing that outlives it is a short code’s mapping to a random room id, which stops working ten minutes after the code was made.
- Log what you transfer, your file names, or who you sent to.
What the relay can see
When a direct path is impossible, traffic goes through a TURN relay. On floe.one that is Cloudflare’s Realtime TURN network; a self-hosted instance can run its own coturn instead. The relay sees encrypted packets, plus the metadata that being the middle hop entails: both IP addresses, and the timing and size of what it forwards. Your infrastructure provider may log that for its own security purposes. The relay does not see the contents of those packets. Files are encrypted before they reach it and decrypted only on the recipient’s device. The relay’s operator is contacted before the route is decided, not only when a relay carries data. While a connection is being set up, every device asks the STUN server for its public address and, unless relay fallback is off, opens a standby TURN allocation, so on floe.one Cloudflare sees each device’s IP address and connection timing on every transfer. File data crosses it only when the relay path is the one that wins. Routing through a relay also changes who learns your IP address. On a direct connection the two devices learn each other’s, which is how any peer-to-peer connection works. If you would rather not reveal yours, Floe Desktop’s Hide my IP address forces the relay path so the other person sees the relay instead, and the CLI’s--relay-only flag does the same. The browser has
no equivalent.
The room secret stays out of every server log
A share link keeps the room id in the URL fragment, after the#, never in the query string.
A link from the web app or the desktop app looks like
https://www.floe.one/?s=a1b2c3d4#room=..., and one from the CLI looks like
https://floe.one/#room=.... The ?s= value is a random per-link marker carrying no information;
it exists only so each link is a distinct page, which stops a device that already has Floe open
from reusing a stale tab.
Browsers never send the fragment to a server. So the room id is not in Referer headers when you
click an outbound link, not in server access logs, and not captured by pageview analytics or
third-party trackers. The signaling server learns it when a device joins that room over its own
connection, and, for a transfer started from the CLI or Floe Desktop, when the sender registers the
three-word code for it; either way no file bytes ever reach it.
Aggregate statistics
The homepage carries a public, all-time count of bytes moved across every Floe user. To feed it, the receiving side reports how many bytes it received after a transfer completes. The sender never reports. All three receivers contribute, and the total itself is only ever displayed in the browser. What is recorded: one cumulative integer. Nothing else. What is not recorded: file names, contents, per-transfer rows, who sent or received, or any link to your identity or IP address. The reported figure is a size, added to a running total. Every receiving surface can turn the report off, and turning it off means the byte count is never sent, rather than sent and ignored.- Browser: uncheck Contribute to global stats on the receiver view before the first file lands. The choice is saved in that browser and applies to every later transfer from it.
- Floe Desktop: turn off Contribute to global stats in Settings. It is saved with your other settings.
- CLI: pass
--no-reporttofloe receivefor one transfer, or setFLOE_NO_STATS=1in your environment to opt out for good.
Error monitoring and analytics
The CLI and the desktop app contain no analytics, no error monitoring, and no telemetry. Beyond the transfer itself they make exactly two kinds of optional request, and both have an off switch: the byte-count report above, and an update check. The update check runs once a day in Floe Desktop (GitHub builds 0.2.3 and later). The CLI does it only when you runfloe version, and never during a transfer; floe update and
floe update --check also reach GitHub, but those are you asking for it. It asks GitHub whether a
newer release exists. The request
carries nothing about you beyond what any web request reveals, and nothing downloads or installs
by itself. Turn off Check for updates in the desktop
Settings, or set FLOE_NO_UPDATE_CHECK=1 for either
surface, and no request is made. Microsoft Store builds never check, because the Store updates
them.
The rest of this section is about the floe.one website only.
- Sentry records application errors and a 10% sample of browser performance traces. It is configured to attach no cookies and no IP address; each report carries the page address, the browser’s user agent, and the referring page. The room secret is stripped out of every error report, breadcrumb, and performance trace before it is sent.
- Session replay is not enabled and will not be added. A replay records the page address, and on a receiver page that address contains the room link, which is the only thing protecting the transfer.
- Umami records cookieless, aggregate page views and transfer outcomes: file count, total bytes, direct or relay, success or failure. Page views carry the browser, operating system, device type, screen size, language, and a location down to city, worked out from the IP address, which Umami says it does not keep. It is configured to send neither the URL fragment nor the query string, so the room secret never reaches it; it sets no cookies and cannot follow you to other sites, though it recognizes a returning visitor for a while through a hashed, salted fingerprint that rotates on a schedule. If your browser sends Do Not Track, it records nothing at all.
Browser hardening
floe.one sends a Content-Security-Policy withframe-ancestors 'none', repeated as
X-Frame-Options: DENY for older browsers, so no other site can put Floe in an iframe.
That matters more here than on a typical site. A receiver page joins its room automatically on
load and then answers the sender’s offer with its own network addresses, so an invisible embedded
copy pointed at an attacker’s room could otherwise disclose a visitor’s local and public IP
addresses without a single click.
The same header set blocks plugin content and <base> rewriting, restricts form submissions to
floe.one, sends X-Content-Type-Options: nosniff, sets
Referrer-Policy: strict-origin-when-cross-origin, denies camera, microphone, geolocation,
payment, and USB access outright, and opts the site out of ad interest cohorts. The signaling
server sends the standard hardening headers too.