RBAC model
How telark models users, groups, roles, and permissions on top of custom resources.
This page is the conceptual primer. The HTTP surface and the UI flows live in Features → RBAC and Features → Auth.
Four resource kinds
| Kind | Owns |
|---|---|
User | Identity. One record per human (or service identity). |
Group | A named collection of users. A user can be in many groups. |
Role | A bundle of scope → permission level rules. |
Category | A tagging primitive used to scope roles by domain. |
All four are persisted as Kubernetes custom resources owned by the exporter service. RBAC mutations land on the cluster's API server, not on a private database.
The shape of a role
A role's substantive content is its scopesAndPermissions array.
Each entry pairs a telark scope (a feature area or resource
group) with a permission level.
Pseudocode for the shape:
type Role = {
id: string;
name: string;
description: string;
version: string;
type: RoleType;
priority: number;
categoryID: string;
scopesAndPermissions: ScopeAndPermissions[];
protection?: Protection; // optional system-role guard
validity?: Validity; // optional expiry rules
status: RoleStatus; // active | deprecated | deleted
// …audit fields
};
type ScopeAndPermissions = {
scope: string; // e.g. "protection-plans", "applications", "rbac"
level: PermissionLevel; // read | write | admin (etc.)
};priority matters when a user inherits from multiple roles —
telark resolves conflicts in priority order so the higher-priority
role wins per scope.
Built-in roles
Four roles ship out of the box:
- Admin — full read/write on every scope, including RBAC and GlobalConfig.
- Contributor — manages applications, plans, rollbacks. Cannot mutate RBAC or GlobalConfig.
- ReadOnly — reads everything. Mutates nothing.
- Owner — bootstrap admin set by configuration on first login. Same surface as Admin.
These are sufficient for most teams. Custom roles cover the rest.
Groups bundle users
A group is a named set of users. The point of groups is to let you assign a role once to many users — and revoke it once for the same many. A user can be in multiple groups.
A role can be assigned to specific users (assignedTo.userIDs),
to specific groups (assignedTo.groupIDs), or both. The resolved
permission set for a user is:
- Roles assigned directly to the user, plus
- Roles assigned to every group the user is a member of,
- Collapsed by priority into a single
scope → levelmap.
Validity windows
Roles can carry an optional validity block to express
time-bound elevation: "Alice gets the Admin role from 09:00 to
17:00 for the audit window today". Outside the window the role is
effectively absent from permission resolution.
The dashboard renders a validity badge on roles that have one and counts down the time remaining.
Protection on system roles
A role's optional protection block is a guard against accidental
deletion of system-critical roles. A protected role surfaces a
confirm-with-confirmation prompt in the dashboard and rejects
unprotected delete attempts at the API layer.
How auth resolves permissions per request
The auth service exposes a /auth/authorisation/permissions
endpoint. On every page load, the dashboard:
- Resolves the current session via cookie or passkey assertion.
- Hits the permissions endpoint.
- Caches the resolved map in Redux.
- Gates UI elements through a
usePermission(scope, level)hook.
Every server-side endpoint independently re-checks permissions on writes. Hiding a button in the UI is not the security boundary; the API is.
What this is not
- Not OPA / Rego. telark RBAC does not run general policy
expressions; it is a flat
scope → levelresolution. - Not federated. Today RBAC is per-cluster. The user / group / role CRDs live in the cluster telark is installed on.
- Not delegated. A user with the Admin role can create roles
with arbitrary scopes. There is no concept of "this user can
only mutate RBAC for the
paymentscategory" today.