Your data¶
What bench stores, who can read it, and how to get rid of it. Short, because the honest answer is short.
What's stored¶
Everything you produce in the app, tied to your user id:
- Attempts — code, phase notes, timings, whether tests passed, confidence
- Content progress — what you read or watched, when, and recitation history
- Assessment and skill scores, readiness, JD analyses, credential runs
- Reflections, decisions, writing drafts
- Mira sessions and messages
- Settings — display name, time zone, review voice, accessibility toggles
- Feedback you submit
- Cached read-aloud audio (
tts_cache) — generated speech, so a chapter is synthesised once rather than on every visit. Your own voice recordings are not stored; they are transcribed and discarded.
Authentication is GitHub OAuth via Supabase. Bench never sees your GitHub password, and there is no password for bench itself to leak.
Who can read it¶
Only you. Two independent layers, on purpose:
- Application layer — every serve route filters on the requesting user's id. A route that forgets is a bug, which is why there is a second layer.
- Database layer — row-level security is enabled on all 36 tables in the
publicschema, with owner-scoped policies. Even a query that forgot itsWHERE user_id =clause returns nothing for another user's rows.
The five tables without per-row policies (news_items, feed_health,
kb_documents, kb_chunks, schema_migrations) hold no per-user data and are
deny-all to signed-in roles — they are reachable only by the server itself.
The operator (Li) has database access, as the operator of any self-hosted tool does. There is no analytics vendor, no session-replay tool, and no third-party script on the page.
What is sent to third parties¶
- Model providers — only for the surfaces listed in AI in the bench, and only that call's inputs.
- Sentry — error reports when something breaks. Stack traces and request metadata, not your attempt contents.
- Resend — transactional email to the operator when you submit an access request.
That is the complete list. No advertising, no data brokers, no "partners".
Deleting your account¶
/settings/delete-account — it is a real delete, not a soft flag.
You have to type DELETE MY ACCOUNT exactly, and the server re-checks that
phrase rather than trusting the form, so a crafted POST can't skip the gate.
The deletion runs as a single transaction across 12 user-scoped tables plus
your public.users row, so a failure part-way through cannot leave you with
attempts wiped and writings intact. Tables that reference your user row with
ON DELETE CASCADE — cached audio among them — go with it.
Two honest caveats:
- Your Supabase
auth.usersrow survives. That is the auth provider's table, not bench's, and bench does not mutate it. Signing in again with the same GitHub identity produces a clean account that goes through onboarding as new — but the identity record itself persists until removed at the Supabase level. Ask the operator if you want that too. - Backups. The database is backed up daily. Deleted rows leave live tables immediately and age out of backups on the retention schedule.
If you want everything gone rather than reset, /settings/reset clears
progress while keeping the account.
Export¶
There isn't one yet. If you want your data out, ask — it's a query, not a project, and if more than one person asks it becomes a feature.
Related¶
- AI in the bench
- Settings
SECURITY.md— the threat model