Encryption
Synced workspaces in General Text are end-to-end encrypted. Your files are encrypted on your device before they travel, and decrypted only on your devices and the devices of people you share with. Our servers relay and store ciphertext; they hold no key that can open it. This page explains how that works and, just as importantly, where its edges are.
Local-only workspaces never touch our servers at all. They live as plain files on your disk, readable by you and any tool you point at them. Encryption applies to what you choose to sync.
What is (and isn't) encrypted
Encrypted end to end:
- File contents. Every edit travels and is stored as ciphertext.
- File names and folder structure. Files sync under opaque random ids, and the name-to-file map is itself an encrypted document. The server never sees what anything is called.
- Binary files. Images, PDFs, and other attachments are encrypted on your device before upload.
- Live presence. Cursors and who's-typing signals are encrypted in transit and never stored.
- App data. The files and documents your apps read and write are your content, so they are encrypted like anything else in the workspace. (The apps' code is not; see below.)
Not encrypted (and we're explicit about it):
- Account and membership data. Your email, workspace and organization names, and who belongs to what. The server needs these to route and bill.
- Traffic shape. Ciphertext sizes, how many files exist, and when syncs happen.
- App code. We host and serve every app's code for the purposes of installing it in workspaces, which means it is not hidden from us, whether the app is public in the gallery or private to your organization ("private" means only your org can install it, not that we can't see it). Once installed it runs entirely from an encrypted copy in your workspace, so we can't see when or how often you use it. We host the code only for installation. As always, the data those apps read and write is your content, and stays encrypted (above).
In short: the server can see that your workspace has 40 files totalling some megabytes and that you edited this morning. It cannot see what any file says or what any file is called.
The keys
Everything hangs off one identity per account, protected in layers:
- Your identity keypair. Created on your device when you set up encryption: one key for receiving encrypted material (X25519) and one for signing your changes (Ed25519). The public halves are published; the private halves never leave your devices unencrypted.
- Your encryption passphrase. Your private keys are encrypted under a key derived from a passphrase you choose (Argon2id, derived on your device). The server stores only the resulting wrapped blob. Entering the passphrase on a new device is how your identity travels; the passphrase itself is never sent anywhere. It is separate from your login password on purpose: login proves who you are to us, the passphrase unlocks what we cannot read.
- Your recovery key. Shown once at setup: a second, independent wrapping of the same identity. If you forget your passphrase, the recovery key restores access and lets you set a new one. Store it somewhere safe (a password manager, a printed copy).
- The organization key. Each organization has one key, delivered to each member as a grant: sealed to that member's public key and signed by the member who granted it. The server stores grants as opaque blobs it cannot open. Holding the org key is what makes you an insider: one grant, and every workspace the organization lets you open, opens.
- Workspace keys. Every synced workspace has its own content key (XChaCha20-Poly1305) that actually encrypts its files. For members it travels wrapped under the org key, so joining an organization never means a pile of per-workspace handshakes. For guests (people invited to a single workspace) it is sealed and signed to them individually: a guest never holds the org key, so the only thing they can ever decrypt is the workspace they were invited to.
- The device cache. After you unlock once, your identity is kept on the device under a non-extractable browser key so you aren't retyping the passphrase constantly. You control how quickly it re-locks after inactivity (Settings › Security), from minutes to never.
How sharing works
How a new member gets the org key depends on whether they already use General Text. If they do, then the moment you invite them your own device wraps the org key to their published public key and stores the sealed grant, so they have access the instant they accept, with nothing else to do. If they're new to General Text, they first accept the invitation, sign in, and choose an encryption passphrase (which publishes their public key); an admin then grants them the key. We email the organization's admins the moment a member is waiting, so nobody has to keep checking. Either way the wrap happens on an admin's own device, never on our servers, and the two of you never need to be online at the same time: the sealed grant waits on the server until the new member's device picks it up.
The receiving device verifies the grant's signature against the member roster before accepting the key, and pins the key's fingerprint so that a later substitution trips an alarm instead of silently re-keying the device. The server only moves the sealed grant; it can neither read it nor forge one.
Inviting a guest to a single workspace works the same way at a smaller radius: when a workspace admin next opens the workspace, their device seals that workspace's key to the guest's published identity and signs it. The guest gets exactly one workspace; removing them deletes their grant and disconnects them immediately.
Because the server distributes public keys, a compromised server could in principle try to substitute one. That's what safety numbers are for: each account has a fingerprint (Settings › Security) that two people can compare over a trusted channel, in person or on a call. Matching fingerprints prove you hold each other's real keys. On the granting side the same fingerprint is shown next to each member in your organization's Encryption settings, so an admin can compare it before handing over the key.
If you'd rather make that comparison mandatory, an owner or admin can turn on Require manual approval for every member in the organization's Encryption settings. Every new member, whether or not they already use General Text, then waits for an admin to grant them by hand after checking the fingerprint, trading the automatic instant-access convenience for a guaranteed human check on every key.
Every change is signed
Each edit and snapshot carries a signature from its author inside the encryption, so the relay never learns who wrote what, but every receiving device verifies that changes come from a current member of your organization. Devices reject anything unsigned or signed by an unknown key, and the server refuses to store unsigned frames at all. Each device also remembers the highest sync position it has seen per file and raises a warning if the server ever serves older history than that, so a rolled-back or tampered log cannot pass silently.
Recovery
End-to-end encryption has a consequence: we cannot reset what we cannot read.
- Forgot your passphrase? Use your recovery key to restore access and set a new one.
- Lost the recovery key but know your passphrase? Generate a new recovery key in Settings › Security.
- Lost both? Your synced data is unrecoverable by us, by design. Copies already on your devices remain readable there, and org content can be re-granted by another member of your organization, but a solo account with no unlocked device has no back door. Keep the recovery key safe.
Removing someone
Removing a member deletes their grant and disconnects their sessions immediately; they can no longer fetch anything. Eencryption cannot un-share the past. Anything they already synced may exist in copies they kept, which is true of every collaboration system. For content created after removal, they hold no working access.
History
Every synced file keeps a version history you can browse and restore from (the History view next to Edit and Preview). It works the same way everything else here does: the server stores an opaque log of encrypted changes and your device decrypts and replays them, so we can serve your history without ever being able to read it. Each version shows who made it, verified by the same signatures that protect live editing. Restoring an old version applies it as a new change; nothing is rewritten, and the restore itself becomes part of the history.
Current limits
- Synced files are capped at 100 MB each.
- History is kept for up to 14 days and counts toward your storage. On desktop, you can set how long of a history to store.
The crypto
All cryptography runs client-side via libsodium: XChaCha20-Poly1305 for content (each file's id is bound into the ciphertext so blobs can't be swapped between files), X25519 sealed boxes for key grants, Ed25519 for authorship signatures, and Argon2id for the passphrase. The server's job is to move and store bytes it cannot interpret, and the app sandbox (see Security) bounds what code you install can reach.