01 · Your Data
Your data, handled honestly.
"Your data is safe" is what every company says. Here's the exact lifecycle of a conversation export from the moment you upload it, with specifics, not vague reassurance.
The full lifecycle
Four steps, each designed to minimize what we touch and what we keep.
Upload in the browser
ZIP parsed within browser boundaries, size-capped, scanned for ZIP-bomb patterns before a byte touches our server.
Sensitive-content filter
Conversations run through a filter that strips API keys, access tokens, email addresses, phone numbers, and obvious personal identifiers before analysis.
Stratified sampling
We bucket conversations into biweekly windows and round-robin sample a representative corpus capped at ~90 KB. So big uploads don't get analyzed as only their most recent weeks.
Score, then expire
The sampled corpus is scored against the current rubric, retained for 90 days so we can re-score when the rubric improves, then auto-deleted.
What we keep, and what we don't
The single most honest thing we can tell you is exactly what's stored and exactly what isn't. Here it is.
What we keep
A small, filtered corpus for 90 days
- ≤ 90 KB of sampled, filtered conversation snippets per user
- Your scores and progression history
- Metadata about your upload (conversation count, date range)
- Encrypted integration tokens (AES-256-GCM)
What we never store
Raw conversation history
- Your full ChatGPT or Claude chat history
- Unfiltered content containing secrets, keys, or identifiable data
- Raw IP addresses, page views store hashed IPs only
- Passwords in plaintext, bcrypt (12 rounds), OAuth preferred
One-click deletion
A delete control is wired into your Settings page. One click purges the stored corpus. Your scores stay, the underlying text is gone.
Technical safeguards, briefly
The specifics behind the promises above.
Encryption & token handling
GitHub tokens and n8n API keys are encrypted at rest with AES-256-GCM. From an n8n workflow file we never keep saved logins or sample data, and any key pasted into a step is dropped before we keep anything. JWTs are signed with a required secret and expire after 30 days. OAuth callbacks issue a one-time exchange code rather than putting the token in a redirect URL.
Upload protection
ZIP uploads enforce entry-count limits (100 entries), uncompressed-size limits (100 MB), and compression-ratio checks (greater than 100x rejected) to block zip-bomb attacks. File MIME types are validated server-side.
Privacy-preserving analytics
Portfolio views store SHA-hashed IPs, not raw addresses. Dedup happens on the hash, so we can count unique viewers without being able to identify them individually.
Abuse protection
Rate limiters are scoped per route family, auth, AI analysis, and everything else, so analysis endpoints can't be swamped without affecting login. Emails are normalized to lowercase so case variations can't create duplicate accounts.