Skip to content

Synchronization and keys ​

Synchronization transfers encrypted records. Decryption, local indexing and retrieval happen on the user's device; the server does not need a model or an account decryption key.

flowchart LR
  A["Device A: keys + SQLite"] <-->|"Encrypted records"| Server["Server: authentication + Postgres"]
  Server <-->|"Encrypted records"| B["Device B: keys + SQLite"]
ModeBehavior
LocalNo configured remote connection
AutomaticThe runtime schedules synchronization after supported writes
ManualRun rsrs sync explicitly

RSRS_NO_AUTOSYNC overrides the account's client.json setting. Setting it to a nonzero value disables automatic synchronization. Explicit sync waits for the synchronization attempt to finish.

Record handling ​

MechanismPurpose
Dirty records / outboxPreserve local edits awaiting acknowledgement
Ordered server cursorDownload changes without depending on device clocks
TombstoneSynchronize deletion intent
Retained versionsPreserve conflicts and history for review
Local feature artifactRebuildable retrieval data; separate from the encrypted content revision

See synchronization v2 for conflict decisions and server recovery.

Key ownership ​

flowchart TD
  Secret["Super password + Account Secret"] --> Wrap["Key derivation and wrapping"]
  Wrap --> URK["User root key"]
  URK --> Data["Local data and embedding encryption keys"]
  Data --> Records["Encrypted records"]
ChangeEffect
Login passwordChanges authentication credentials
Super password resetRewraps the root key; does not rewrite every record
New deviceRequires authentication and the necessary key-recovery material
LogoutFollow logout --help; removing local identity is separate from revoking a remote session

Legacy v1 recovery uses the original login password plus Account Secret, with no separate super password. The wrapping diagram above describes accounts with a separate super/recovery factor; do not request a replacement super password for v1 recovery. Normal login preserves the vault version and encrypted read/write format. Only explicit namespace migration rewrites the selected copy, and it retains the original factors and source.

The server stores opaque vault versions 1 through 4 at POST /api/self/vault. For the first upload of recovery material, send If-None-Match: * to create only a missing vault. If another vault already exists, the server returns 412 and preserves that vault; the client must read and verify it instead of overwriting it. Invalid fields, versions or unsupported conditions return 400. A request without the condition keeps the existing upsert behavior and is not safe for first-time recovery initialization.

An optional server-side envelope is proposed but not yet released: it would add wrapped_urk_server and server_urk_nonce, a second, opaque wrapping of the same URK under a server KMS envelope key, so a host holding the envelope key could unwrap the URK without the super password when RSRS_SERVER_KEK is set. The published server does not accept or return these fields yet. The documented baseline POST /api/self/vault takes kdf_salt, wrapped_urk, urk_nonce and optional version.

Later server revisions also accept optional operation and expected_key_generation. An intentional same-URK rewrap uses operation=rewrap_same_urk with the current expected_key_generation to preserve passkeys; the client must first unlock the existing URK because the server cannot compare opaque keys. A changed legacy upsert can advance the generation and invalidate passkeys. Check the contract for the deployed server revision before using these fields.

The proposal is incomplete and does not commit to a release or deployment. An older server ignores unknown JSON fields and would store the vault without any envelope. This page and the contract will document the fields as supported only after the producer ships them.

Keep migration credentials, Account Secret and session files private. Do not add them to repositories or send them through ordinary plugin payloads.

Backup ​

BackupContainsRecovery requirement
exportPlaintext recordsProtect the exported file
backupLocal SQLite databaseKeep the matching key material
Key recovery materialAccount secrets or wrapped-key accessStore independently from the database backup

Before replacing an active database, stop the corresponding runtime and follow the installed restore procedure. Verify a restored copy before relying on a backup.