# Built-in Roles in Kaneo’s Permission System: Viewer, Member, and Admin Explained

> Understand Kaneo's built-in roles viewer member and admin Explore how these core permissions function within the Kaneo permission system and manage access effectively

- Repository: [kaneo.app/kaneo](https://github.com/usekaneo/kaneo)
- Tags: deep-dive
- Published: 2026-08-30

---

**Kaneo compiles three core workspace roles—viewer, member, and admin—into its permission package via the `DEFAULT_ROLE_NAMES` constant, while treating the owner role as a separate system-level designation.**

The open-source project management platform **Kaneo** (available at `usekaneo/kaneo`) implements a hierarchical permission system using built-in roles that determine access levels across workspaces. These predefined roles form the foundation for all authorization checks, ensuring that workspace members have appropriate capabilities for their responsibilities without requiring manual permission configuration.

## The Three Built-in Roles in Kaneo

According to the source code in [`packages/permissions/src/index.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/permissions/src/index.ts), Kaneo defines exactly three compiled-in workspace roles through the `DEFAULT_ROLE_NAMES` constant. These roles provide tiered access control ranging from read-only observation to full administrative capabilities.

### Viewer (Read-Only Access)

The **viewer** role provides read-only access to workspace resources. Users assigned this role can view tasks, projects, and workspace data but cannot modify them. This role suits stakeholders who need visibility into project progress without the ability to create or edit content.

### Member (Standard Contributor)

The **member** role represents the standard contributor level. Members can create tasks, add comments, and perform most day-to-day project management actions. This role targets active team members who contribute to workstreams but do not require administrative privileges over the workspace configuration.

### Admin (Full Workspace Administration)

The **admin** role grants full workspace administration capabilities. Admins can manage tasks, projects, users, and workspace settings, including the ability to modify or delete resources created by other users. This role is reserved for team leads and workspace managers who need complete control over the environment.

## Where Built-in Roles Are Defined in the Source Code

The canonical definition of built-in roles resides in [`packages/permissions/src/index.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/permissions/src/index.ts), where the system exports the `DEFAULT_ROLE_NAMES` constant as a frozen array:

```typescript
// packages/permissions/src/index.ts
export const DEFAULT_ROLE_NAMES = ["viewer", "member", "admin"] as const;

```

This TypeScript `as const` assertion ensures type safety throughout the application, allowing the compiler to enforce that role strings match only these three values.

**Important Distinction**: The **owner** role exists at the system level (automatically assigned to the workspace creator) but is **not** part of the compiled-in `DEFAULT_ROLE_NAMES` set. The owner designation is handled separately in the workspace creation logic found in [`apps/api/src/auth.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/auth.ts).

## Implementing Permission Checks with Built-in Roles

Kaneo leverages these built-in roles for middleware-based authorization. The `requireWorkspacePermission` function from `@kaneo/permissions` validates that the authenticated member’s role satisfies the required action.

```typescript
// Permission check in a route controller
import { requireWorkspacePermission } from "@kaneo/permissions";
import { createRoute } from "your-router";

export const createTask = createRoute({
  method: "post",
  path: "/tasks",
  middleware: [requireWorkspacePermission("task:create")],
  handler: async (req, res) => {
    // Task creation logic executes only for members and admins
  }
});

```

When creating workspace members programmatically, you must specify one of the built-in role names:

```typescript
// Creating workspace members with different access levels
const member = await createWorkspaceMember({ role: "member" });
// → Can create tasks and comment, but cannot delete tasks

const admin = await createWorkspaceMember({ role: "admin" });
// → Full management capabilities including user administration

const viewer = await createWorkspaceMember({ role: "viewer" });
// → Read-only access to project data

```

## Seeding Default Roles in New Workspaces

When a workspace is created, Kaneo automatically seeds the database with records for each built-in role. The utility in [`apps/api/src/utils/seed-default-workspace-roles.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/utils/seed-default-workspace-roles.ts) handles this initialization:

```typescript
// Seeding default roles for a new workspace
import { DEFAULT_ROLE_NAMES, defaultRolePayloads } from "@kaneo/permissions";

async function seedDefaultRoles(workspaceId: string) {
  for (const name of DEFAULT_ROLE_NAMES) {
    await db.insertInto("workspace_role")
      .values({ 
        workspace_id: workspaceId,
        name, 
        ...defaultRolePayloads[name] 
      })
      .execute();
  }
}

```

This ensures that every workspace starts with the complete permission structure defined in the `workspace_role` table.

## Custom Roles and Fallback Behavior

While Kaneo provides these three built-in roles, the system also supports custom roles defined in the `workspace_role` database table. When resolving permissions, the system first checks for a custom role matching the member’s assignment. If the specific custom role is missing or undefined, Kaneo falls back to the built-in role of the same name, ensuring that the `DEFAULT_ROLE_NAMES` always serve as the authoritative baseline for access control.

## Summary

- Kaneo defines **three built-in roles**—viewer, member, and admin—through the `DEFAULT_ROLE_NAMES` constant in [`packages/permissions/src/index.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/permissions/src/index.ts).
- The **viewer** role provides read-only access, **member** enables standard contributions, and **admin** grants full workspace management.
- The **owner** role exists separately at the system level and is automatically assigned to workspace creators, distinct from the compiled-in set.
- Built-in roles serve as the fallback mechanism when custom roles are undefined, ensuring consistent permission resolution.

## Frequently Asked Questions

### What are the three built-in roles in Kaneo?

Kaneo defines three core workspace roles: **viewer** (read-only access to tasks and projects), **member** (ability to create tasks and comments), and **admin** (full workspace management including user and settings control). These are compiled into the application via the `DEFAULT_ROLE_NAMES` constant.

### How do I assign a built-in role to a workspace member?

Assign a built-in role by passing one of the three valid strings—`"viewer"`, `"member"`, or `"admin"`—to the `role` parameter when calling `createWorkspaceMember()`. The system validates this against the `DEFAULT_ROLE_NAMES` array defined in the permissions package.

### Is the owner role a built-in role in Kaneo?

No, the owner role is **not** part of the built-in `DEFAULT_ROLE_NAMES` set. According to the source code in [`apps/api/src/auth.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/auth.ts), the owner designation is added automatically for the workspace creator at the system level, separate from the three compiled-in roles.

### Where are the default roles defined in the Kaneo codebase?

The default roles are defined in [`packages/permissions/src/index.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/permissions/src/index.ts) as the exported constant `DEFAULT_ROLE_NAMES = ["viewer", "member", "admin"]`. This file also contains the `defaultRolePayloads` object used during workspace seeding, while database seeding logic resides in [`apps/api/src/utils/seed-default-workspace-roles.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/utils/seed-default-workspace-roles.ts).