Introduction
Security
When you add Rough to your app, you choose what Features can do with it. This page explains how Features run, how they access your data, and what you need to check in your integration.
If you're reviewing Rough for your company and need more detail, please get in touch.
Features run separately from your app
Each Rough Feature runs in an iframe served from a different origin to your app. The browser keeps the two separate, so a Feature cannot directly read your app's cookies or browser storage, or inspect and change the rest of your page.
To work with your app, a Feature sends requests through a bridge provided by the SDK. That bridge makes the capabilities you've defined for its Surface available to the Feature.
For example, if you provide a capability that reads a list of tasks, a Feature can use it to display those tasks. That doesn't also give it a way to delete them. You would need to provide a separate capability for that.
Your app still checks permissions
You write the code behind each capability. It runs in your app, using your existing session and backend. Rough passes the request along; your app is responsible for deciding whether to allow it.
If a user isn't allowed to delete a task in your app, your backend should also reject an attempt to delete it through a Rough Feature. Don't skip permission checks because a request came from Rough, and don't rely on hiding a button to prevent an action.
You describe each capability's inputs and outputs using Zod schemas. The bridge checks requests and responses against those schemas, helping catch invalid data. These checks don't replace authorisation: a valid task ID can still refer to a task the user shouldn't have access to.
Users sign in through your app
Your users don't need a separate Rough login. Your server checks their existing session and signs a short-lived token, which the SDK exchanges for a Rough session.
Keep the private signing key on your server. The user and account IDs in the token should come from your authenticated session, not from values supplied by the browser. Rough trusts the identity your server provides.
The getting started guide shows how to set this up, including how to choose which users share Features.
What data Rough receives
When you define a Surface, Rough receives the capability descriptions, schemas and sample data so it can build Features that work with your app. Your capability implementation code stays in your app. Builder previews use the samples rather than calling your live implementations, so use made-up values instead of real customer data.
Once a Feature is running in your app, it receives the data your capabilities return. Only return the fields the Feature needs and the current user is allowed to see. For example, a customer list doesn't need to include billing details just because they're part of the same database record.
Rough also stores information needed to build and manage Features, including Feature definitions and generated build files. Our privacy policy explains how we handle this information and how long we keep it.
AI providers
We use third-party AI providers to build Features. Prompts and relevant context provided to the Builder may be sent to those providers. Our privacy policy says we do not permit them to use your data to train their models, and we select providers whose terms reflect that commitment.
If you need the current list of providers or have specific requirements for what you can send to them, contact us.
Saved Feature data
By default, the SDK saves a Feature's application state in your app's browser local storage. This storage is keyed by Feature ID, not by user or account. Someone switching accounts in the same browser can therefore see state saved for that same Feature by the previous user.
If you need user-specific or account-specific storage, provide a custom state storage adapter. This is separate from Rough's Feature metadata, which is scoped to the workspace, project and user/account access. See the SDK reference for the storage options.
Before you ship
A few things are worth checking in your integration:
- Check permissions on your backend for every capability, including reads.
- Only expose the data and actions you want Features to use.
- Validate inputs and add rate limits where needed, as you would for other requests to your backend.
- Keep signing keys on the server and use made-up data for preview samples.
- Choose state storage that matches how your users share Features and devices.
If you need information about security assessments, compliance or data residency, ask us. We can discuss your requirements rather than leave you guessing about what we support.