Subscription Token
This token represents a subscription to a subscribable action, such as a conversation (CONV). Subscriptions control who receives messages and updates from group activities.
The subscription token must contain both a subject (sub) field referencing the subscribable action and an audience (aud) field specifying the owner of that action. For other constraints see the Action Tokens. Like every action token it is content-addressed — see Content Addressing.
Purpose
A SUBS token records that one profile is a participant in one subscribable action: it is the membership list, the delivery list and the role assignment all at once, and creating or deleting it is how a user joins or leaves.
Required Fields
| Field | Required | Description |
|---|---|---|
| iss | Yes | The subscriber’s identity |
| aud | Yes | The owner of the subject action (e.g., CONV creator) |
| sub | Yes | The action_id being subscribed to (a1~...) |
| t | Yes | “SUBS”, “SUBS:UPD”, or “SUBS:DEL” |
| c | Optional | Subscription metadata (role, invitedBy, message) |
Subtypes
| Subtype | Description |
|---|---|
| SUBS | Create a new subscription (join) |
| SUBS:UPD | Update subscription (change role) |
| SUBS:DEL | Delete subscription (leave) |
Content Structure
The optional content (c) field contains subscription metadata:
{
"role": "member",
"invitedBy": "alice.cloudillo.net",
"message": "Joining the team discussion"
}| Property | Type | Required | Description |
|---|---|---|---|
| role | string | No | Participant role: “observer”, “member”, “moderator”, “admin” |
| invitedBy | string | No | Identity of the user who invited this subscriber |
| message | string | No | Optional message when joining |
Note
The authoritative role is stored server-side as x.role (extensible metadata, not in the signed JWT). The subject owner assigns it — e.g. the CONV creator’s auto-subscription gets x.role: "admin", and an INVT acceptance creates a SUBS with x.role: "member". A role in the content payload is only used as a fallback. The default role for a plain subscription is member.
Database Key
The database key for a subscription token is {type}:{sub}:{iss}
This ensures only one active subscription per user per subject — see Database Keys. Example: SUBS:a1~conv123:alice.example.com.
Auto-Accept Logic
When a SUBS token is received, on_receive (crates/cloudillo-action/src/native_hooks/subs.rs:59) walks a fixed decision tree. The first branch that matches wins.
flowchart TD
S[SUBS received] --> O{"Target has the 'O' (open) flag?"}
O -- yes --> A["Accept, status 'A'"]
O -- no --> I{"Invitation on record for this issuer?"}
I -- yes --> A
I -- no --> C{"Issuer is the target action's creator?"}
C -- yes --> A
C -- no --> P{"Arrived pre-approved (bundled under an owner APRV)?"}
P -- yes --> A
P -- no --> R["Reject, status 'D'"]
The pre-approved branch (subs.rs:117-124) is what lets a member node accept a subscription belonging to somebody it has never met. When a container owner vouches for an accepted child, the child travels bundled under the owner’s APRV as its related token; the receiving node has no local invitation and the issuer is not the creator, but the owner’s approval already answers the question. See Related Action Bundling and the worked example in Walkthrough — A Conversation in a Community.
Accepting also retires any outstanding invitation for that subject, so a consumed invitation no longer counts as pending. If no branch matches, the subscription rests at status 'D'.
Participant Roles
Each role is a superset of the one below it. Default role is member.
| Role | Additional permissions |
|---|---|
| observer | Read only |
| member | + write (send messages) |
| moderator | + invite/remove members |
| admin | + manage conversation settings |
Warning
These are not community roles. The four roles above are subscription roles — they live on a single SUBS, in server-side x.role (crates/cloudillo-action/src/helpers.rs:222-243), and they say what you may do inside one conversation. Community membership uses a separate, longer hierarchy — public, follower, supporter, contributor, moderator, leader (crates/cloudillo-types/src/roles.rs:15-16) — stored in the profile’s roles column, saying what you may do in the community as a whole. The two overlap only in the word “moderator”, and neither implies the other: a community moderator with no SUBS is not in the conversation at all. See Communities.
Federation Flow
Subscribing to a Conversation
User creates SUBS token
│
▼
┌─────────────────────────────┐
│ Local processing │
│ - Validate subject exists │
│ - Check for INVT or 'O' │
└───────────┬─────────────────┘
│
▼
┌─────────────────────────────┐
│ schedule_delivery() │
│ - Send to subject owner │
└───────────┬─────────────────┘
│
▼
Owner receives SUBS
│
▼
┌─────────────────────────────┐
│ on_receive hook │
│ - Check auto-accept logic │
│ - Accept or reject │
│ - Update subscription list │
└─────────────────────────────┘Message Fan-Out and Leaving
Once subscribed, messages are delivered via schedule_subscriber_fanout() which walks the parent chain to the CONV and delivers to all subscribers. See Subscriber Fan-Out for details.
To leave, the user creates a SUBS:DEL token. The subject owner marks the subscription as deleted and removes the user from the subscriber list.
Example
User @bob.cloudillo.net subscribes to a conversation owned by @alice.cloudillo.net:
| Field | Value |
|---|---|
| iss | bob.cloudillo.net |
| aud | alice.cloudillo.net |
| iat | 2024-04-13T00:01:10.000Z |
| k | 20240301 |
| t | SUBS |
| sub | a1~NAado5PS4j5+abYtRpBELU0e5OQ+zGf/tuuWvUwQ6PA= |
| c | {“role”: “member”, “invitedBy”: “alice.cloudillo.net”} |
Status Values
| Status | Description |
|---|---|
| A (Active) | Subscription is active, user receives messages |
| D (Deleted/Rejected) | User left, was removed, or the subscription was rejected (no invitation, not open) |
See Also
- Walkthrough — A Conversation in a Community - SUBS in a full federated story
- Conversation Token - Subscribable group conversations
- Invitation Token - Inviting users to subscribe
- Message Token - Messages delivered to subscribers
- Federation Architecture - How messages are distributed to subscribers