Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
61986a3
docs: encrypted cloud sync (E2E) design spec (#520)
ericgriffin Jul 10, 2026
6fad1bd
docs: encrypted cloud sync implementation plan + cryptography deps (#…
ericgriffin Jul 10, 2026
fa4ca19
feat(sync): SBE1 encrypted envelope with python-generated KAT vectors…
ericgriffin Jul 10, 2026
84f1f72
feat(sync): keyslot file with Argon2id passphrase/recovery wrapping (…
ericgriffin Jul 10, 2026
1d8ae4c
feat(sync): recovery code generation on the EFF short wordlist (#520)
ericgriffin Jul 10, 2026
a67d62c
feat(sync): local key custody, keyslot mirror, encryption preference …
ericgriffin Jul 10, 2026
994ece0
feat(sync): encrypting cloud storage decorator (#520)
ericgriffin Jul 10, 2026
ecf144d
feat(sync): awaitingPassphrase halt for encrypted libraries (#520)
ericgriffin Jul 10, 2026
7962986
feat(sync): encryption lifecycle service - enable, unlock, rotate slo…
ericgriffin Jul 10, 2026
344eeb9
feat(sync): riverpod wiring for encryption session and provider wrap …
ericgriffin Jul 10, 2026
50014ff
feat(backup): framed self-decrypting .sbe backup encryption (#520)
ericgriffin Jul 10, 2026
99940b1
feat(backup): encrypted cloud backup upload, restore, plaintext clean…
ericgriffin Jul 10, 2026
a39592f
test(backup): update restore-service doubles for the encryptionSecret…
ericgriffin Jul 10, 2026
30da9be
test(sync): no-plaintext-leak invariant and encrypted two-device conv…
ericgriffin Jul 10, 2026
6afdf1e
feat(settings): end-to-end encryption section with enable and manage …
ericgriffin Jul 10, 2026
1823276
feat(sync): unlock banner, troubleshoot status, encrypted restore pro…
ericgriffin Jul 10, 2026
09c56d3
l10n: translate sync encryption strings into all locales (#520)
ericgriffin Jul 10, 2026
2fa8031
fix(sync): address PR #548 review + raise patch coverage to 97% (#520)
ericgriffin Jul 10, 2026
960d133
docs: v1.6.1.115 release notes for encrypted cloud sync (#520)
ericgriffin Jul 11, 2026
fad12de
fix(sync): address PR #548 re-review comments (#520)
ericgriffin Jul 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions docs/releases/v1.6.1.115.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 🎉 Submersion v1.6.1.115 Release Notes

This release adds optional end-to-end encryption for cloud sync and cloud backups. Submersion's sync has always used storage you control — iCloud or an S3-compatible bucket — with no Submersion server in the middle, but until now your storage provider could still read what you uploaded: dive sites and their GPS coordinates, buddy names, certifications, and notes. Turn encryption on and Submersion encrypts everything it writes to the cloud on your device first, so the provider only ever sees opaque blobs.

---

## ✨ New and improved

### Optional end-to-end encryption for cloud sync and backups

A new **End-to-end encryption** section under Settings → Cloud Sync lets you lock your cloud library behind a passphrase that never leaves your devices. You set it up on one device: choose a passphrase, save the eight-word recovery code Submersion shows you, and it re-uploads your whole library in encrypted form. From then on every sync — and every backup uploaded to your cloud storage — is encrypted before it leaves the device, using AES-256 with a key derived from your passphrase. Your storage provider, or anyone who gets hold of your storage credentials, sees only unreadable files.

Encryption is opt-in and off by default, and it protects the contents of your files rather than their existence: file names, sizes, and timestamps remain visible to the provider, so a private bucket and a tightly scoped access token are still worth keeping. The dive log on each of your devices is never encrypted by this feature, so you never type a passphrase just to open the app or read your own dives — only what leaves the device for the cloud is protected.

Each device is unlocked once. When another device syncs to an encrypted library, sync pauses and the Cloud Sync page shows an "Enter passphrase" banner; enter the passphrase (or the recovery code) and that device unlocks the library, downloads it, and syncs normally from then on, remembering the key in its secure keychain. You can change your passphrase at any time without re-uploading your library, generate a fresh recovery code if you misplace the old one, or turn encryption back off to return to plaintext sync. Because Submersion never stores the recovery code itself, it cannot show it to you later — if it is lost, you generate a new one.

Turning encryption on republishes the cloud library in a form older app versions cannot read, so update Submersion on all of your devices to this version before — or soon after — enabling it. A device left on an older version simply stops syncing with an error rather than losing or damaging anything, until you update it.

Losing both your passphrase and recovery code does not mean losing your dives. Because the library on each device is never encrypted, any device that already has your data still has all of it; you re-publish from that device (turning encryption off, or on again with a new passphrase) and your other devices adopt the new library. The only thing lost is the old cloud copy, which was unreadable anyway.

### Encrypted cloud backups

Cloud backups are covered by the same setting. While encryption is on, each backup uploaded to your cloud storage is encrypted with your passphrase and is self-contained: you can restore it on a brand-new device by entering the passphrase or recovery code, even before sync is configured there, and Submersion prompts for it automatically when the backup it is opening is encrypted. Backups you save to a local folder, a connected drive, or the share sheet stay unencrypted on purpose — a backup is your safety net and should never be locked behind a passphrase you might forget.

---

## 🔧 Under the hood

Encryption is implemented as a layer around the existing storage backends rather than a change to the sync protocol, so every sync file becomes ciphertext by construction and the merge logic is untouched. It uses Argon2id to derive keys from your passphrase and recovery code, HKDF and AES-256-GCM (which detects tampering as well as preventing reading) for the data itself, and a wrapped-key design so that changing your passphrase re-wraps the library key instantly instead of re-encrypting your whole logbook. Enabling and disabling encryption reuse the same library-replacement mechanism that a "Replace everywhere" restore already uses, which is why other devices adopt the change the same familiar way. No database migration is required, and all new interface text is translated into all ten supported languages.
Loading