Nerd stuff

Fortune Cookie

We host the cookie. We cannot read the fortune.

A message goes in, a sealed cookie comes out, and someone cracks it open in three taps. The interesting engineering is that every party — including us — knows exactly as much as they need to, and not a byte more.

React 19WebCrypto AES-GCM 256Firestore (ciphertext-only)FastAPI (Python)Claude API (structured output)Cloud Run

§Encrypted before it leaves the browser

The fortune is encrypted client-side with AES-GCM 256; Firestore stores only a blob, an IV and an expiry. The document id and the key travel together in the share link's #fragment, which never reaches a server. The database rules enforce the contract mechanically: a TTL of at most 7 days is mandatory, blobs are size-capped, expired cookies are unreadable even before cleanup, and nothing can ever be updated — only created, read once, and burned.

§The baker is one AI call with two jobs

The rewrite and the moderation are a single structured-output request: the model returns either {ok, cookie} or a refusal — in fortune-cookie style, in the sender's language, never echoing the original. Group hatred and advertising are refused; teasing between friends passes, because humor is half the cookie. Self-written fortunes skip the rewrite but pass the same gate in a check-only mode. A hard regex filter blocks URLs, prices and phone numbers before a single token is spent.

§Three taps, then fire

The cookie burns after the third tap, not on page load — deliberately. Messaging apps prefetch links for previews; a burn-on-load design would let WhatsApp's link preview eat the cookie before the recipient ever saw it. Requiring human interaction makes the preview bots harmless. After the reveal the blob is deleted; the same link then shows crumbs.

§What each party knows

The server knows: a random id, an unreadable blob, an expiry. The baker briefly sees the plaintext message (transient, unlogged) and forgets it. The recipient sees the fortune and a footnote that the sender wrote it. We see aggregate counters — baked, cracked — and nothing else. The paranoid path even works with the baker offline: write the fortune yourself and only ciphertext ever exists outside your browser.

§The flow

plaintext, transientciphertextciphertext#id.keySenderwrites + sealsBakerClaude · Cloud RunFirestoreblob + iv · TTL ≤ 7dRecipient3 taps → burn

← Back to rm-worx.be

This website uses minimal technical storage (cookies and local storage) to ensure proper functioning and simple visit statistics. By continuing to browse, you agree to this. See our Cookie Policy and Privacy Policy.