Invitation Token

This token represents an invitation for a user to join a subscribable action, such as a conversation (CONV). Invitations enable controlled access to closed groups.

The invitation token must contain a subject (sub) field referencing the subscribable action and an audience (aud) field specifying the invited user. For other constraints see the Action Tokens.

Content-Addressing

This token is content-addressed using SHA-256:

  • The entire JWT token (header + payload + signature) is hashed
  • Action ID format: a1~{base64_hash}
  • Changing any field invalidates the action_id
  • See Content-Addressing & Merkle Trees for details

Immutability: Once created, an INVT token cannot be modified without changing its action ID.

Purpose

INVT tokens serve several important purposes:

  1. Access Control: Enable users to join closed/private groups
  2. Role Assignment: Pre-assign roles for invited users
  3. Discoverability: Notify users about groups they can join
  4. Subject Delivery: Include the subject action (CONV) with the invitation

Required Fields

Field Required Description
iss Yes The inviter’s identity (must have moderator+ role)
aud Yes The invited user’s identity
sub Yes The action_id being invited to (a1~...)
t Yes “INVT” or “INVT:DEL”
c Optional Invitation metadata (role, message)

Subtypes

Subtype Description
INVT Create a new invitation
INVT:DEL Revoke an invitation

Content Structure

The optional content (c) field contains invitation metadata:

{
  "role": "member",
  "message": "Welcome to our project discussion!"
}
Property Type Required Description
role string No Role to assign when accepting: “observer”, “member”, “moderator”, “admin”
message string No Optional invitation message

Database Key

The database key for an invitation token is {type}:{sub}:{aud}

Purpose: This key ensures that only one active invitation exists per user per subject. The key components are:

  • {type}: “INVT” (base type)
  • {sub}: Subject ID (what they’re invited to)
  • {aud}: Audience identity (who is invited)

Example:

  • Alice invites Bob to a CONV β†’ Stored with key INVT:a1~conv123:bob.example.com
  • A new invitation to the same user replaces the previous one

Permission Requirements

To create an invitation, the inviter must have appropriate permissions:

Inviter Role Can Invite
observer No
member No
moderator Yes
admin Yes

The system validates that the inviter has at least moderator-level access to the subject action.

Subject Delivery

INVT has deliver_subject=true behavior, meaning:

  • When an invitation is delivered, the subject action (e.g., CONV) is included
  • The invitee receives both the INVT and the CONV token
  • This allows the invitee to see conversation details before accepting
{
  "token": "eyJhbGciOi...INVT_TOKEN",
  "related": ["eyJhbGciOi...CONV_TOKEN"]
}

Federation Flow

Sending an Invitation

Moderator creates INVT token
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Validate permissions        β”‚
β”‚ - Check inviter has mod+    β”‚
β”‚ - Validate subject exists   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ schedule_delivery()         β”‚
β”‚ - Deliver to invitee (aud)  β”‚
β”‚ - Include subject action    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
    Invitee receives INVT + CONV

Accepting an Invitation

Invitee receives INVT + CONV
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Invitee creates SUBS token  β”‚
β”‚ - sub = CONV action_id      β”‚
β”‚ - aud = CONV owner          β”‚
β”‚ - role from INVT (optional) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SUBS sent to CONV owner     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Auto-accept logic           β”‚
β”‚ - INVT exists? β†’ Accept!    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
    Invitee is now a subscriber
    and receives messages

Revoking an Invitation

Moderator creates INVT:DEL token
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Delivered to invitee        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Original INVT marked deletedβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
    User can no longer use
    invitation to subscribe

Invitation Lifecycle

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     Create      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  None    │────────────────▢│  Active  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β–Ό              β–Ό              β–Ό
              SUBS created    INVT:DEL       Expires
                    β”‚              β”‚              β”‚
                    β–Ό              β–Ό              β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  Used    β”‚  β”‚ Revoked  β”‚  β”‚ Expired  β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Example

User @alice.cloudillo.net invites @bob.cloudillo.net to a conversation:

Field Value
iss alice.cloudillo.net
aud bob.cloudillo.net
iat 2024-04-13T00:01:10.000Z
k 20240301
t INVT
sub a1~NAado5PS4j5+abYtRpBELU0e5OQ+zGf/tuuWvUwQ6PA=
c {“role”: “member”, “message”: “Join our project discussion!”}

Delivery includes:

  • INVT token (the invitation)
  • CONV token (the conversation being invited to)

Flow:

  1. Alice (moderator or admin) creates INVT for Bob
  2. Bob receives INVT + CONV details
  3. Bob creates SUBS to accept
  4. SUBS auto-accepted because INVT exists
  5. Bob now receives messages in the conversation

See Also