Skip to content

End-to-end encryption

End-to-end encryption (E2EE) means the server can’t read your data. Encryption and decryption happen on your devices; the server stores only ciphertext and wrapped key material.

For the server-side architecture (endpoints, entities, workflows), see E2EE architecture.

When E2EE is enabled, these record types are encrypted client-side before upload:

  • Memory — your personal knowledge store
  • Sessions — optimization history
  • Providers — your AI provider configurations (with API keys)
  • Todos — task list

What’s not encrypted, by necessity:

  • Account metadata (your email, role, account creation time).
  • Record metadata: per-record timestamps, IDs, owning user, entity type.
  • Sync cursors and the audit log.
  • The shape of your traffic — which endpoints you hit, when, from where.

E2EE protects content; it does not give you anonymity from the server operator.

Three layers of keys, all 32 bytes:

KeyWhat it doesHow it’s stored
UMK — User Master KeyWraps all DEKs. Identifies “you” cryptographically.Generated locally; stored in DPAPI on Windows; never uploaded in plaintext
DEK — Data Encryption KeyOne per record. Encrypts the payload.Wrapped with UMK and stored next to the ciphertext
KEK — Key Encryption KeyDerived per-purpose: ECDH for device-to-device, Argon2id for recoveryEphemeral; never stored

Every encryption uses AES-256-GCM with AAD context binding — a string that ties a wrapped blob to its context. A blob from one context can’t be silently replayed in another:

PurposeAlgorithmAAD
Record payloadAES-GCM(DEK, plaintext)pia-e2ee-v1:{userId}:{entityType}:{entityId}
DEK wrapAES-GCM(UMK, DEK)pia-dek-wrap-v1:{entityType}:{entityId}
Device-to-device wrapAES-GCM(KEK, UMK), KEK from ECDHpia-umk-wrap-v1:{targetDeviceId}
Recovery wrapAES-GCM(KEK, UMK), KEK from Argon2id

Each device has its own ECDH (P-256) and ECDSA (P-256) keypairs, generated locally via Windows CNG. The first device on an account self-wraps the UMK using its own keys. Each additional device must be approved from a device that’s already active:

  1. The new device registers as Pending and uploads its public keys.
  2. An existing device sees the request and confirms (you compare a 16-character fingerprint shown on both screens — XXXX-XXXX-XXXX-XXXX).
  3. The existing device wraps the UMK for the new device using ECDH.
  4. The new device unwraps it locally and is upgraded to Active.

If you don’t have an existing device handy, the recovery code is the way back in — see Recovery codes.

DEKs, KEKs, and unwrapped UMK material are zeroed in memory immediately after use on the client. Plaintext keys never touch disk except via DPAPI for the UMK at rest.