Automation you control, by construction.
Twin Browser is hardened at every layer — authenticated execution you direct call by call, database-enforced tenant isolation, hashed keys, an encrypted credential vault, and a complete audit log. Control isn't a policy here; it's the architecture.
Six layers between a goal and an action.
Each control is independent and fails safe — an invalid key, an unreachable credential store, or an unreachable target all stop the run rather than guess.
You direct every run
Nothing runs that you did not ask for. Each call is authenticated with your API key and acts on exactly the target URL you provide — the URL you pass is the instruction. There is no autonomous crawling and no action you did not initiate.
You hold the authorization
You target only the sites you own or are authorized to automate — that responsibility stays with you, where it belongs. Every run stamps the target it acted on into the record, so there is always a clear trail of what was done, and where.
Default-deny RLS isolation
Tenancy is enforced in the database, not just the app. Postgres Row-Level-Security scopes every row to its owner with default-deny policies, so one tenant can never read or drive another tenant's keys, skills, secrets, or run history.
Hashed, per-tenant API keys
The raw API key is shown exactly once, at creation. We store only a hash and metadata — a leaked database never yields a usable key, and revocation fails closed.
Audit log on every call
Every run records its goal, the path taken, the success condition, and the target it acted on. The result is an auditable trail of exactly what each agent did, on which target, and under which key.
Shared skill library — sanitized
When a task succeeds, its sanitized navigation skeleton joins a cross-tenant library so everyone automating the same host compiles faster. Only the structure crosses tenants — host and which UI elements were used. Your field values, credentials, results, and free-text are stripped first, and only your own tenant ever replays your exact path.
Secrets your model never sees.
Store a credential once; reference it by name. Twin fills the value at the keystroke, inside the browser, on your own runs — it never reaches the model, the logs, the audit record, or the shared corpus.
# Store a credential once — the value goes to the encrypted vault.
curl -X POST https://twin-browser.com/api/v1/secrets \
-H "Authorization: Bearer ab_live_…" -H "Content-Type: application/json" \
-d '{ "name": "acme_password", "value": "•••••••••" }'
# Reference it by name in a run — Twin fills it at the keystroke,
# inside the browser, on your own run only.
curl -X POST https://twin-browser.com/api/v1/run \
-H "Authorization: Bearer ab_live_…" -H "Content-Type: application/json" \
-d '{ "url": "https://app.acme.com/login",
"prompt": "sign in", "secrets": ["acme_password"] }'
# The value never reaches the model, the logs, the audit record,
# or the shared corpus. Only the reference name is ever stored.The target URL is the authorization.
Twin runs exactly the URL you pass and audits the call. Authorization stays with you, the caller — you target only the sites you own or are authorized to automate. Twin is not a CAPTCHA-bypass or anti-bot-evasion service.
Authorized use, plainly
First-party apps, operator-approved automation, internal RPA, accessibility, and authorized testing. Auth, billing, and audit logging run on every call. See the acceptable-use policy for the full boundary.
What's enforced, and how it fails safe
Each layer is independent. When something is wrong — an invalid key, an unreachable vault, a cross-tenant read — the system stops or returns nothing rather than guessing.
| Layer | Control | How it fails safe |
|---|---|---|
| Tenant isolation | Postgres default-deny Row-Level-Security on every table | A cross-tenant read returns nothing — isolation is in the database, not the app. |
| API keys | Per-tenant keys, shown once, stored only as a hash | A leaked database yields no usable key; revocation fails closed. |
| Credentials | Encrypted vault, referenced by name, filled at run time | The value is never returned, logged, or added to the shared corpus. |
| Audit | Append-only log on every call | Every run is attributable to a key and the exact target it acted on. |
| Authorization | The target URL is the authorization signal | The run records the target; authorization stays with you, the caller. |
| Data handling | Field values stripped before anything crosses tenants | Only the sanitized navigation structure is ever shared. |
Security, answered
How is one tenant isolated from another?
Do my credentials ever reach the model?
What is the authorization model?
What gets logged on each call?
What crosses tenants in the shared skill library?
Related policies & capabilities
Built for authenticated execution.
Every run is authenticated to a tenant and directed by you. Every key is scoped. Every action is logged. Security by architecture, not by policy.