> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sente.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Security model

> Where credentials and session state live, who can read them, and what the AI models involved do and don't see.

*Last updated 2026-07-31. This page describes what is actually built today, including the parts
that aren't. Questions: [support@sente.run](mailto:support@sente.run).*

Sente holds two kinds of secrets for you: **account credentials** (password, optional TOTP seed)
and **live session state** (cookies / storage for a logged-in browser). This page explains where
each lives, who can read it, and what the AI models involved do and don't see.

## The core design: your agent never holds the credential

The point of the product is that credentials move **out of your prompts, your `.env`, and your
agent's context** into a server-side vault. Your agent asks Sente for a logged-in session and
receives one of:

* an interactive **live view URL** (human-watchable, take-over capable),
* a **CDP URL** to drive with your own Playwright/Puppeteer,
* an exported **`storageState`** to run locally.

It never receives the password or the TOTP seed. If you [connect an account](/guides/connect), the
credential goes in **write-only**: `GET /credentials` on a connected account returns
`403 CREDENTIALS_WRITE_ONLY`, permanently. Rotation is re-submitting new credentials. **Revoking**
a connection stops all use of it in one call (the vault entry is kept so re-connecting re-enables
it); **deleting** the connection additionally purges the vaulted secrets. See
[Sessions](/guides/sessions) for how session handoff works.

## At rest

* Credentials and TOTP seeds are encrypted with **AES-256-GCM** before they touch the database.
* The encryption key is held only in the API/worker environment on our production host — it is an
  application-level key, **not yet a KMS/HSM-held key** (that upgrade is on the roadmap and we'll
  say so here when it lands, not before).
* For **connected** accounts, only one code path in the system decrypts credentials: the run
  controller, at the moment a login/registration run needs them — the public API never returns
  them. For **Sente-created** accounts, the generated password is retrievable through the API
  (it's your credential; we made it for you), and every read is recorded in the audit log.

## During a run (what the models see)

Two different models touch your data, with different exposure:

1. **The browser-driving agent** (Anthropic Claude, via API). When it must type your password into
   a login form, it receives it — the same way a human assistant would have to. Mitigations:
   the run executes in an **isolated remote browser session** (a dedicated per-identity browser
   profile — persistent across that identity's runs, but never your machine and never shared
   across identities); the password is registered in a **redaction vault** before the run starts, so it is
   scrubbed from logs, step streams, run records, and the activity feed; Anthropic's API does not
   train on this traffic.
2. **The TOTP seed never reaches any model.** When a site asks for an authenticator code, the
   driving agent stops and reports; our server computes the current 30-second code from the vaulted
   seed and injects only that code. Wrong-seed loops are capped at 3 attempts.

Inbound email is treated as **untrusted content**: the model that classifies verification emails
(OTP / magic link / other) runs with a fixed system prompt, no tools, and constrained structured
output — a hostile email can't instruct it to do anything.

## Blast-radius controls

* Per-organization API keys; every identity, registration, and run is org-scoped.
* Per-org caps: identities, outbound sends per day, runs per day — all hard 429s
  (see [Limits](/trust/limits)).
* Webhook URLs pass an SSRF guard (public addresses only, re-checked at every dispatch).
* A global kill switch can pause all runs platform-wide in one operation.
* Every run leaves a full status timeline + activity record you can audit in the dashboard.

## What we don't have yet (read this before trusting us with production)

* **No SOC 2** (yet). Solo-founder company; happy to walk through the posture on a call.
* **No KMS-held keys** (see above).
* **SMS 2FA and CAPTCHAs require a human** — a run that hits one blocks and pages you with an
  interactive live view; Sente never attempts to complete a CAPTCHA. See
  [Runs and human takeover](/concepts/runs-and-human-takeover).
* **SSO-only accounts** (Google/Okta sign-in, passkeys) can't be connected — there's no password
  to vault.
* An exported `storageState` or CDP URL is a **bearer credential**. Treat it like one: it grants
  the session it names, and its safekeeping on your side is yours.

## Our recommendation for the RBAC-minded

Don't connect your root/prod account. Create a **scoped account or token for the agent** in the
target app's own permission system (staging scope, non-destructive prod scope), connect *that* to
Sente, and rotate it on your schedule — re-submitting credentials takes one call and invalidates
nothing else. Your model never sees the secret at any point in that loop; your `.env` stays empty.

Acceptable use: [Acceptable use policy](/trust/acceptable-use). Abuse reports: [support@sente.run](mailto:support@sente.run).
