Security

Isolated by the database, not by a WHERE clause

You are trusting us with your customers' conversations. This is how that trust is enforced — mechanically, at the layer below the application, where a forgotten line of code cannot undo it.

One account cannot see another

Every row in the database carries the account it belongs to, and row-level security enforces that boundary for every signed-in session automatically — not as a filter the application remembers to add, but as a rule the database will not let a query escape. Where code genuinely must run with elevated privileges — an inbound webhook, the AI engine, a public booking page — every query is explicitly scoped by hand, and any function that accepts an account id checks that the caller belongs to it before doing anything. Passing someone else's account id gets you an error, not their data.

Four roles, and the database agrees with the app

Owner, admin, agent and viewer. Managing members and editing settings needs admin or above; sending and writing needs agent or above; deleting the account and transferring ownership are owner-only. The same ladder is implemented in the database, so a permission is not something the interface merely hides — it is something the data layer refuses. A viewer who reaches an API route directly still gets nothing.

Secrets are encrypted, credentials are hashed

Channel access tokens, AI provider keys, voice credentials and custom connector authentication are encrypted at rest with AES-256-GCM. API keys and MCP connection tokens are never stored at all — only their SHA-256 hashes — so they are shown to you exactly once and cannot be recovered by anyone, including us. Both are revocable, and MCP tokens additionally expire.

Nothing untrusted gets in unchecked

Inbound webhooks from Meta are signature-verified against the raw request bytes before anything is read from them, so a forged payload never reaches the database. Custom HTTP connectors — the way you let the AI call your own systems — go out through a guard that requires HTTPS, blocks private-range addresses after resolving the host, and refuses to follow redirects, so a connector cannot be pointed at your internal network.

Hardened by default

Strict transport security, content-type sniffing disabled, framing denied, a tight referrer policy and a permissions policy on every response. Rate limiting per API key and per IP. Public token pages — a review link, a booking link — return an identical 404 for an unknown, disabled or suspended target, so a stranger cannot use them to work out which accounts exist.

The AI runs inside the same walls

The assistant is not a privileged actor. Every tool it can call declares a minimum role and re-filters by account when it runs, and each assistant carries a per-tool access map you control. A human taking over a conversation stands the AI down immediately, and it will not resume that thread. Over MCP, a connection can never exceed the authority of the person who created it.

How the MCP guarantee works

Or run the whole thing yourself

RaabtaHQ is self-hostable on your own infrastructure and your own database. If your data cannot leave your building — or your jurisdiction — that is a supported way to use it, not a special case. Talk to us about what the arrangement looks like.

Your data

Getting it out, and getting it deleted

Your customers' data is yours. We hold it to run the product for you, and you can take it back or have it removed.

What we collect and why is set out in the privacy policy. How to request deletion, what gets deleted, and how long it takes are set out on the data & GDPR page.

Found something that looks wrong? Tell us at hello@raabtahq.online and we will look at it properly. We would much rather hear it from you than not hear it.

Questions your security team needs answered?

Send them over. We would rather work through a real review than hand you a badge and hope it covers it.