Google Drive sync
midden keeps your browsers in sync through a hidden app folder in your Google Drive, encrypted on your device with a sync passphrase. The app folder is private to midden: midden can't see your other Drive files, and they don't show it. Google stores only ciphertext.
This page covers how sync works and what it protects.
Once connected, midden syncs straight away. After that, your changes go out about 30 seconds after you make them. Other devices' changes come in when you open or return to midden (at most once a minute), when the browser starts, and every 10 minutes. sync in the menu (or sync now in Settings → Sync) runs one immediately.
Using it in another browser
- Install midden there.
- Settings → Sync: enter the same sync passphrase and connect. midden merges in everything your other browsers have, then sends this one's.
From then on, sync runs both ways by itself. Each change you make (a capture, a tag, a pin, a reminder, a deletion) is noted as it's saved, and goes out in a small encrypted batch once things go quiet. Each browser applies the other browsers' batches in order. Browsers that are never open at the same time still converge: the batches wait in Drive.
How changes merge:
- New captures, tags and taggings from either side are kept. Images download only if they're missing.
- Deletions follow. Forgetting a fragment, removing a tag from it, renaming a tag or deleting one leaves a small tombstone, which tells the other browsers to remove it too. If the item was captured or tagged again after the deletion, it stays: a deliberate re-add wins. Tombstones are kept forever, so a browser that was offline for months can't bring a deleted item back.
- What you say about an item (its reminder, the trash, "it's fine" on something that might be sensitive, markdown and its ticked boxes, which bundle it's in): kept beside it by its hash, and the most recent change wins, for markdown box by box.
- Pins: the most recent pin or unpin wins. Positions midden chooses itself aren't synced: each browser lays out the rest of the map from the same data, so maps look alike but not pixel-identical.
- The hoard (a separate extension): its envelope travels with the changes when it changed, still encrypted, and midden hands it to the hoard. If both browsers share the same hoard (one was set up from the other's), entries merge even while it's locked, the most recent edit wins, and deletions follow (into the hoard's 30-day bin). Otherwise (no hoard set up yet, or a different master password) the items wait in the hoard for your OK, and midden says so. Without the hoard installed, midden can't deliver them; they stay in Drive.
- Same-item edits made in two browsers between syncs aren't merged field by field: the later one wins.
When the store is erased or replaced: before each run, a device checks that the store's
sync-key.json is still the one it joined. It's the same store if:
- it's the same file as last time;
- it carries this device's key's check mark (a passphrase change elsewhere keeps the key);
- or, for a key file from before those marks, this device's key opens one of the store's files.
Anything else (no key file, a different key, nothing to tell by) stops sync on that device before anything is sent or taken. The device drops its copy of the key, and Settings → Sync says the store was erased or replaced. Nothing on the device changes. Connect again with the passphrase of the store that's there now. If the check itself can't run (offline, signed out), nothing goes either way, and the next run tries again.
Changing the passphrase: Settings → Sync → Sync passphrase → change asks for the current one and a new one, then re-wraps the same sync key under the new one. Browsers already connected keep syncing (they hold the key); a browser connecting from now on uses the new one. It doesn't re-encrypt what's already in Drive under a new key: if a passphrase leaked, start over (below). A recovery sheet keeps working.
The recovery key (optional): ten words from the EFF list (about 129 bits), printed once,
that open the store if the passphrase is forgotten. Connecting offers one when the store has
none, and Settings → Sync → Encryption → Recovery key makes one later. A connected device
already holds the sync key, so it needs no passphrase: you print the sheet (or write it by
hand), type two of its words back, and only then is it saved. The words wrap the same sync
key the passphrase does (HKDF-SHA256 under its own label, then AES-256-GCM), and that slot
sits beside the passphrase's in sync-key.json. midden keeps no copy of the words.
- Forgot the passphrase: on a device joining the store, a passphrase that doesn't open it leads to Forgot the passphrase?. When the store has a recovery key, its ten words come first: they open the key, you set a new passphrase, and the device joins (the usual join it step). Erasing is still there below it. Devices already connected keep syncing.
- What stops a sheet working: making a new one, removing it, or erasing the store (the key file goes). Changing the passphrase doesn't.
- What it doesn't open: the hoard. The hoard has its own recovery key.
- Checks: the slot is only used from a key file that carries the key's check mark, and the key the words open must match that mark, so a slot copied in from another store opens nothing. A malformed slot is refused, not skipped.
Joining a store with data in it: once the passphrase opens it, midden says what the store holds (files, size, how many devices wrote to it) before this device takes it in, with join it or erase it and start over.
Devices: each device puts a small sealed device-<id>.enc in the store: its name, whether
it's a browser or a phone, and when it last ran. It starts as its browser and system ("Brave
on Linux", "Android phone"), and Settings → Sync → Devices → rename changes it; the
others pick the new name up on their next sync. The list shows only devices with files in
the store. remove… takes another device out of sync: a removed-<id>.enc marker goes up
first, then that device's logs, snapshots and name file go. What it sent is already on the
devices that pulled it, and what's on it stays there. midden warns if this device hasn't
taken in its latest changes yet. If the removed device runs again, it finds the marker,
stops, and says it was removed; connecting it again clears the marker.
Starting over: Settings → Sync → Danger zone → Erase synced data removes every file in the store, the key file first, so each connected device's next run finds no key and stops (above) rather than writing into what's left. A run under way on this device stops between files. This device disconnects; what's on every device stays. A forgotten passphrase leads to the same place from the connect form.
What's stored, and how
| Drive file | What it is |
|---|---|
sync-key.json |
the sync key, wrapped by your passphrase (Argon2id + AES-256-GCM), and the key's check mark (SHA-256 of a label and the key, so a device can recognize its key without the passphrase); the same key wrapped by the recovery key, when you made one; no data |
blob-<sha256>.enc |
each image or file, and each link thumbnail, encrypted, uploaded once; an item's own file is removed once it's deleted for good (a thumbnail's stays) |
hoard-<sha256>.enc |
each of the hoard's pictures, still encrypted by the hoard (its key is inside the item), then by the sync key; uploaded once; removed once only deleted hoard items have it |
log-<browser>-<n>.enc |
one batch of a browser's changes, numbered in order |
device-<id>.enc |
a device's name, kind and when it last ran (Settings → Sync → Devices) |
removed-<id>.enc |
that device was removed from sync on another device: it stops if it runs again |
snapshot-<browser>-<n>.enc |
everything that browser knew at batch n (pins only, not layout), for a browser catching up |
- Each file is AES-256-GCM encrypted, with its own file name bound in as associated data, so files can't be swapped between names without decryption failing.
- Each browser numbers its own files, so two browsers never write the same name.
- A browser writes a snapshot when it connects, after you import a file (what a file adds isn't noted as changes), then about every 100 batches or 7 days. It keeps its newest two, and deletes its batches the older one already covers. A browser that was away longer than that catches up from the snapshot instead.
- The hoard's envelope rides in a batch only when the hoard changed. Its pictures don't ride
in it: each item names its pictures by the hash of their ciphertext, and they go up as
hoard-*.encfiles beforehand. A browser whose hoard lacks one fetches it after pulling, and the hoard takes it only if one of its items (or an offer waiting for your OK) names it. - Transcripts, the text read from pictures and the QR codes found in them travel with the changes, since they're slow to work out again. So does the text read from a link's screenshot, which only search uses. The rest of what midden derives (embeddings, similarity, layout) isn't uploaded: each device rebuilds it.
Security
What protects what:
- Your sync passphrase wraps the sync key (Argon2id, then AES-256-GCM). Every file midden uploads is encrypted with that key on your device first. Google, and anyone who gets into your Google account, sees only ciphertext.
- The scope is
drive.appdata: midden's own hidden app folder. midden can't read or list your other Drive files, and they can't see its folder. - File names are bound in: each file is encrypted with its own name as associated data, so a file renamed or swapped for another fails to decrypt instead of being read as the wrong thing.
What Google can still see:
- how many files there are, their sizes, and when they were written;
- the file names: which device wrote a batch, the batch numbers, and each picture's or file's SHA-256. The hash reveals whether two uploads are the same file, but nothing about what it contains.
What's kept on the device:
- Google's access token lasts about an hour. The extension holds it in
chrome.storage.session, in memory only, never written to disk. It's renewed silently while you're signed in to Google in that browser. The phone gets its token from Play services and holds it in memory for 45 minutes at most. - No client secret exists anywhere: the extension uses the browser's sign-in flow and the phone uses Play services.
- The unwrapped sync key stays in this browser profile (or the phone's app storage), so sync can run in the background without asking for the passphrase. midden's data is stored unencrypted in the same place anyway: the encryption protects the Drive copy, not the device. Someone with your unlocked device has your midden.
Limits, said plainly:
- Changing the passphrase re-wraps the same key; it doesn't re-encrypt what's in Drive. If a passphrase leaked, start over: Settings → Sync → Danger zone → Erase synced data.
- Every device you connected holds the key, and there's no way to take it back from one. To shut out a lost device, start over with a new passphrase: it can't read anything written after that.
- A device's clock decides which of two conflicting edits wins.
- The recovery sheet, with access to your Google account, reads your synced midden. Keep it like a passport. Without it and without the passphrase, the Drive copy can't be read; what's on your devices stays.