Role-Based Access Control (RBAC)
Hippocortex Enterprise uses a hierarchical RBAC model with two levels: organization roles and team roles.
Role Hierarchies
Organization Roles (highest to lowest privilege)
- owner -- full control, can delete the org
- admin -- manage members, teams, settings
- operator -- manage agents, namespaces, policies
- support -- read + limited write for support workflows
- viewer -- read-only
- agent -- machine-to-machine access
Team Roles (highest to lowest privilege)
- manager -- full team admin
- contributor -- read + write within team scope
- reader -- read-only within team scope
- agent -- machine-to-machine team access
Permission Matrix
Organization Permissions
| Permission | owner | admin | operator | support | viewer | agent |
|---|---|---|---|---|---|---|
| org.read | Y | Y | Y | Y | Y | Y |
| org.update | Y | Y | - | - | - | - |
| org.delete | Y | - | - | - | - | - |
| org.invite | Y | Y | - | - | - | - |
| team.create | Y | Y | Y | - | - | - |
| team.read | Y | Y | Y | Y | Y | Y |
| team.update | Y | Y | Y | - | - | - |
| team.delete | Y | Y | - | - | - | - |
| team.members.manage | Y | Y | Y | - | - | - |
| agent.create | Y | Y | Y | - | - | - |
| agent.read | Y | Y | Y | Y | Y | Y |
| agent.update | Y | Y | Y | - | - | - |
| agent.delete | Y | Y | - | - | - | - |
| namespace.create | Y | Y | Y | - | - | - |
| namespace.read | Y | Y | Y | Y | Y | Y |
| namespace.update | Y | Y | Y | - | - | - |
| namespace.delete | Y | Y | - | - | - | - |
| policy.create | Y | Y | Y | - | - | - |
| policy.read | Y | Y | Y | Y | Y | - |
| policy.update | Y | Y | Y | - | - | - |
| policy.delete | Y | Y | - | - | - | - |
| memory.read | Y | Y | Y | Y | Y | Y |
| memory.write | Y | Y | Y | Y | - | Y |
| memory.delete | Y | Y | Y | - | - | - |
| memory.admin | Y | Y | - | - | - | - |
| audit.read | Y | Y | Y | Y | - | - |
| billing.read | Y | Y | - | - | - | - |
| billing.manage | Y | - | - | - | - | - |
How Permission Evaluation Works
- Authenticate -- JWT or API key authentication resolves the user identity
- Resolve org context -- The
X-Organization-IDheader identifies which org the request targets - Look up membership -- The user's org membership is fetched to determine their role
- Check role minimum -- The route's required minimum role is compared against the user's role using the hierarchy
- Grant or deny -- If the user's role meets the minimum, access is granted
Example Flow
Request: PATCH /v1/organizations/org_123/teams/team_456
Headers: Authorization: Bearer <jwt>, X-Organization-ID: org_123
1. JWT resolves user_id = "user_789"
2. Org context: org_123
3. Membership lookup: user_789 has role "operator" in org_123
4. Route requires: "viewer" minimum (team update needs operator+)
5. operator >= viewer? Yes -> access granted
6. Route handler checks orgRoleMeetsMinimum("operator", "admin") for update
Middleware Stack
Enterprise routes use this middleware chain:
JWT Auth -> resolveOrgContext -> requireOrgRole("viewer") -> auditMiddleware -> route handler
resolveOrgContext-- looks up the user's membership and setsorgRbaccontextrequireOrgRole(minRole)-- rejects if the user's role is below the minimumrequireOrgPermission(permission)-- checks specific permission for the user's roleauditMiddleware-- logs successful mutations to audit_logs
Programmatic Permission Check
Route handlers can check permissions programmatically:
import { orgRoleMeetsMinimum } from "../middleware/rbac.js";
// In a route handler:
const orgRbac = c.get("orgRbac");
if (!orgRoleMeetsMinimum(orgRbac.orgRole, "admin")) {
return c.json({ ok: false, error: { code: "forbidden" } }, 403);
}