Cremind
Cremind Connect

The two-plane model

How Cremind Connect separates the authorization plane (your tokens, kept local) from the event plane (content-free nudges relayed in real time) so the relay never needs to hold your data.

Cremind Connect is built around one structural decision: cleanly separate who holds your tokens from who relays your events. These are the authorization plane and the event plane. Understanding them is the fastest way to see why the relay can be useful without ever becoming a custodian of your data.

Authorization plane — the relay is (almost) never in the token path

The authorization plane is where your account access is actually granted. The goal is simple: your tokens are minted and stored on your machine, not on the relay.

Google: loopback PKCE — relay never sees a token

For Google (Gmail and Calendar), the Cremind organization registers one Desktop OAuth client. Your local app drives the flow itself:

  1. It generates a PKCE verifier and challenge plus a single-use nonce.
  2. It opens your system browser to Google's consent screen, using the public client id from Connect's discovery document and a loopback redirect (http://127.0.0.1:<port>).
  3. It catches the authorization code on a loopback listener and exchanges it directly with Google's token endpoint, using the PKCE verifier.

Google supports loopback plus PKCE for Desktop clients and treats the Desktop client secret as non-confidential, so this exchange needs no confidential server. The access token, refresh token, and ID token are stored only on your machine. The relay is never in this path.

Atlassian: confidential 3LO — relay exchanges, then forgets

Atlassian Cloud uses a confidential OAuth 2.0 (3LO) flow: there is no public PKCE, and the client secret is required at the token exchange. Because an end user can't safely hold that secret, the relay mediates the code-to-token exchange (and refresh), holding the secret server-side.

The important part: even though the relay performs the exchange, it hands the tokens straight back to your app and stores nothing. The tokens still live only on your machine. The relay's involvement is transient — it brokers the exchange and forgets.

Two flows, one guarantee

Google and Atlassian differ in how tokens are minted (loopback PKCE versus a relay-mediated confidential exchange), but they share the same outcome: your tokens end up local, and the relay keeps none of them.

Event plane — a token-less relay of content-free nudges

The event plane is how a change at the provider reaches your app in real time. It is built so the relay can route events without ever seeing your content and without any user token.

How a nudge flows

  1. Your local app, using its own token, registers a watch with the provider that points at Connect's organization-owned infrastructure — a shared Pub/Sub topic for Gmail, a domain-verified webhook for Calendar.
  2. When something changes, the provider pushes a notification to the relay. The relay verifies that push (for Gmail, full OIDC verification of Google's signed JWT).
  3. The relay derives a routing key by hashing the account identifier from the payload, then routes to a per-account Durable Object.
  4. That Durable Object broadcasts a content-free nudge — { type: "resync", source } — over WebSocket to every app currently connected for that account.
  5. Each app then performs its own incremental sync locally, with its own token, pulling only the changed surface (the nudge's source tells it whether to sync Gmail, Calendar, and so on).

The nudge carries no email, no event, no issue — just "something changed, go re-sync." The relay never fetches your content, because the fetch always happens on your machine with your token.

Fan-out to every app that linked the account

A routing key is derived deterministically from the account, so a single change can fan out to every app that proved control of that account. If two people independently linked the same shared mailbox, both of their apps get the nudge. There is no per-user mapping stored to make this work — the key comes from the event payload itself.

Subscriptions are access-controlled

Routing by a hash of the account alone would let anyone who knows an email address join its hub. So connecting to the relay requires proof of control: your app presents a Google ID token (openid email) to bootstrap. The relay verifies the signature, audience, expiry, the email_verified claim, and a single-use nonce, and confirms the derived key matches the requested account before issuing a short-lived relay-session token for cheap reconnects. An ID token proves identity but grants no API access — so the relay only ever sees a verifiable identity assertion, transiently, never an access or refresh token.

Who does what

CapabilityWho does itNeeds a user token?Lives on the relay?
Mint tokens (Google)your local appno
Mint tokens (Atlassian)relay-mediated exchangeno — handed back, not stored
Register / renew watchyour local appyes (its own)no
Receive provider pushrelayno (verifies the provider's signed push)
Route / fan out eventsrelayno (key derived from payload)derived, not stored
Fetch the actual changesyour local appyes (its own)no

Why it's stateless at rest

Because routing keys are derived per event and subscriber connections are ephemeral, the relay holds no durable user state. If no app is connected when an event arrives, the nudge is simply dropped — and that's correct: on reconnect, your app re-establishes its watch and does a catch-up incremental sync. Connect is a real-time accelerator, not a durable queue. This self-healing behavior is also why a brief relay outage doesn't lose your data — your app re-syncs from the provider directly.

See Privacy and trust for exactly what the relay can momentarily observe and what it provably never keeps.

On this page