Hexclave

Permissions, sorted

Roles that nest·One check, server or client·Managed from the dashboard

Ask whether a user can do something — get an answer

Same call on server and client·Inheritance handled for you·Project-wide or per-team

ts
1"use server";
2import { stackServerApp } from "@/stack";
3 
4export async function inviteMember(teamId: string, email: string) {
5 const user = await stackServerApp.getUser({ or: "throw" });
6 const team = await user.getTeam(teamId);
7 
8 // Returns the permission if the user has it, null otherwise.
9 if (!(await user.getPermission(team, "$invite_members"))) {
10 throw new Error("Not allowed");
11 }
12 await team.inviteUser({ email });
13}

Roles without the wiring

Define them in the dashboard·Check them anywhere in your code·Let them nest, naturally

Acme team/Members
Live check
Signed in as
MV
Mira (viewer)
Viewer · 1 permissions
user.usePermissionchecking
const canInvite =
user.usePermission(team, "$invite_members");
Members · 4
LP
Lia ParkAdmin
NR
Noah ReyesMember
AK
Alex KimMember
KS
Kai SinghViewer

01·Permission checks

One line decides what shows up

  • Ask the same question on the server and in your React components
  • Buttons that need a permission hide themselves — no flicker
  • Server-side checks keep the real enforcement honest
Server & clientReactive UIOne API
Noah·Acme team
Inheritance
Role definition · admincontains 4
adminparent
└─moderator
└─$invite_members
└─$read_members
└─$update_team
Grant admin to Noah
user.grantPermission(team, "admin")
Effective permissions
No permissions yet

02·Nested roles

Roles that contain other roles

  • Build an admin role from smaller, named permissions
  • Grant the parent once — every nested permission comes along
  • Drop a permission into a role and every member picks it up
Nested permissionsInheritanceOne source of truth
Mira·Effective permissions
Two scopes
AC
Acme
5 perms
GX
Globex
1 perms
Team scope· changes per team
usePermission(team, …)
$update_team$invite_members$read_members$remove_membersbilling
$built-inStack Auth ships these for every team
Project scope· follows the user
usePermission(…)
staffbeta_tester
Same across Acme, Globex, every team
Pass a team for team-scoped. Drop it for project-wide.

03·Per-team and project-wide

Some permissions belong to a team. Some belong to everyone.

  • Team permissions live inside a team — admin of Acme, member of Globex
  • Project permissions apply across your whole app — staff, beta, premium
  • Same check, just pass a team or don't
  • Built-in team permissions cover invites, member management, and team settings
Team scopeProject scopeBuilt-ins included

Ready to lock things down?

Drop in a single app — or use the whole platform. Either way, you ship faster.

Get started for free