UCAN Token Architecture
Sthalam uses UCAN (User Controlled Authorization Networks) tokens for capability-based access control. Unlike traditional permission systems that require centralized servers to check access rights, UCAN tokens are self-contained authorization certificates that encode all permission logic directly in the token structure.
Token Verbosity for Sync Intelligence
Section titled “Token Verbosity for Sync Intelligence”The key innovation in Sthalam is using UCAN token verbosity to enable intelligent, decentralized sync decision-making. By parsing capability strings in tokens, viewers automatically know:
- What to sync: Extract resource/folder IDs from capabilities
- What to merge: Write permissions enable bidirectional synchronization
- What to ignore: Read-only permissions indicate one-way data flow
- Document-specific behavior: Different permissions for content vs. comments vs. submissions
This eliminates the need for a centralized permission server—the tokens themselves contain all the logic needed for correct sync behavior.
3-Document Architecture
Section titled “3-Document Architecture”
Every Sthalam resource (website, post, newsletter) uses three separate Yjs documents with distinct permission models:
1. blocksuite_doc (Main Content)
Section titled “1. blocksuite_doc (Main Content)”Purpose: Website structure, blog posts, newsletter content
Viewer Permission: crud/read (read-only)
UCAN Capability:
sthalam:resource:abc123:blocksuite_doc - crud/readSync Behavior (Local-First + State Vector Sync):
- First time: Full resource sent to viewer
- Viewer renders: Always from local
blocksuite_docfirst (instant load) - Background sync: Viewer sends state vector to node
- Publisher edits → Writes to local first, syncs via state vector exchange
- State vector exchange: Viewer sends state vector, node responds with missing CRDT diffs
- Apply updates: Viewer applies CRDT diffs to local copy
- One-way state vector flow: Publisher writes local & syncs via state vectors, viewer receives diffs via state vector exchange
Use Case: Main website content that viewers read but cannot modify
2. thread_comments_doc (Collaborative Comments)
Section titled “2. thread_comments_doc (Collaborative Comments)”Purpose: Real-time comment threads and discussions between publisher and multiple viewers. A single document can have multiple independent threads (e.g., separate discussions for different sections)
Viewer Permission: crud/write (bidirectional)
UCAN Capability:
sthalam:resource:abc123:thread_comments_doc - crud/writeSync Behavior (Local-First + State Vector Multi-Thread):
- First time: Full resource sent
- Render: Always from local
thread_comments_docfirst (instant load) - Write to local: Comments written to LOCAL Yjs doc first (instant UI update)
- State vector exchange: All participants send state vectors, receive only missing CRDT diffs
- Bidirectional: Both viewer and node exchange state vectors and respond with diffs
- Any participant writes → Writes to local with
thread_id, syncs via state vector - Apply updates: CRDT diffs applied to local copy
- Client-side filtering → Comments filtered by
thread_idfor display - All can read and write to any thread
- Multi-participant state vector flow: All write local, exchange state vectors, receive only missing diffs
- Viewers see each other’s comments: Multiple viewers collaborate across all threads via state vector sync
- Never full doc: Only state vectors and CRDT diffs exchanged
Use Case: Collaborative discussions where publisher and multiple viewers contribute across multiple independent threads, with viewers able to discuss with each other in organized topic-specific conversations. All sync happens via efficient state vector-based CRDT protocol - comments written to local first for instant UI, then synced in background.
3. form_submissions_doc (Submissions)
Section titled “3. form_submissions_doc (Submissions)”Purpose: Form responses and feedback collection. A single document can have multiple forms (e.g., contact form, feedback form, survey) differentiated by form_id, with field metadata for parsing
Viewer Permission: crud/append (append-only)
UCAN Capability:
sthalam:resource:abc123:form_submissions_doc - crud/appendSync Behavior (Local-First + Incremental Multi-Form):
- First time: Full resource sent to publisher (viewers don’t receive this doc)
- Publisher renders: Always from local
form_submissions_docfirst (instant load) - Viewer fills form → Pushes incremental CRDT update with
form_idand field metadata (append operation) - Node stores incremental diff
- Publisher background poll → Pulls only incremental diffs, not full doc
- Apply updates: Publisher applies CRDT diffs to local copy
- Filter by form_id: Display submissions grouped by form
- Parse with metadata: Use field
parse_asfor structured display - No updates back to viewer (append-only, viewer never pulls)
- One-way incremental push and pull: Viewer pushes diffs to node, publisher polls and pulls diffs, no return sync
Use Case: Collecting feedback across multiple forms without exposing other viewers’ submissions. All forms stored in single doc, organized by form_id with field metadata for parsing.
UCAN Token Structure
Section titled “UCAN Token Structure”Folder-Level Token
Section titled “Folder-Level Token”When publishers generate connection strings, they create folder tokens:
{ "alg": "EdDSA", "typ": "JWT", "aud": "*", "cap": { "sthalam:folder:folder_uuid": { "view/public": [{}] } }, "exp": 1759045632, "iss": "publisher_did", "ucv": "0.10.0-canary"}Key Properties:
- Wildcard Audience:
*allows anyone with the token - Public View:
view/publiccapability for folder access - 30-Day Expiry: Reasonable validity period for sharing
- Folder Scope: Grants access to all resources in folder
Resource-Level Token
Section titled “Resource-Level Token”When nodes prepare resources for viewers, they generate resource-specific tokens:
{ "alg": "EdDSA", "typ": "JWT", "aud": "viewer_did", "cap": { "sthalam:resource:abc123:blocksuite_doc": { "crud/read": [{}] }, "sthalam:resource:abc123:thread_comments_doc": { "crud/write": [{}] }, "sthalam:resource:abc123:form_submissions_doc": { "crud/append": [{}] } }, "exp": 2702046588, "iss": "publisher_did", "prf": ["folder_token_cid"], "ucv": "0.10.0-canary"}Key Properties:
- Specific Audience: Targeted to viewer’s DID
- Multiple Capabilities: One capability per document type
- Granular Permissions: Different access levels per document
- Proof Chain: Links back to folder token for validation
- Long Lifetime: 30-year validity for persistent access
Token Parsing for Sync Decisions
Section titled “Token Parsing for Sync Decisions”The verbosity of capability strings enables automatic sync behavior:
Extracting Resource IDs
Section titled “Extracting Resource IDs”From capability strings like:
sthalam:resource:abc123:blocksuite_docsthalam:resource:abc123:thread_comments_docsthalam:resource:abc123:form_submissions_docThe system extracts:
- Domain:
sthalam - Resource Type:
resource - Resource ID:
abc123 - Document Type:
blocksuite_doc,thread_comments_doc,form_submissions_doc
Code Reference (crypto_utils/src/ucan_utils.rs:456-499):
pub fn extract_resource_id_from_ucan(ucan: &Ucan) -> Result<String, UcanError> { for capability in ucan.capabilities().iter() { let cap_resource = capability.resource;
if cap_resource.contains(":resource:") { let parts: Vec<&str> = cap_resource.split(':').collect();
// Supports: // - "domain:resource:resource_id" (3 parts) // - "domain:resource:resource_id:doc_type" (4 parts) if parts.len() >= 3 && parts[1] == "resource" { let resource_id = parts[2]; return Ok(resource_id.to_string()); } } } Err(UcanError::CapabilityNotFound)}Determining Sync Behavior
Section titled “Determining Sync Behavior”By checking the ability field for each document:
crud/read:
- Viewer renders from local first (instant)
- Viewer sends state vector to node in background
- Node responds with missing CRDT diffs
- Viewer does not write modifications
- Unidirectional state vector sync: Publisher writes & syncs via state vectors, viewer receives diffs
crud/write:
- All participants write to local first (instant UI update)
- All participants exchange state vectors with node
- Node responds with only missing CRDT diffs
- All participants send their own CRDT diffs node doesn’t have
- Bidirectional state vector sync: All write local, exchange state vectors, receive only missing diffs
- Never full doc: Only state vectors and diffs transferred
crud/append:
- Viewer pushes incremental append operations to node
- Viewer does not sync this doc (append-only, no reads)
- Publisher syncs via state vectors to receive submissions
- Unidirectional: Viewer pushes diffs, publisher receives via state vector sync
Permission Validation During Sync
Section titled “Permission Validation During Sync”Every sync message includes the resource UCAN for validation:
Node Validates Incoming Updates (network/src/p2p/website_handler.rs:866-963):
async fn process_viewer_comments_update( &self, resource_id: String, resource_ucan: String, sync_data: String,) -> P2PResult<()> { // 1. Validate resource UCAN structure let ucan = crypto_utils::ucan_utils::validate_structure(&resource_ucan).await?;
// 2. Extract resource_id and verify match let ucan_resource_id = crypto_utils::ucan_utils::extract_resource_id_from_ucan(&ucan)?; if ucan_resource_id != resource_id { return Err("Resource ID mismatch"); }
// 3. Check capability (implicit: must have crud/write or crud/append) // 4. Apply updates only if UCAN is valid services::apply_updates(&resource_id, &sync_data, &local_user.id, repo_ctx, &crypto_utils).await?;}Viewer Validates Received Updates: Similar validation on viewer side ensures updates come from authorized publisher.
Capability-Based Access Control
Section titled “Capability-Based Access Control”Why UCAN Over Traditional ACLs?
Section titled “Why UCAN Over Traditional ACLs?”Traditional ACL Systems:
- Require centralized permission server
- Must query server for every operation
- Single point of failure
- Network latency for permission checks
UCAN-Based System:
- Self-contained authorization
- No server queries needed
- Offline verification possible
- Cryptographic proof of authority
Proof Chains
Section titled “Proof Chains”Resource tokens chain back to folder tokens, which chain to publisher’s root:
Publisher Root Authority ↓ (issues)Folder Token (view/public for folder_uuid) ↓ (delegates)Resource Token (crud/read + crud/write + crud/append for resource_uuid) ↓ (presented by)ViewerEach link in the chain is cryptographically signed, creating an audit trail back to the root authority.
Implementation Benefits
Section titled “Implementation Benefits”Decentralized Permission Logic
Section titled “Decentralized Permission Logic”No centralized permission server required—viewers autonomously determine correct sync behavior by parsing their UCAN tokens.
Explicit vs. Implicit Permissions
Section titled “Explicit vs. Implicit Permissions”Explicit: Each document type has explicit capability string
- Easy to audit and understand
- Clear permission boundaries
- No ambiguity in what’s allowed
Implicit (traditional): Permissions inferred from context
- Harder to debug permission issues
- Potential for unintended access
- Requires centralized interpretation
Fine-Grained Control
Section titled “Fine-Grained Control”Different permissions per document type enable nuanced publishing models:
- Public content with moderated comment discussions between multiple viewers
- Read-only newsletters with feedback forms
- Interactive websites with multi-viewer participation and collaboration
Security Properties
Section titled “Security Properties”Token Validation: Every sync operation validates UCAN signature and expiration
Proof Chain Integrity: Resource tokens chain cryptographically to folder tokens
Permission Isolation: Different documents can have different access levels
Capability Confinement: Viewers can only perform actions explicitly granted in token
Offline Verification: UCAN validation works without network access to permission server
What This Enables
Section titled “What This Enables”- Intelligent Sync: Viewers automatically know how to sync each document type
- Decentralized Access Control: No centralized permission server needed
- Flexible Publishing Models: Mix read-only content with interactive features
- Audit Trails: Proof chains provide cryptographic audit of delegation
- Offline Operation: Permission validation works without network connectivity
Future Possibilities
Section titled “Future Possibilities”The UCAN token architecture’s flexibility enables interesting future possibilities like viewer-owned documents and interactive bidirectional workflows.
See Future Concepts for exploratory ideas about how UCAN could enable new sovereign application models.