Permissions & roles
LocalMind's access control follows one principle:
Permission is the currency. A role is just a fixed, named bundle of permissions.
Every endpoint checks a permission string (for example members:write).
Role names never appear at a call site — they exist only in the bundle tables the
platform maintains. Adding or changing a role never touches endpoint code.
Two axes, never mixed
| System axis | Project axis | |
|---|---|---|
| Answers | "Are you a platform operator?" | "What are you inside this project?" |
| Source | user.role (comma-separated, may hold several) | one role per (user, project) membership |
| Scope | global / admin surface | a single project |
| Regular users | none | one per project they belong to |
A regular end user has no System role; all their power comes from project
memberships. The two axes are evaluated independently, so a permission that
exists on both (like billing:read) never leaks across.
Project roles
The four project roles form a subset chain:
| Permission | Viewer | Member | Admin | Owner |
|---|---|---|---|---|
| Read project & members | ✅ | ✅ | ✅ | ✅ |
| Write resources | — | ✅ | ✅ | ✅ |
| Manage members & settings | — | — | ✅ | ✅ |
| API keys & webhooks | — | — | ✅ | ✅ |
| Delete & transfer ownership | — | — | — | ✅ |
System roles
Platform operators hold one or more of five named System roles — Super Admin, Platform Manager, Billing Manager, Security Manager and Support Agent. Effective permissions are the union of every role held.
The override
platform:override is the single key that can reach a tenant project's internal
data, and it is held only by Super Admin. Every use is written to the
audit log. Everywhere else, a cross-tenant read returns
404 — the platform never confirms a resource it won't show you exists.