Fail closed.
The security model is built on refusals: a query without tenant context returns nothing, an identity that is not verified is never written, a gate that is not met does not move. This page states what holds, and exactly how far each claim goes.
A governance product that is loose about its own security is a contradiction, so this page is written the way we write audit rows: precisely, and no further than the evidence goes. Isolation is enforced in the database, not just the application. Identity is derived from credentials, not accepted from callers. And where a control has limits, the limit is stated here rather than discovered later.
Row-level security, with FORCE.
Every tenant-scoped table carries a Postgres RLS policy keyed on the request's tenant context, applied with FORCE so even the table owner cannot bypass it. No context, no rows. Application-level scoping and tenant middleware add layers on top of the database guarantee, not in place of it.
USING (
org_id = current_setting(
'app.current_tenant_id', TRUE)
OR org_id IS NULL
)The human is not a parameter.
Audit rows carry two identities. The agent label is self-declared. The authenticated human is stamped server-side from the verified credential, and no request body, header or tool parameter exists that could carry it: a forged value has nowhere to land.
{
"actor": "implementer",
"actor_user_id": "usr_…",
"actor_user_name": "David Marsa"
}OAuth first, keys when you need them.
The MCP surface authenticates with OAuth 2.1 and JWKS verification; a static key path exists for automation. API keys are bcrypt-hashed, displayed once at creation, and scoped to the user across their workspaces.
- Sign-in opens a browser; no credentials pass through the client config
- Keys carry no embedded secrets in transit besides the bearer itself
- Roles are owner / admin / member, enforced with real 403s and last-owner protection
What the audit covers, exactly.
Field-level before-and-after diffs cover tasks and workflow instances: the surfaces where agents act. Policies are governance text delivered into the active step, evaluated by the agent that reads them; gates are the enforcement primitive. We state the mechanism as it is.
questions
What happens if a request arrives without tenant context?
It reads nothing. The row-level security policy keys on the request's tenant setting, and with FORCE applied even the table owner cannot step around it. Fail closed is the default state, not an error path.
Can I recover an API key I lost?
No, by design. Keys are bcrypt-hashed at rest and displayed exactly once at creation; if one is lost, you revoke it and mint another.
Where does the human identity on an audit row come from?
From the verified credential, stamped server-side. There is no request field, header, or tool parameter that carries it, so it cannot be spoofed by an agent or a caller.
Do you support SSO?
SSO and SCIM are part of the Enterprise plan. Standard sign-in is OAuth; the MCP surface authenticates with OAuth 2.1 and JWKS verification, with a static key path for automation.