Authorization

Role-based access control and permissions in the LegionEdge Platform

The LegionEdge Platform uses role-based access control (RBAC) to manage what users and API keys can do. Permissions are evaluated at both the organization and project levels.

Roles

The platform ships with three built-in roles:

RoleDescription
OwnerFull access to all resources. Can manage billing, delete the organization, and assign roles.
AdminCan manage projects, teams, and members. Cannot modify billing or delete the organization.
MemberCan view and interact with assigned projects. Cannot manage teams or organization settings.

Custom Roles

You can create custom roles with fine-grained permissions:

const role = await client.roles.create({
  organizationId: "org_abc123",
  name: "Deployer",
  description: "Can deploy to staging and production",
  permissions: [
    "projects:read",
    "deployments:create",
    "deployments:read",
    "environments:read",
  ],
});

Permissions

Permissions follow the format resource:action. The platform defines these resource types:

  • organizations -- Organization-level settings and billing
  • projects -- Project CRUD and configuration
  • deployments -- Deployment creation and management
  • environments -- Environment configuration
  • resources -- Resource allocation and lifecycle
  • teams -- Team membership management
  • roles -- Role and permission management
  • api-keys -- API key management
  • webhooks -- Webhook configuration

Available actions: create, read, update, delete, list.

Policy Evaluation

When a request arrives, the authorization system evaluates policies in order:

  1. API key scope -- If the request uses an API key, the key's scoped permissions are checked first.
  2. Organization role -- The user's organization-level role is evaluated.
  3. Project role -- If the resource is project-scoped, the user's project-level role is checked.
  4. Explicit denies -- Any explicit deny policy overrides all allow policies.
// Check if the current user has a specific permission
const allowed = await client.auth.checkPermission({
  resource: "projects",
  action: "delete",
  resourceId: "proj_abc123",
});

if (!allowed) {
  throw new Error("You do not have permission to delete this project.");
}

Resource-Based Access Control

Beyond role-based policies, you can attach access policies directly to resources:

await client.projects.setPolicy("proj_abc123", {
  statements: [
    {
      effect: "allow",
      principals: ["user_jane", "user_bob"],
      actions: ["deployments:create", "deployments:read"],
      conditions: {
        environment: ["staging"],
      },
    },
    {
      effect: "deny",
      principals: ["user_bob"],
      actions: ["deployments:create"],
      conditions: {
        environment: ["production"],
      },
    },
  ],
});

Organization-Level Permissions

Organization-wide settings are managed separately from project permissions:

// Assign an organization role
await client.organizations.setMemberRole({
  organizationId: "org_abc123",
  userId: "user_jane",
  role: "admin",
});

// List all members and their roles
const members = await client.organizations.listMembers("org_abc123");
for (const m of members.data) {
  console.log(`${m.user.email}: ${m.role}`);
}

Auditing

All authorization decisions are logged and available through the audit log API:

const logs = await client.audit.list({
  organizationId: "org_abc123",
  action: "projects:delete",
  since: "2025-01-01T00:00:00Z",
});

for (const entry of logs.data) {
  console.log(`${entry.timestamp} ${entry.actor.email} ${entry.action} ${entry.result}`);
}

Next Steps

  • Explore the data models to understand the entities behind these permissions.
  • See best practices for security recommendations.