Security
What mxAURA enforces
- Tenant boundary in the data layer. Every database statement from every worker passes through a query plane that requires a tenant predicate on every tenant table (the list is derived from the schema, not maintained by hand). A statement that could read another account's rows is refused before it runs. The API code cannot forget to check an id; the database layer would refuse anyway.
- Credentials at rest. API keys are stored as SHA-256 hashes. OAuth tokens likewise. HubSpot OAuth tokens and webhook signing secrets are encrypted (AES-256-GCM, envelope keyed by a vault-held master key).
- Keys never in browsers. A request carrying a browser
Originis refused for API keys (403 browser_origin). Browser apps use OAuth. - Rate limits and caps at three levels plus the hourly enrollment cap, and 30 calls a minute per account on anything that spends the AI allowance (shared by the app, the API and MCP).
- AI spend needs its own scope. Every call that pays a model or a web search needs
ai.writeand is metered against the account's allowance (402 budget_exhaustedwhen it refuses). - People sign in with two-factor. Platform administrators always; an account owner can require it for everyone in the account, and new accounts start with it on. Sign-up is checked by Cloudflare Turnstile and needs a confirmed email before any AI is used. These apply to people in the app; API keys and OAuth grants carry their own scopes.
- Idempotency on POST so retries cannot duplicate.
- Model-facing surfaces never see user-authored bodies.
- 5xx text never leaves the platform: you get a reference id, our logs get the detail.
- Every request is logged (credential, route, status, latency) to an analytics dataset an operator watches for runaway keys; every credential action (create, rotate, reveal, revoke) is audited.
What you should do
- One key per integration, named for it. Rotate when someone leaves.
- Least scope. A reporting job needs
dispatch.read, notfull. A content pipeline needsarticles.write+publishing.write, notsubscribers.write. - Set the IP allowlist on keys used from fixed infrastructure.
- Never put
enrollments.writeon a key you are not sure about. It sends email to real people. - Verify every webhook signature and reject stale timestamps.
- Store the key and the webhook secret in a secret manager, not in code
or a
.envcommitted to git. - Use
Idempotency-Keyon any create you might retry. - Watch for
X-MXA-Key-Status: rotated_gracein your logs. It means a caller still has the old key.
Policies
Access control, data protection, backup and recovery, and incident response are published at mxaura.ai/security, with the date of the last backup restore test.
Reporting a vulnerability
Email support@mxaura.ai with "security" in the subject. We acknowledge within one business day.
Do not test against accounts you do not own.