Presence Token

This token represents an ephemeral presence indication, such as typing status or online presence. Unlike other action types, presence tokens are NOT persisted to the database - they are only forwarded via WebSocket in real-time.

The presence token must contain a subject (sub) field referencing the context (e.g., a conversation). For other constraints see the Action Tokens.

Ephemeral Nature

IMPORTANT: PRES tokens are fundamentally different from other action types:

  • NOT persisted: Not stored in the database
  • NOT content-addressed: No action_id is generated
  • Real-time only: Forwarded via WebSocket immediately
  • Short TTL: Default time-to-live of 30 seconds
  • No delivery tasks: No scheduling or retry logic

This makes PRES tokens ideal for real-time status updates that don’t need to be permanent.

Purpose

PRES tokens serve several important purposes:

  1. Typing Indicators: Show when someone is typing in a conversation
  2. Online Status: Indicate when users are online/active
  3. Activity Updates: Real-time presence in collaborative contexts
  4. Low-Overhead Updates: Frequent status changes without database writes

Fields

Field Required Description
iss Yes The user’s identity
sub Yes Context (e.g., CONV action_id)
aud Optional Specific target user (if omitted, broadcast to context)
t Yes “PRES:TYPING”, “PRES:ONLINE”, etc.
c Optional Additional metadata
a Forbidden Attachments are not allowed

Subtypes

Subtype Description
PRES:TYPING User is currently typing
PRES:ONLINE User is online/active
PRES:AWAY User is away/idle
PRES:OFFLINE User has gone offline

Additional subtypes can be defined for application-specific presence states.

Subject Reference

The sub (subject) field specifies the context for the presence update:

  • For typing indicators: the CONV action_id
  • For online status: could be a user’s profile context
  • Creates a scoped presence update

Why Subject Instead of Parent:

  • PRES doesn’t create hierarchy (unlike comments)
  • It’s contextual - “presence in this context”
  • Non-hierarchical reference semantics

Processing Flow

User starts typing
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Create PRES:TYPING token    β”‚
β”‚ - sub = CONV action_id      β”‚
β”‚ - aud = (optional recipient)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Check: Is ephemeral?        β”‚
β”‚ - Yes! (PRES is ephemeral)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Forward to WebSocket        β”‚
β”‚ - No database storage       β”‚
β”‚ - No action_id generated    β”‚
β”‚ - No delivery tasks         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Deliver to audience         β”‚
β”‚ - If aud set: single user   β”‚
β”‚ - If not: context subscribersβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Federation Flow

Local Presence (Same Instance)

User starts typing
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ WebSocket message           β”‚
β”‚ - Signed PRES token         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Broadcast to CONV           β”‚
β”‚ subscribers on same instanceβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Remote Presence (Cross-Instance)

User starts typing (instance A)
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Forward to CONV owner       β”‚
β”‚ (instance B)                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό (HTTP POST to /inbox)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Instance B receives PRES    β”‚
β”‚ - Verifies signature        β”‚
β”‚ - Does NOT store            β”‚
β”‚ - Forwards to WebSocket     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Broadcast to other          β”‚
β”‚ subscribers on instance B   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Time-To-Live (TTL)

PRES tokens have an implicit TTL:

  • Default: 30 seconds
  • After TTL expires, presence is considered stale
  • Clients should send periodic updates to maintain presence
  • No explicit expiration in the token (handled by clients)

Typing indicator flow:

  1. User starts typing β†’ PRES:TYPING sent
  2. User continues typing β†’ Periodic PRES:TYPING (e.g., every 5s)
  3. User stops typing β†’ No more updates
  4. After 30s β†’ Recipients consider typing stopped

Example

User @alice.cloudillo.net is typing in a conversation:

Field Value
iss alice.cloudillo.net
sub a1~NAado5PS4j5+abYtRpBELU0e5OQ+zGf/tuuWvUwQ6PA=
iat 2024-04-13T00:01:10.000Z
k 20240301
t PRES:TYPING

Properties:

  • No action_id generated (ephemeral)
  • Not stored in database
  • Forwarded immediately via WebSocket
  • Recipients see “Alice is typing…”
  • After 30s without update, typing indicator disappears

Security Considerations

Since PRES tokens are ephemeral:

  • Still require valid signature verification
  • Rate limiting applies to prevent spam
  • Context (subject) must be valid
  • User must have access to the context

Comparison with Persistent Actions

Aspect PRES (Ephemeral) Other Actions
Database storage No Yes
Action ID None SHA256 hash
Delivery tasks None Scheduled with retry
TTL 30 seconds Permanent (until deleted)
Use case Real-time status Permanent records

See Also