Data & masking
The page to forward to your security reviewer. Everything here describes the system as built; the drafts it links to are cross-checked against the code.
Collected
- Semantic events: label, role, selector, section, parametrized route, timestamp, count. "Clicked Save changes (button) in Billing on
/settings/:id", nothing rawer. - Friction events: rage clicks, dead clicks, JS-error clicks, each tied to its target element.
- State probes on friction only: masked visible error text, spinner/empty/disabled flags, nearest heading text (masked).
- Session references: a random per-tab session ID; a person reference only if you call
identify(). - Release stamps: the
buildIdyou configure.
Never collected
- Input values (always
[masked]before transport). - Screenshots, session video, pixel or DOM recording, raw HTML.
- Mouse-movement or scroll streams.
- Third-party cookies; there is no cross-site tracking of any kind.
The optional visual_probe (a sampled frame on opted-in ambiguous
issues) is off by default, hard-capped, and never part of the
default path.
Masked, twice
The SDK masks in the browser
(emails, phones, cards, SSNs, long digit runs, sensitive keys,
data-sonder-mask subtrees), and the ingest collector applies the same
rules again server-side before storage, so a stale SDK can't smuggle PII in. It also
rejects raw-HTML payloads.
<!-- Everything inside a data-sonder-mask subtree reports [masked] as its
label, and its text never appears in state probes. -->
<section data-sonder-mask>
<h2>Account balance</h2>
<p>$12,340.55</p>
<button>Withdraw</button> <!-- captured as: click "[masked]" (button) -->
</section>
<!-- Give an unstable or icon-only control a stable, human name. -->
<button data-sonder-name="Close checkout">×</button>
Storage, retention, deletion
- Raw masked events: ClickHouse Cloud (GCP us-east1), 90-day default retention, configurable per workspace, enforced by an audited purge job.
- Control plane and issue registry: Supabase Postgres (East US) with per-workspace row-level security.
- Delete by person: owners can purge one person's data; derived records delete immediately with an audit record, residual raw events age out within the retention window (at most 90 days).
- All US-region during beta; EU residency is roadmap, stated plainly.
The LLM step
Diagnosis sends masked, aggregated friction ribbons to the DeepSeek API, once per issue, not per session. No input values, no screenshots. The endpoint is configurable if you need to bring your own model. We flag this provider by name on the security page so you can weigh it.
Documents
Security overview · privacy policy (draft) · DPA template (draft). Drafts are watermarked pending counsel review, and every claim in them is cross-checked against the code; discrepancies live in a public mismatch log rather than being papered over.