Concepts

How Thuum works

Domains, App Keys, tokens, claims, brokers and topics, and how one request is authorized.

The pieces#

ConceptWhat it is
DomainYour tenant, identified by a slug (acme). Every URL starts with it: /api/acme/…. Its keys, claims and data are isolated from every other Domain.
App KeyA secret credential of your Domain: an identity and a token lifetime. It grants nothing by itself, cannot be modified, and is shown in full only when created.
TokenA short-lived bearer credential exchanged from an App Key. Every REST request and WebSocket handshake presents one.
ClaimA named, reusable set of permissions linked to App Keys. There is one kind per area: Domain Claims, Event Broker claims, State Broker claims.
BrokerA real-time service: the Event Broker (events) and the State Broker (states). Each has its own REST routes, WebSocket and topics.
TopicWhere data lives in a broker: chat, chat:lobby, orders:1042. Levels are joined by : and form a hierarchy.

App Keys#

An App Key is 80 lowercase hex characters: a 16-character selector, which is public and identifies the key in lists and URLs, followed by a 64-character secret.

Text
3f9c1a7be04d52aa  9d0e…(64 hex)…41c7
└── selector ───┘ └──── secret ────┘
  • Thuum stores only a keyed hash of the key. Lose it and you create a new one.
  • Its token TTL (1 second to 24 hours, 30 seconds by default) is how long tokens minted from it live.
  • It is immutable: to change its name or TTL, create a new key and move the claim links to it (the console's Renew).
  • It cannot be deleted while it is linked to a claim.

Tokens#

POST /api/{domain}/token with an App Key returns a token (a signed JWT) and its lifetime:

JSON
{ "data": { "token": "eyJhbGciOi…", "token_type": "Bearer", "expires_in": 30 } }
  • Present it as Authorization: Bearer <token> on REST requests, or as ?token= when opening a WebSocket (browsers cannot set headers on WebSockets).
  • It always expires, and cannot be refreshed: exchange the key again.
  • It is a reference, not a bag of permissions: its subject is the key's selector. Permissions are looked up from the key's claims on every REST request, so changes apply immediately.
  • A WebSocket checks the token once, at the handshake, and takes a snapshot of the claims. The connection outlives the token; reconnect to pick up permission changes.

Claims#

A key has at most one claim of each kind:

Claim kindGrants
Domain ClaimManagement, per protocol: domain (App Keys, Domain Claims), event and state (their claims).
Event Broker claimEvent Broker access: retention configs (topic_flags) and data, per Main Topic.
State Broker claimState Broker access: TTL and size configs (topic_flags) and states, per Main Topic.

Permissions are bit flags, P W S R, the same everywhere. Details in Claims and permissions.

Brokers#

The two brokers are independent: their topics, data, claims and WebSockets are separate. chat in the Event Broker has nothing to do with chat in the State Broker.

Event BrokerState Broker
UnitAn event: type + JSON data, immutableA state: key → JSON value, with a version
Writepublishset, merge (JSON Merge Patch), delete, echo
Liveevery event, to subscribers of the topic's familyevery change, to subscribers of the topic's family
Readhistory, newest first, within a retention windowone key, or a listing of a topic's subtree
Keptthe newest events, by count and agethe current value only, optionally with a TTL
WebSocket/api/{domain}/event/connect/api/{domain}/state/connect
REST/api/{domain}/event/…/api/{domain}/state/…

Read more: Event Broker, State Broker.

How a request is authorized#

Every request with a token goes through the same steps:

  1. Domain: it must exist (404) and be active (403).
  2. Token: valid signature, not expired, and its key still exists in this Domain (401).
  3. Claim: the claim the route needs, looked up from the key's links. Management routes use the Domain Claim's protocol; data routes use the broker claim. No linked claim: 403.
  4. Flag: the bit the operation needs, on the topic's Main Topic. Missing: 403.

On a WebSocket, steps 1–3 run at the handshake and step 4 on every operation, answered with an :error reply rather than closing the connection.

Responsibilities#

ThuumYou
WebSocket servers, fan-out, delivery to every subscriberKeep App Keys on your servers; give browsers tokens
Authentication of tokens, authorization by claims, tenant isolationDecide which of your users may get a token (Thuum doesn't know your users)
Retention, pruning, versioning, atomic mergesValidate the data you read: anyone with write access can write anything
History for catch-upReconnect, catch up, de-duplicate (guide)