Text2Store

Developer notes

AI summaries without surveillance

We shipped the privacy-purist design (on-device Apple Intelligence plus bring-your-own-key) and killed it within days. What replaced it earns the privacy story differently: a hold-nothing relay, per-action consent, and contractual zero retention.

An app that holds ten years of someone's private messages and an AI feature are natural enemies. Summarizing a 40,000-message custody thread is genuinely useful; sending that thread anywhere is exactly what this product promises not to do casually. We shipped four different answers to that tension in ten days, and the order we abandoned them in surprised us. This is the design record.

Version one: respect every privacy posture

The first shipped design was a ladder. On-device Apple Intelligence as the default on capable Macs: free compute, nothing leaves the machine, the purist's answer. Bring-your-own-key for everyone else: paste an Anthropic or OpenAI key, or point at a local server like Ollama, and summaries run under your own account and your own trust decisions. It felt principled. Every user type had a lane.

What killed the principled version

Two collisions with reality, honestly recorded at the time:

  • Nobody wants to paste an API key. BYOK is a developer fantasy about what normal people will do. Our buyers are managing custody disputes and estates, not provisioning API credentials. The lane existed; it was empty.
  • On-device was a bundled Swift sidecar and a pile of engine-picker UI serving a niche subset of Macs. The commit that removed it says it plainly. Apple Intelligence requires the newest hardware; our demographic's real machines are OptiPlex-class Windows desktops and several-year-old Macs. The privacy-ideal engine was unavailable to most of the people the privacy mattered for, and Windows got nothing at all.

So both privacy-flattering options died, within days of each other. What replaced them had to earn the privacy story a different way.

The managed design: hold nothing, prove it structurally

Summaries now run through the same Cloudflare Worker that handles licensing: the app asks with its device token, the Worker calls the model with our credentials, streams the result back, and stores nothing. Not "we promise not to look": the Worker has no storage for message content and logs error classes only, so the subpoena answer is that we architecturally cannot produce your messages. Consent is per-action: every summary names what is about to leave the machine and where it goes, and nothing is sent until you say so.

The economics were designed before the feature: the subscription price was set partly to fund it, summaries are metered by monthly credits carried in the signed entitlement, the Worker caps input size, and a refunded account loses inference on the next request. Three independent ceilings between an abuser and our bill.

The provider journey, including the dead end

The wire protocol is provider-agnostic (the app speaks one message shape; the Worker translates server-side, so switching providers is a database flag, not an app release). The provider itself moved twice, both times for the same reason: retention posture.

  • We asked OpenAI about zero data retention and the request died in an enterprise sales funnel. Nothing against the models; a solo developer cannot ship a privacy promise on a contract he cannot get.
  • Google's Vertex AI offered the opposite experience: a formal opt-out of abuse-monitoring retention, approved in days, yielding unconditional zero retention on Gemini. That approval, more than any benchmark, chose the provider. Summaries run on Gemini Flash Lite today, and the AI's terms are disclosed in the app and the help page in plain words.

The lesson we keep relearning

The privacy-maximal architecture and the actually-private product turned out to be different things. On-device and BYOK optimized for a user who mostly does not exist, at the cost of the ones who do. What users needed was a feature that works on their real hardware, asks permission in plain words every time, and is backed by a retention contract and an architecture that cannot betray them quietly. Field note: the first real stress test summarized an 84,000-message thread in one go. It worked, and it consumed a month of credits doing it, which is its own honest data point about where the limits are.