Entities — Versola Docs
VersolaVersola/docs
0.5.0versola.kzGitHub

Entities

Users, clients and resources — the three actors Versola is built around, and how they relate to tenants, scopes, permissions and roles

Versola is organized around the three actors of OAuth 2.0: the user (the OAuth resource owner) who owns the data, the client that wants to act on their behalf, and the resource that holds the data. Everything else in the admin console — tenants, scopes, permissions and roles — exists to describe how these three are allowed to interact.

The big picture

flowchart TB
    subgraph tenant["🏢 Tenant — configuration boundary"]
        client["📱 Client<br/><i>an application</i><br/>redirect URIs, scopes,<br/>permissions, auth flow"]
        resource["🔌 Resource<br/><i>an upstream API</i><br/>resource URI, audience,<br/>endpoints"]
        scope["🏷️ Scope<br/><i>claims released<br/>to the client</i>"]
        permission["🔑 Permission<br/><i>a set of<br/>resource endpoints</i>"]
        role["👥 Role<br/><i>a set of<br/>permissions</i>"]
    end

    owner["👤 Resource Owner<br/><i>the end user</i><br/>global identity + claims"]

    owner -->|holds roles in| tenant
    owner -->|grants access to| client
    client -->|requests| scope
    client -->|may request| resource
    resource -->|lists allowed clients in| client
    role -->|bundles| permission
    permission -->|unlocks endpoints of| resource
    client -->|carries own| permission

    style owner fill:#166534,stroke:#166534,color:#fff
    style client fill:#155e75,stroke:#e6edf3,color:#fff
    style resource fill:#155e75,stroke:#e6edf3,color:#fff
    style scope fill:#334155,stroke:#e6edf3,color:#fff
    style permission fill:#92400e,stroke:#92400e,color:#fff
    style role fill:#92400e,stroke:#92400e,color:#fff
EntityWhat it isWhere it lives
UserAn end user with an identity and claims (the OAuth resource owner)auth (global, not tenant-scoped)
ClientAn application requesting tokenscentral, inside a tenant
ResourceAn upstream API protected by edgecentral, inside a tenant
TenantThe namespace owning everything belowcentral
ScopeClaims a client may receive about the usercentral, inside a tenant
PermissionA named set of resource endpointscentral, inside a tenant
RoleA named set of permissions, assigned to userscentral, inside a tenant

Tenant — the configuration boundary

A tenant is the namespace that owns clients, resources, scopes, permissions and roles. Two tenants can each have a web-app client with no interference. A tenant may be bound to an edge deployment, and every client and resource inside it inherits that binding.

Users are deliberately not tenant-scoped: one person has one identity across the whole platform. What is tenant-scoped is their roles — a user can be an administrator in one tenant and an ordinary user in another.

The entities

  • User — the end user: their identifiers, claims, credentials and per-tenant roles, stored once in auth.
  • Client — an application requesting tokens: its identity, scopes, permissions, auth flow and logout configuration.
  • Resource — an upstream API behind edge: its identity, audience, internal/public type and the endpoints that make it up.
  • Tenant — the namespace owning clients, resources, scopes, permissions and roles.
  • Scope — a named bundle of claims a client may request about a user.
  • Permission — a named set of resource endpoints, referenced by roles and clients.
  • Role — a named set of permissions, assigned to a user per tenant.

For step-by-step registration instructions, see How To.

How a request flows through them

sequenceDiagram
    participant Owner as 👤 Resource Owner
    participant Client as 📱 Client
    participant Auth as auth
    participant Edge as edge
    participant Resource as 🔌 Resource

    Owner->>Client: Uses the application
    Client->>Auth: /authorize (scope, resource)
    Auth->>Auth: Authenticate the owner<br/>(auth flow of this client)
    Auth->>Auth: Check requested resources:<br/>client must be in resource.audience
    Auth-->>Client: Access token (aud = resource URIs)

    Client->>Edge: GET /resources/{resourceId}/orders<br/>+ access token
    Edge->>Edge: Verify signature, aud, expiry
    Edge->>Edge: Match method + path → endpoint
    Edge->>Edge: Permission check<br/>(owner roles or client permissions)
    Edge->>Edge: Evaluate allow (CEL),<br/>step-up, max age
    Edge->>Resource: Proxy request<br/>+ injected headers/query/body
    Resource-->>Edge: Response
    Edge-->>Client: Response

The two authorization gates are worth calling out separately:

  1. At token issuance (auth) — the requested resource values are checked against the registry: the resource must exist in the client’s tenant, and the client must be listed in its audience. Only then does the resource URI land in the token’s aud claim.
  2. At request time (edge) — the token’s aud must cover the resource, the matched endpoint must be reachable through the caller’s roles (or, for client_credentials, the client’s own permissions), and the endpoint’s allow expression must return true.

Because the second gate re-reads configuration from central on a refresh interval, revoking a permission or a role takes effect without reissuing any tokens.