RBAC Architecture
Role-Based Access Control (RBAC) in Clue2App manages who can access what resources and perform which actions.
Overview
Clue2App uses a hierarchical permission model:
Account
└── Groups
└── Roles
└── Permissions
User Types
| Type | Description | Scope |
|---|---|---|
| SYSTEM | Platform administrators | Access to all accounts |
| ACCOUNT | Account-level users | Limited to their account |
Roles
Clue2App splits roles across two scopes: account (who can manage the account, its users, and its projects) and project (who can do what inside a specific project).
Account-scope roles
| Role | Permissions |
|---|---|
| ACCOUNT_ADMIN | Full account management: users, projects, limits, billing |
| MEMBER | Belong to the account; access grants come via project roles |
Project-scope roles
| Role | Permissions |
|---|---|
| PROJECT_ADMIN | Full project control (apps, secrets, domains, members) |
| CONTRIBUTOR | Create/edit apps, deploy, view logs |
| VIEWER | Read-only access to project resources |
These are the roles the invitation flow (c2a user invite -P <project> -r <role>) grants.
Permission Matrix
| Permission | ACCOUNT_ADMIN | PROJECT_ADMIN | CONTRIBUTOR | VIEWER |
|---|---|---|---|---|
| Manage account users / limits | ✓ | |||
| Add project members | ✓ | ✓ | ||
| Create / delete apps | ✓ | ✓ | ✓ | |
| Edit apps + env | ✓ | ✓ | ✓ | |
| View apps + logs | ✓ | ✓ | ✓ | ✓ |
Data model note. As of V56 (
account_user_roles, SCK-475) and V57 (account_limit_overrides, SCK-481), account-scope role grants and limit overrides carrycreated_by/updated_by/created_at/updated_ataudit columns.
Architecture
How Groups Work
- Users belong to Groups - A user can be in multiple groups
- Groups have Roles - Each group is assigned one role
- Roles grant Permissions - The role determines what actions are allowed
- Permissions are additive - Users get the union of all their groups' permissions
Example
User: alice@example.com
└── Groups: [DevTeam, QATeam]
├── DevTeam → APPLICATION_ADMIN
│ └── Permissions: addApplications, editApplications
└── QATeam → APPLICATION_DEVELOPER
└── Permissions: readOnly
Result: Alice can create, edit, and view applications
Invitation Flow
The operational way users get onboarded is via invite-by-email, either from the CLI or the console.
# CLI: invite alice as a contributor on the "clues" project
c2a user invite -e alice@corp.com -P clues -r CONTRIBUTOR
# Invite bob as a project admin across two projects
c2a user invite -e bob@corp.com -P clues -P entrada -r PROJECT_ADMIN
Behind the scenes:
POST /api/accounts/{accountId}/memberscreates the account membership and the project role grants atomically. The invitee is placed into the project's owning account, not the caller's account (SCK-475).- A
SoloInvitationrecord is issued and emailed to the invitee. - When the invitee signs in via Google/OAuth for the first time, the redeem path (SCK-436) resolves the
SoloInvitation— thesha256Hexof the invitee's email is compared as lowercase-hex on both sides — and completes the account + project bindings.
Legacy direct-create (POST /api/user/account/{accountId}) still works for LOCAL users but is not the recommended onboarding path.
API Endpoints
User Management
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/user/account/{accountId} | List account users |
| POST | /api/user/account/{accountId} | Legacy: create user directly |
| PUT | /api/user/{userId} | Update user |
| DELETE | /api/user/{userId} | Delete user |
Account Members & Invitations
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/accounts/{accountId}/members | Invite by email with atomic project grants (preferred) |
| GET | /api/accounts/{accountId}/members | List account members and their project roles |
| DELETE | /api/accounts/{accountId}/members/{userId} | Remove a member from the account |
Group Management
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/group/account/{accountId} | List account groups |
| POST | /api/group/ | Create group |
| PUT | /api/group/{groupId} | Update group |
| DELETE | /api/group/{groupId} | Delete group |
| GET | /api/group/{groupId}/members | List group members |
| POST | /api/group/{groupId}/members | Add member(s) to group |
| DELETE | /api/group/{groupId}/members/{userId} | Remove member |
Role Management
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/role/ | List available roles |
| GET | /api/account-user-roles/{userId} | Account-scope role grants for a user (audited: created_by / updated_by since V56) |
Best Practices
Principle of Least Privilege
- Assign users the minimum permissions needed
- Use APPLICATION_DEVELOPER for read-only users
- Reserve ACCOUNT_ADMIN for account owners
Group Organization
- Create groups by team or function (e.g., "Backend Team", "DevOps")
- Avoid assigning roles directly to users
- Use groups to manage permissions at scale
Account Structure
- One account per organization or project
- Use SYSTEM type only for platform operations
- Account owners should be ACCOUNT_ADMIN
Planned Improvements
Future enhancements to the RBAC system:
- Resource-Level Permissions - Control access to specific apps/services
- Custom Roles - Create account-specific roles
- Role Hierarchy - Inherit permissions from parent roles
- Audit Logging - Track all permission changes
- Temporary Elevation - Time-limited permission grants
Need help? Contact support or visit our GitHub Issues.