Trust

Agents on a short leash, data on your servers.

SalesOS holds mailbox credentials, messages and contacts, and lets AI agents work with them. This page says what those agents can and cannot do, how the data is protected, and how to report a problem.

The approval model. Agents draft. People decide. The server enforces it.

Agents draft, people send

Over MCP an agent can read, research and draft. Tools that send email are never exposed to it.

Only people approve

Approving, rejecting and changing autonomy policies need a signed-in member. Keys, tokens and MCP tools are refused.

Enforced on the server

Approvals, suppressions and consent are enforced on the server, not by a prompt. An agent can never approve its own request.

How approvals work

Out of reach. What an agent can never touch.

These hold today for your Claude over MCP, for API keys and for OAuth apps.

Sending email over MCP

Tools that send a message are never exposed over MCP, whatever scope a client holds, and a self-registered client is never granted the permission to start a campaign.

Approving or setting policy

Approval decisions and autonomy policies belong to signed-in members only.

Other workspaces

Every read of a workspace’s data is scoped to that workspace, for people and agents alike.

Your cloud keys

Workers hold no cloud credential and never connect to the database. Decryption and file signing are brokered one request at a time.

On the chat channels (merged, not released yet)

Prospect text, wrapped

On the WhatsApp and LinkedIn tools, inbound text arrives wrapped as untrusted content with links neutralised, and can never add recipients, switch senders or export data.

Frozen recipients

An approved channel send goes only to the recipient fixed at request time, or nowhere.

Blocks a member lifts

An agent can block an address on every channel; only a signed-in member can lift that block.

The inherited email tools behave differently today: an agent with the right scope reads email bodies as written, and can change mailbox limits or lift an email suppression. Scope each key and connected app to what it needs.

Encryption. A key per workspace, and only its wrapped copy stored.

Each workspace gets its own 256-bit data key. Only the wrapped copy is stored; the plain key is used briefly and cached for a short time. Mailbox credentials, integration tokens and sensitive payloads are sealed with AES-256-GCM before they are written. On a self-host the root key is your own, held locally or in the key service you choose.

Figure 1. Envelope encryption: the root key wraps a data key per workspace, which seals each sensitive field.

The worker boundary. The machines that send hold no cloud credential and no database access.

Workers sign in to your mailbox providers and nothing more. They never connect to Postgres, hold no cloud credential, and ask the control plane for each decryption or file signature they need.

Figure 2. A worker talks to the event bus, the brokers on the control plane and the mailbox provider, and to nothing else.

Accounts and sign-in. The basics, done properly.

  • Passwords are hashed with Argon2id and checked against a list of known breached passwords.
  • Sign-in, sign-up and password reset can be protected by a CAPTCHA you configure.
  • Two-factor codes can only be used once, and admin routes require a second factor.
  • Changing a password or signing out other sessions ends those sessions everywhere, including live connections.
  • Every token is bound to one purpose and verifies for nothing else.
  • Every API response carries strict security headers, including HSTS and a default-deny content policy.

Your data. It stays where you put it, apart from what you send to AI.

No telemetry

An instance reports nothing to us. Its only outbound call of its own is an optional update check against GitHub releases.

You are the controller

You decide what is collected, how long it is kept and where it lives. Retention windows are settings, with a minimal preset at install.

What leaves for AI

AI features send the text they work on to the model provider you configure (Anthropic by default), and reply labelling sends reply text to its provider. Leave them unset and nothing goes.

Errors without secrets

A server error answers with one fixed sentence and a request id. Secrets, tokens and full connection strings never reach a log line or an error message.

Data control in the docs

Reporting a vulnerability. Tell us privately.

Use private vulnerability reporting on the repository so the report is visible only to the maintainers. Please do not open a public issue for a security problem: every instance that has not updated yet runs the code everyone can read.

What this is not

This page is not a certification. SalesOS claims no SOC 2, ISO 27001 or similar audit, and it is not GDPR compliant out of the box: as the operator you are the controller, and the software gives you settings and defaults that help.

Audit it, then run it.

Every line that touches your data is in the public repository. Read it, then install it on a server you control.