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)

  1. owner -- full control, can delete the org
  2. admin -- manage members, teams, settings
  3. operator -- manage agents, namespaces, policies
  4. support -- read + limited write for support workflows
  5. viewer -- read-only
  6. agent -- machine-to-machine access

Team Roles (highest to lowest privilege)

  1. manager -- full team admin
  2. contributor -- read + write within team scope
  3. reader -- read-only within team scope
  4. agent -- machine-to-machine team access

Permission Matrix

Organization Permissions

Permissionowneradminoperatorsupportvieweragent
org.readYYYYYY
org.updateYY----
org.deleteY-----
org.inviteYY----
team.createYYY---
team.readYYYYYY
team.updateYYY---
team.deleteYY----
team.members.manageYYY---
agent.createYYY---
agent.readYYYYYY
agent.updateYYY---
agent.deleteYY----
namespace.createYYY---
namespace.readYYYYYY
namespace.updateYYY---
namespace.deleteYY----
policy.createYYY---
policy.readYYYYY-
policy.updateYYY---
policy.deleteYY----
memory.readYYYYYY
memory.writeYYYY-Y
memory.deleteYYY---
memory.adminYY----
audit.readYYYY--
billing.readYY----
billing.manageY-----

How Permission Evaluation Works

  1. Authenticate -- JWT or API key authentication resolves the user identity
  2. Resolve org context -- The X-Organization-ID header identifies which org the request targets
  3. Look up membership -- The user's org membership is fetched to determine their role
  4. Check role minimum -- The route's required minimum role is compared against the user's role using the hierarchy
  5. 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 sets orgRbac context
  • requireOrgRole(minRole) -- rejects if the user's role is below the minimum
  • requireOrgPermission(permission) -- checks specific permission for the user's role
  • auditMiddleware -- 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);
}