Skip to content

Architecture

Orange Copy Paste is a desktop app plus an optional sync backend. The app is the source of truth for your data; the backend is a relay that never sees plaintext.

The client captures the clipboard, keeps history and notes in local files, holds all key material, and performs every encryption and decryption. The Rust side owns state, persistence, OS integration, and cryptography; React is the UI. With sync off or the server unreachable, the app is fully functional and queues work locally.

The backend verifies the JWTs Supabase issues (it never signs one), stores ciphertext, fans changes out to a user’s other devices and space members over a WebSocket, and hands out presigned URLs for encrypted blobs. It is stateless, so it scales to N replicas; cross-replica delivery goes through Redis pub/sub.

The client holds every key and does all the crypto. Everything below the wire stores or relays ciphertext.
The master key is opened on the device before anything syncs, and the server hands back only wrapped keys.
  1. The client stretches the account password with Argon2id, salted from the email, and splits the result in two. It signs in with Supabase directly using one half, the auth key. The password itself is never sent.
  2. It bootstraps the account and receives the account’s key salt and the password-wrapped master key.
  3. It derives the key-encryption key from the other half and that salt, and unwraps the User Master Key in memory. A wrong password is simply a failed decryption.
  4. It registers the device, publishes the device’s public key, and stores a copy of the master key wrapped for that device, so the device can open it again later without the password.
  5. Entries are encrypted locally, pushed, and pulled. Merges are last-write-wins on updated_at.
  6. The WebSocket streams live changes from other devices and space members.
Replicas share nothing in memory. A change reaches a socket on another replica through Redis.

The keys and what each one protects are explained in the technical security model.

Deletes travel as tombstones (a push carrying a deletion marker, not a delete request), and a tombstone wins a conflict. Sharing is one primitive, the Space: persistent, multi-member, with a random space key distributed to members by wrapping it for each member’s X25519 public key.

Each specification lives in the repo next to the code that enforces it, so the code stays the one place it is edited. The Reference pages below mirror those files here, read-only, and each one links back to its home in the source repo. Read them before changing anything that crosses the wire.

Specification Reference page
Wire contract: routes, payloads, DDL, socket events, crypto envelope Backend architecture
Client internals: state, commands, events, persistence, sync engine Client architecture
Cross-component map and invariants Architecture map
Who may do what, and where it is enforced Permissions
How a release gets cut Releasing
Notable regressions and their causes Bug fix history