Security
An AI you can audit. A tenant boundary the database enforces.
A CRM that reads your team's email has to clear a higher bar than one that stores typed notes. We designed for that bar from the first migration — and we write our security posture down, including what happens when something goes wrong.
Isolation is the database's job
Every table carries row-level security enforced by Postgres itself — tenant isolation doesn't depend on application code remembering to filter. Agents, schedules, and AI budgets are scoped per workspace.
Mailbox tokens live in a vault
Per-user Microsoft refresh tokens are encrypted at rest in a dedicated vault; the connection table stores only an opaque reference, so dumping it yields nothing usable. Access tokens are minted per request and never persisted.
Mail access is opt-in, per person
Sign-in and mailbox access are two separate consents by design. Signing in grants identity only — nobody's mail is readable because their company adopted the product. Each rep connects, and can disconnect, their own mailbox.
Agents cannot act alone
One write path from agents to the world, through a human approval queue. Outbound email and invites are permanently draft-first — there is no configuration that removes the human.
Hostile content is fenced
Everything synced from the outside world is wrapped in untrusted-data markers before any model sees it, with look-alike markers neutralised — prompt injection can't talk an agent into an action, and the approval queue stands behind that anyway.
Errors never leak tenant data
One error-reporting choke point, with a hard rule: no verified workspace, no stored text. Secrets and tokens are redacted by pattern, messages are capped, and request bodies, headers, and email content are never captured.
SSO with defense in depth
Microsoft Entra single sign-on, domain-gated account creation — an email domain that matches no workspace can't even create an account — and per-workspace SSO-only enforcement that bounces password sessions.
API access that expects rotation
API keys are SHA-256 hashed and shown once, org-scoped, and rate-limited. Webhooks are HMAC-SHA256 signed. Everything is built to be rotated without ceremony.
A written incident runbook
We publish our kill-switch order internally and rehearse it: rotate the service key, cut the identity-provider secret — which instantly bricks every stolen mail token — revoke sessions, rotate the rest, audit deployments.
We assume things break, and we say what mail access means.
A Microsoft refresh token is scoped and bound: it cannot reach the Azure portal, Teams, or SharePoint, cannot self-escalate, and cannot touch anyone who never connected. We still treat mailbox access as the most sensitive thing we hold — because a mailbox is the recovery channel for everything else. That's why tokens sit in a vault, why every send is human-approved, and why the fastest kill switch bricks every token at once.
The posture is written down.
The architecture, the approval gates, and the runbook — the same material we hold ourselves to.