Skip to main content

User Domain

The user domain covers identity lifecycle decisions — who may be admitted to the platform, how they authenticate, what user data they can read, and who may create or read Personal Access Tokens. Each action below indicates the service that calls it.

Contracts

All contracts include Subject, see Subject claims.

user:onboard

Evaluated when a user logs in for the first time via an identity provider. The decision controls whether onboarding is permitted at all, and the obligations carry the initial account configuration the backend must apply.

Resource

FieldDescription
idUsername being onboarded. Required.
typeResource type. The value is user.
attributes.idpIdentity provider name (e.g. idp.k8shell.io/github). Required.
attributes.orgOrganization name, if the provider reports one. Optional.

Obligations

KeyDescription
sudotrue | false. Whether the user gets sudo access inside workspaces.
rolesJSON array of role name strings. Roles to assign on the user record.
blueprintsJSON array of blueprint names or * for all. Blueprints the user is permitted to use.

user:auth

Evaluated on every SSH authentication attempt, before a session is opened. The decision controls whether the authentication method and key are accepted.

Resource

FieldDescription
idUsername authenticating. Required.
typeResource type. The value is user.
attributes.idpIdentity provider the user was onboarded from. Required.
attributes.orgOrganization name, if the provider reports one. Optional.

Context

FieldDescription
methodpublickey or password. Required.
fingerprintSHA256 fingerprint of the public key being presented. Required for publickey.

Obligations — none; allow/deny only.

user:read

Evaluated when a caller requests access to a specific category of user data. Policies can restrict which data types a user may read about themselves or others.

Resource

FieldDescription
idUsername whose data is being requested. Required.
typeResource type. The value is user.

Context

FieldDescription
data_typeprofile, credentials, or blueprints. Required.

Obligations — none; allow/deny only.

user:list

Evaluated when a caller requests the full list of platform users. There is no context — the decision is based solely on the subject's identity.

Resource

FieldDescription
idEmpty — no specific user.
typeResource type. The value is user.

Obligations — none; allow/deny only.

token:create

Evaluated when a PAT is about to be issued. The decision controls whether the caller may create a token for the target user. When allowed, the obligations constrain the token's permitted scopes and lifetime.

Resource

FieldDescription
idUsername of the user who will own the new token. Required.
typeResource type. The value is user.

Context

FieldDescription
sourceweb-flow or api. Required. web-flow — token issued at the end of an OAuth flow initiated by the CLI. api — token created via a direct API request.

Obligations

KeyDescription
scopesJSON array of scope strings the issued token is permitted to use.
expires_inGo duration string for the token lifetime (e.g. 720h) or never for no expiry.

token:read

Evaluated when a caller requests the list of PATs belonging to a specific user.

Resource

FieldDescription
idUsername whose tokens are being read. Required.
typeResource type. The value is user.

Obligations — none; allow/deny only.

Example policy

package user

import rego.v1
import data.common

default allow := false

# admins can perform any user action except those explicitly denied
admin_denied_actions := {"token:create"}

allow if {
input.subject.username in common.admin_users
not input.action in admin_denied_actions
}

# any authenticated user can onboard or authenticate via SSH
allow if input.action in {"user:onboard", "user:auth"}

# users can read their own data (profile, sessions, credentials, blueprints)
allow if {
input.action == "user:read"
input.subject.username == input.resource.id
}

# users can create tokens for themselves
allow if {
input.action == "token:create"
input.subject.username == input.resource.id
}

# user:list is admin-only — covered by the admin rule above

# --- token:create obligations ---

obligations["expires_in"] := "24h" if {
input.action == "token:create"
input.context.source == "web-flow"
}

# --- user:onboard obligations ---

roles contains "user" if {
input.action == "user:onboard"
}

roles contains "admin" if {
input.action == "user:onboard"
input.subject.username in common.admin_users
}

obligations["roles"] := roles if {
input.action == "user:onboard"
}

obligations["sudo"] := "true" if {
input.action == "user:onboard"
input.subject.username in common.admin_users
} else := "false" if {
input.action == "user:onboard"
}

obligations["blueprints"] := ["*"] if {
input.action == "user:onboard"
input.subject.username in common.admin_users
} else := ["dev", "am2"] if {
input.action == "user:onboard"
}

This example demonstrates the following patterns:

  • Any authenticated user may onboard (user:onboard) and authenticate via SSH (user:auth).
  • Users can read their own data (user:read).
  • Users can create tokens via web-flow. Such tokens are valid for 24h.
  • Admins can read all users (user:list).
  • Admins are granted sudo, the admin role, and access to all blueprints (*) on onboarding. Regular users receive the user role and are permitted the dev and am2 blueprints.