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

# Security architecture

> How the SmartAlex platform is put together from a security point of view: trust boundaries, tenant isolation, secrets handling, staff access, change approval, and signed messages between services.

This page shows how the platform is protected, with a diagram for each part. It describes what each control does, not how it is built. Suppliers are named by the job they do; the [sub-processor list](https://docs.getsmartalex.com/trust/subprocessors.md) names the categories and regions.

## Trust boundaries

Every request crosses the same boundaries. Traffic is encrypted between each hop. A request from your team is checked for a signed-in user and a workspace, a message between our own services is checked for a valid signature, and the database itself refuses rows that belong to another workspace.

```mermaid theme={null}
flowchart LR
    U["Your team<br/>web app and mobile app"] -->|"encrypted"| E["Edge network"]
    C["Callers<br/>phone and web"] -->|"encrypted"| V["Voice engine"]
    E --> A["Application services"]
    V --> A
    A -->|"workspace checked"| D[("Database<br/>row-level isolation")]
    A --> S[("File storage<br/>recordings and documents")]
    A --> K[("Encrypted secrets vault")]
    V --> P["AI providers<br/>speech and language"]
    A --> P
```

## Tenant isolation

Each customer is a workspace. Isolation is enforced twice: the application checks that the signed-in user belongs to the workspace named in a request, and the database applies row-level security so a query can only ever return that workspace's rows. A mistake in the application layer still cannot return another customer's rows. Recordings in file storage are protected by the same per-workspace access rules.

```mermaid theme={null}
flowchart TB
    R["Request from a signed-in user"] --> W{"Member of this<br/>workspace?"}
    W -->|"no"| X["Refused"]
    W -->|"yes"| Q["Query"]
    Q --> RLS{"Database row-level<br/>security"}
    RLS --> T1[("Workspace A rows")]
    RLS -. "never returned" .-> T2[("Workspace B rows")]
```

## Secrets and environments

* Credentials you connect, such as messaging tokens and calendar or email sign-ins, are stored in an encrypted vault. The ordinary database row holds only a marker, so a copy of the database alone does not reveal them.
* Platform secrets are never kept in source code or written to logs. They are injected into the running service at deploy time.
* Production and test environments are separate. Production credentials and customer data never flow into test or development, and test data is synthetic.

```mermaid theme={null}
flowchart LR
    You["You connect an account"] --> App["Application"]
    App -->|"secret"| Vault[("Encrypted vault")]
    App -->|"marker only"| DB[("Database row")]
    Vault -->|"read at the moment of use"| Svc["Service that needs it"]
```

## Staff access and step-up sign-in

Our own staff follow least privilege. Production access is limited to a small set of named people, and every platform administrator must have two-factor authentication.

* **Step-up for cross-workspace actions.** An administrator acting outside their own workspace must have completed a second factor in the current session. A password-only session is refused, even for an administrator.
* **Staff reads are logged.** When a platform administrator opens a recording, a transcript, a contact or an export for a workspace they are not a member of, the access is written to a log first. If the log entry cannot be written, the recording is not opened.

```mermaid theme={null}
sequenceDiagram
    participant Admin as Platform administrator
    participant App as Application
    participant Log as Staff access log
    Admin->>App: Open a recording in another workspace
    App->>App: Second factor completed this session?
    alt Password only
        App-->>Admin: Refused, complete two-factor first
    else Second factor done
        App->>Log: Record who, what and when
        Log-->>App: Written
        App-->>Admin: Short-lived link to the recording
    end
```

## Audit trail

Changes to agents, knowledge bases, phone numbers, team members, roles, permissions and workspace settings are recorded in an append-only audit log with the person who made them and when. Workspace owners can review their own log in the app.

## Approval before an agent change goes live

A workspace owner can switch on **Approve agent changes**. From then on, an edit to an agent's instructions or settings is saved as a draft and does not reach callers until a second person approves it. The person who made the edit cannot approve their own change, and every step is written to the audit log.

```mermaid theme={null}
flowchart LR
    Edit["Someone edits<br/>an agent"] --> Draft["Saved as<br/>a draft"]
    Draft --> Rev{"A second<br/>person reviews"}
    Rev -->|"approve"| Live["Live for callers"]
    Rev -->|"reject"| Back["Nothing changes"]
```

## Signed messages

* **Between our services.** Messages from the voice engine to the rest of the platform, such as a tool call during a call or the report when a call ends, are signed and checked. An unsigned or altered message is refused.
* **From us to you.** When an agent calls your own systems through an HTTP tool, the request is signed so your endpoint can prove it came from us. See [Signature verification](https://docs.getsmartalex.com/guides/http-tools/signature-verification.md).

```mermaid theme={null}
sequenceDiagram
    participant Sender as Sending service
    participant Receiver as Receiving endpoint
    Sender->>Sender: Sign the message body with a shared secret
    Sender->>Receiver: Message and signature
    Receiver->>Receiver: Recompute and compare
    alt Signature matches
        Receiver-->>Sender: Accepted
    else Missing or altered
        Receiver-->>Sender: Refused
    end
```

## Browser protections

Our web origins use HTTPS only, with HTTP Strict Transport Security. A strict content security policy, which limits the scripts a page may run, is in **report-only** mode: browsers report anything it would block, and we will switch it to enforcing once those reports are clean.

## Related pages

> [card] [Trust & Security](https://docs.getsmartalex.com/security.md)
>
> The summary, with the status of each safeguard.

> [card] [Data lifecycle](https://docs.getsmartalex.com/trust/data-lifecycle.md)
>
> What happens to call data, from the call to deletion.

> [card] [MCP security and permissions](https://docs.getsmartalex.com/mcp/security-and-permissions.md)
>
> How AI assistants connected through MCP are scoped.

> [card] [Telephony security](https://docs.getsmartalex.com/telephony/security-compliance.md)
>
> Security and compliance for phone numbers and calling.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.