Skip to content

ThunderCrab — case study

ThunderCrab

ThunderCrab — sharing what it learns, never what it reads

A private-by-design mail client for Android and Linux. It works out how you file your inbox and can pass those rules to other people's copies — which is exactly the feature that would normally leak your mail, so it is built so that it cannot.

Download a build
One core
Rust: IMAP, SMTP and ManageSieve, the rule engine, the store, the federated learning
Two faces
A Jetpack Compose app on Android and an Iced desktop app on Linux, over the same core through UniFFI
Reading path
No HTML engine, no JavaScript, no network — the desktop app renders a message through a native Markdown widget
Connections
Post-quantum hybrid key exchange offered first on every IMAP, SMTP and ManageSieve connection

The feature that should not be safe

Learning how someone sorts their mail means learning about their mail. Sharing that learning between installs is the kind of feature that ends up in a write-up about how a privacy app leaked its users' correspondence, and it usually leaks not because anyone intended it but because a rule grew a field that could hold a fragment of a message, and nobody noticed.

So the guarantee is not a promise in the documentation and not a check in a review checklist. It is a property of the type. A shareable rule is described by an expression with exactly eight shapes: always, this header contains, this header exists, the sender's domain is one of these, the subject contains one of these, and the three ways of combining them. There is no shape for a message body. There is no shape for a full address. Content cannot be expressed, so it cannot be shared, and no amount of careless coding downstream can put it back.

A safety check that enumerates every case, with a comment saying the branch is unreachable and kept anyway — so that adding a ninth shape later forces someone to decide, in writing, whether it is safe to share.

What a rule you receive is allowed to do

  1. 1

    It can only move mail out of your way

    The one sanctioned path into your rule store rejects anything that targets your inbox or your important folder, and anything that sets a flag you use to mark something as mattering — including when those are buried inside a sequence of actions. The net effect is an invariant worth stating plainly: a rule from someone else can file mail away, and can never promote anything into your attention.

  2. 2

    It can never outrank a rule of your own

    Every federated rule's score is clamped below the range local rules use, so your own sorting always wins a disagreement.

  3. 3

    It is signed, and dated only to the day

    Each install signs its submissions with its own key, and stamps them with the day rather than the minute, because a precise timestamp is a correlation handle.

  4. 4

    And the guards are property-tested

    The safety checks are tested against generated inputs, not a handful of cases someone thought of — which is the only way to test a rule about all possible rules.

$ cargo test -p thundercrab-suggestions
running 4 tests
test protected_folders_always_reject ... ok
test protected_in_sequence_rejects_as_nested ... ok
test protected_flags_always_reject ... ok
test applied_rules_are_clamped ... ok
test result: ok. 4 passed; 0 failed

The rest of it is the same instinct

Settings sync with no server

Your accounts and preferences travel in private metadata on your own mailbox, so there is no sync service to trust, breach or shut down.

Read receipts that never answer themselves

A receipt can be requested but is never sent automatically, because an automatic one hands over the fact you read it, when, and from which address.

Secrets in the platform keystore

The account password is sealed by the Android keystore, and push runs in a foreground service so new mail arrives without polling.

Where it actually is

Four interim builds are published and downloadable without an account, and they are debug-signed development builds rather than a store listing — the Android app is real and installable, and it is not finished. The desktop app compiles and runs and has no automated tests of its own; the correctness that matters lives in the shared core, where a hundred and thirty-eight tests pass.

Free software

The builds, and the code under them

Rust core, Kotlin app, Iced desktop client, and the safety module that makes the sharing feature possible to ship at all.

ThunderCrab releases