What happens to your data, with the receipts.

Five claims about how Outsample handles customer data, each stated only as far as the code and tests in the repository support it. The file paths and test names sit next to each claim so you can check them, not take them on faith.


tenant isolation

One tenant cannot read or write another tenant's rows.

Every table that holds customer data carries row-level security, enforced by the database itself. The API talks to Postgres as an unprivileged role that cannot bypass those policies. A standing isolation gate runs as that same role, not as an administrator, and proves the boundary from the outside: cross-tenant reads return zero rows, cross-tenant writes touch zero rows, and requesting another tenant's resource returns 404, never a revealing 403.

The gate is a 142-cell matrix covering database reads and writes, API-level access with real sessions, uploads, derived artifacts, billing rows, and account deletion. It is a committed, re-runnable regression asset, and it re-runs whenever the schema or a tenant-touching code path changes. The latest committed run: 142 of 142 cells pass, verdict G-ISO GREEN.

storage

Uploads are private objects with server-derived keys.

Uploaded PDFs are stored as private objects in an R2 bucket; no object is ever written with a public ACL. Keys are derived on the server as tenant/<id>/<sha256>.pdf, never from request input, so a tenant's requests can only construct keys under its own prefix.

Serving is license-gated. The PDF endpoint returns your own uploads on a strict tenant match. A corpus paper you did not upload is served only when its redistribution tier is Open; restricted, unknown, or unset tiers return 404. Fail-closed, and 404 rather than 403, so the response never confirms what exists.

deletion and retention

Deletion is a staged purge, and we say what stays.

Today the deletion path is operated by us: an admin-triggered endpoint, run on request. A self-serve flow in Settings calls the same functions and ships before public launch.

Requesting deletion starts a 7-day window. API keys are revoked, sessions are revoked, the Stripe subscription is cancelled, and sign-in is blocked for the whole window; within it, the deletion can still be cancelled. After the window, a staged purge deletes stored objects before database rows, sweeps the storage prefix for orphaned objects the database cannot name, deletes the SuperTokens user record, and ends by deleting the tenant row itself. Each stage is idempotent and records its own evidence, so an interrupted purge resumes rather than restarts.

What stays: the Stripe customer and its invoice records, which we are legally required to retain for tax and accounting. Nothing else survives the purge.

model providers

Every AI request carries a no-retention directive.

We direct no-retention on every AI request: all requests carry OpenRouter's data_collection: deny directive, which restricts routing to provider endpoints that do not store or train on prompts. Your queries and documents are processed by Anthropic models under their API data policy, which does not use API content for training.

The scope of that claim, precisely: the directive is a routing restriction enforced by OpenRouter against its classification of provider data policies, not a per-request guarantee of what a provider retains. Anthropic's standard API policy holds content for a bounded abuse-monitoring window, which is why this page says no-retention directive and not zero retention.

The directive defaults on, and it cannot be bypassed by a new code path: a test fails if any code calls the model SDK outside the one wrapped client, and another fails if the default ever flips off.

error tracking and analytics

Errors are scrubbed, and analytics never carry your queries.

Error reports go to Sentry through a scrubbing hook that runs before anything leaves the app. Request bodies, query strings, cookies, and environment data are dropped; emails, API keys, and token-shaped values are redacted by pattern; and a test asserts that a sample research query never survives serialization into an event.

Product analytics run server-side to an EU-hosted PostHog instance. The page loads no third-party analytics script: events post to our own origin, and the server keeps a whitelist of allowed property keys and drops everything else. The event schema has no field for query text, so your questions are structurally not part of any analytics event.


How the product itself behaves, including where it fails, is on the methodology page with three real runs and their raw output.