Security

Who can see your deals, and what enforces it

Your mailbox content, your client relationships and your commercial terms are in here, so the fair first question is who else can reach them. The controls below are structural rather than procedural — they hold because of where they sit, not because everyone remembers to apply them.

RLS by defaultAES-256-GCMOAuth 2.0Migration-only schema
68
Tables with RLS
161
Policies
100
Migrations
45
DB functions
Controls

Six things that are true regardless of the code path

Each of these sits below the application, so no feature can be written in a way that quietly opts out of it.

Authorization at the data layer

Row-level security is enabled on 68 tables behind 161 policies. Access is decided by the database on every query — not by whichever screen happened to render. A bug in the UI cannot widen what a query returns.

Encrypted integration credentials

Per-user connection keys are sealed with AES-256-GCM — a random IV per record and an authentication tag stored alongside — before they reach a row, and are decrypted only inside server-side code paths.

Secrets never reach the browser

The client holds a publishable key and nothing more. Service keys, the model-provider key and the connection-key secret exist only in server modules that the client bundle cannot import.

Least-privilege integration scopes

Microsoft access is delegated per user through OAuth 2.0 with the narrowest scope set each feature needs. Odoo credentials are configured per workspace, never shared across tenants or baked into a build.

Schema as source of truth

Every change ships as a numbered migration — 100 of them so far, alongside 45 database functions. There is no drifted production schema, because there is no path that edits one by hand.

Auditable by construction

Job runs, agent runs and their steps, AI usage and cost, deal events and activity are all first-class rows. Reconstructing what happened is a query, not an investigation.

Boundaries

What each tier is allowed to hold

The useful question is not whether a system is secure, but what each part of it can reach when something goes wrong.

TierHoldsNever holds
BrowserSession token, publishable key, rendered data the user may already see.Service keys, provider API keys, other users' rows.
Application serverSecrets, integration clients, decryption of connection keys, job execution.Anything it has not been asked for by an authenticated caller.
DatabaseWorkspace content, with policies attached to the tables themselves.Rows returned to a caller who is not entitled to them.
AI and your data

What leaves the system, and what is recorded when it does

Drafting features send workspace content to a model provider. That is worth being explicit about rather than burying in a policy page.

  • Only the context a feature needs is sent — the thread, the notes, the figures behind that one draft.
  • Requests route through a single provider gateway rather than many direct integrations.
  • Every call is logged with its feature, model, token counts and cost, so what left the system is reviewable.
  • Administrators choose which models are enabled per feature, and may restrict that choice for members.