> ## Documentation Index
> Fetch the complete documentation index at: https://docs.withsutro.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Security & Auth

> Define subjects, identities, groups, roles, permissions, and authenticated user updates.

SLang security is built around the request `@subject`. A subject is the authenticated caller. You decide which entity represents a subject, which field identifies it, and which role paths grant permissions.

## Subjects and Identity Fields

Mark an entity with `subject` when records of that entity can authenticate. Add `identity <fieldName>` to choose the login identifier field.

The identity field must exist on the entity. SLang also includes `@id` as an identity field internally, so `identity email` means the runtime can connect a token subject back to the persisted user row.

```slang theme={null}
enum MembershipRole
  values
    member
    admin
    owner

entity User
  subject
  identity email
  fields
    email: EMAIL
    displayName: TEXT?

entity Organization
  group @id
  fields
    name: TEXT

entity Membership
  role membershipRole
  fields
    membershipRole: MembershipRole := "member"

entity Project
  fields
    title: TEXT

relation User[memberships] 1 --- 0..* Membership[member]
relation Organization[memberships] 1 --- 0..* Membership[organization]
relation Organization[projects] 1 --- 0..* Project[organization]

permissions User->memberships->member
  "project:read"

permissions User->memberships->admin
  "project:read"
  "project:write"

permissions User->memberships->owner
  "project:read"
  "project:write"
  "member:manage"

action CurrentUser(): User
  body
    return @subject.entity

action UpdateCurrentUser(displayName?: TEXT): User
  body
    user := @subject.entity
    update user {
      displayName := displayName
    }
    return user

action ListProjects(organizationId: TEXT): Page<Project>
  body
    org := single Organization where @id == organizationId
    return pageOf Project where organization == org

trigger CurrentUser on HttpRequest
  endpoint GET /me
  auth
    @subject is @defined

trigger UpdateCurrentUser on HttpRequest
  endpoint PATCH /me
  arguments
    displayName := @request.body.displayName
  auth
    @subject is @defined

trigger ListProjects on HttpRequest
  endpoint GET /organizations/{organizationId}/projects
  arguments
    organizationId := @request.path.organizationId
  auth
    @subject can "project:read" in Organization(@request.path.organizationId)
```

## Getting the User Entity

Use `@subject.entity` when action logic needs the persisted row for the authenticated subject.

Common uses:

* Return the current user from `GET /me`.
* Update profile fields on the authenticated user.
* Compare ownership with `where owner == @subject.entity`.

When assigning ownership on create, you can assign either `owner := @subject.entity` or `owner := @subject` when the relation field points at the subject entity. The runtime resolves the subject to the stored entity before writing.

## Groups, Roles, and Permissions

Use `group @id` on an entity whose instances scope permissions, such as an `Organization`, `Team`, or `Workspace`.

Use `role <fieldName>` on the entity that carries role membership. The role field must be a non-optional enum. In the example above, `Membership.membershipRole` is the role field.

Permission statements start at a subject entity, traverse relation fields, and end at one role enum value:

`permissions User->memberships->admin`

That grants the listed permission strings to users whose `memberships` path resolves to a `Membership` with role `admin`.

## Trigger Auth Rules

Trigger `auth` blocks support these predicates:

* `@subject is @defined` for any authenticated subject.
* `@subject is @anonymous` for anonymous callers.
* `@subject is admin` for a role by name.
* `@subject is admin in Organization(@request.path.organizationId)` for a role scoped to a group instance.
* `@subject can "project:read"` for a global permission.
* `@subject can "project:read" in Organization(@request.path.organizationId)` for a permission scoped to a group instance.

You can combine predicates with `and` and `or`. Parenthesized auth subexpressions are not supported by current validation, so write combined rules without parentheses. If a trigger omits `auth`, it is public.

## Generated Auth Endpoints

When a SLang app defines a subject with an identity field, the generated app exposes standard auth endpoints for that subject model:

* `POST /register`
* `POST /login`
* `POST /refresh`
* `GET /.well-known/jwks.json`

Registration and login accept `identity` and `password`. The identity value should match the field declared by `identity <fieldName>`, such as the user's email address.
