2026-06-10

Tenant isolation by default: how the kit scopes every query

Every tenant-facing query is scoped to the current account, client-supplied account ids are rejected, and e2e tests prove it.

Multi-tenancy fails quietly. A missing where-clause does not throw — it leaks. The kit treats isolation as a default, not a convention.

One rule, enforced everywhere

Every tenant-facing query includes the current account id taken from the session, never from the request body. A client-supplied account id in a tenant action is ignored or rejected. The only code paths that may read across accounts are the system admin routes, which live in a separate route scope with their own guard.

Deny by default

Roles are a table, not a vibe. Owner, admin, and member each have an explicit allow list; anything outside the table is denied. Admins can switch roles between member and admin only — owner stays protected, and every role change lands in the audit log.

Tests that try to break it

The e2e suite signs in as tenant A and attempts to read tenant B's projects, users, and access keys. API tests send malicious account-id payloads on purpose. The suite fails the build if any of it succeeds. Isolation you cannot test is isolation you do not have.

Where to look

The schema and tenant helpers live in packages/db, the role policies in packages/rbac, and the evidence — env matrix, test commands, source map — is contained in the admin Developer surface, never on tenant screens.