YURT

YAK Unified Room Tags

Decentralized room discovery for YakApp chat rooms

v1.0.0
"Every yurt on the steppe has its own fire. Find them by the smoke, or follow the path you know. Discovery is optional. Direct access always works."

The YURT Insight

Traditional chat apps require central servers to discover rooms. YURT provides three discovery modes that work independently:

  • 1.
    Direct Link — Click a yak:// link from any website. Works immediately, no gossip needed.
  • 2.
    Website Embed — "Join Chat" buttons on websites that link to yak:// or HTTPS gateway.
  • 3.
    Gossip — Browse rooms propagated through the mesh network.

The yak:// URI Scheme

YURT uses the yak:// URI scheme for direct room links. Like clicking a Zoom link, but for decentralized chat.

yak://qrl-node.theqrl.org:8787/qrl-official

Basic format: yak://host:port/bundleId

yak://example.com/private-room?invite=eyJ0eXBlIjoiYXR0ZXN0YXRpb24i...

With invite attestation for private rooms

import { YurtLink } from 'yakmesh/mesh/yurt.js';

// Parse any yak:// link
const link = YurtLink.parse('yak://qrl-node.theqrl.org:8787/qrl-official');
console.log(link.host);     // 'qrl-node.theqrl.org'
console.log(link.port);     // 8787
console.log(link.bundleId); // 'qrl-official'
console.log(link.invite);   // null (or attestation object if present)

// Create a yak:// link
const uri = YurtLink.create('my-node.example.com', 'my-room');
// → 'yak://my-node.example.com/my-room'

// Browser fallback (for browsers without yak:// handler)
const httpsUrl = YurtLink.toHttpsGateway(uri);
// → 'https://yak.to/join/my-node.example.com:8787/my-room'

Discovery Modes

Direct Link

The simplest path. User clicks a link, app connects directly to the host node. No gossip propagation required.

Use case: QRL posts "Join Official Chat" on theqrl.org

Website Embed

Websites embed join buttons. Works with yak:// for native apps or HTTPS gateway for browsers.

Use case: Project documentation with "Chat with us" button

Gossip Propagation

Rooms are advertised through the mesh. Users can browse and search for public rooms.

Use case: Discovering new communities in the network

QR Code

QR codes encode yak:// URIs. Scan to join rooms at events, conferences, or physical locations.

Use case: Conference networking, local meetups

Room Entries

A YurtEntry represents a discoverable room listing. Entries are signed by the host node and can be propagated via gossip or accessed directly.

import { YurtEntry, YURT_CONFIG } from 'yakmesh/mesh/yurt.js';

// Create a room entry
const entry = new YurtEntry({
  bundleId: 'qrl-official',
  hostNodeId: myNode.identity.nodeId,
  hostEndpoint: 'qrl-node.theqrl.org:8787',
  name: 'QRL Official',
  description: 'Official Quantum Resistant Ledger community chat',
  visibility: YURT_CONFIG.visibility.PUBLIC,
  tags: ['qrl', 'crypto', 'quantum', 'official'],
  memberCount: 500,
});

// Sign with host's secret key (proves ownership)
entry.sign(myNode.identity.secretKey);

// Generate shareable link
const link = entry.toUri();
// → 'yak://qrl-node.theqrl.org:8787/qrl-official'

// For invite-only rooms, include attestation
const inviteLink = entry.toInviteUri(attestation);
// → 'yak://...?invite=...'

Visibility Types

Type Badge Gossip Direct Link Access
public PUBLIC ✓ Propagated ✓ Works Anyone can request to join
invite-only INVITE ✓ Propagated ✓ Works Requires GUMBA attestation
unlisted UNLISTED ✗ Not shared ✓ Works Only via direct link sharing

Local Directory

The YurtDirectory maintains a local index of known rooms. It handles searching, indexing by tags/host, and automatic cleanup of expired entries.

import { YurtDirectory } from 'yakmesh/mesh/yurt.js';

const directory = new YurtDirectory();

// Add entries (from gossip or manual)
directory.add(entry);

// Search rooms
const results = directory.search({ 
  query: 'QRL', 
  tags: ['crypto'],
  visibility: 'public',
  limit: 20,
});

// Get by bundle ID
const room = directory.getByBundle('qrl-official');

// List all public rooms
const publicRooms = directory.listPublic(100);

// Get rooms by a specific host
const qrlRooms = directory.getByHost(qrlNodeId);

// Manual cleanup of expired entries
directory.cleanup();

Gossip Propagation

The YurtGossip module handles advertising rooms to the mesh network. Entries expire after 7 days without refresh, preventing stale listings.

import { YurtGossip, YurtDirectory } from 'yakmesh/mesh/yurt.js';

const directory = new YurtDirectory();
const gossip = new YurtGossip(identity, directory, mesh);

// Start gossip (periodic announcements + refresh)
gossip.start();

// Announce a new room
gossip.announce(entry);

// Search the network
const queryId = gossip.query({ query: 'QRL', tags: ['crypto'] });
gossip.on('query:response', (response) => {
  console.log('Found rooms:', response.entries);
});

// Withdraw a room from the network
gossip.withdraw('my-bundle-id');

// Stop gossip
gossip.stop();

Integration with GUMBA

YURT handles discovery. GUMBA handles access control. They work together seamlessly.

The Complete Flow

  1. 1
    Discovery — User finds room via YURT (link, gossip, or embed)
  2. 2
    Connect — App connects to host node at the endpoint
  3. 3
    Challenge — Host issues GUMBA challenge to visitor
  4. 4
    Proof — Visitor proves identity (challenge-response, attestation, or Merkle)
  5. 5
    Session — Host grants session, messages delivered via ANNEX

YurtHub

YurtHub combines directory, gossip, and GUMBA integration into one convenient interface.

import { YurtHub } from 'yakmesh/mesh/yurt.js';

const hub = new YurtHub(identity, gumbaHub, mesh, options);
hub.start();

// Publish a room from your GUMBA hub
hub.publishRoom('my-bundle-id', {
  name: 'My Awesome Room',
  description: 'A great place to chat',
  visibility: 'public',
  tags: ['community', 'tech'],
});

// Browse public rooms
const rooms = hub.browse({ limit: 50 });

// Search by query
const results = hub.search('crypto', { tags: ['qrl'] });

// Join via direct link
const joinResult = await hub.joinViaLink('yak://example.com/room-id');

// Get a shareable link
const link = hub.getJoinLink('my-bundle-id');

// With invite for private rooms
const inviteLink = hub.getJoinLink('private-room', { invite: attestation });

Real-World Example: QRL Official

Setting Up the QRL Community Room

// On the QRL server (qrl-node.theqrl.org)
import { YurtHub, YurtEntry } from 'yakmesh/mesh/yurt.js';
import { GumbaHub } from 'yakmesh/mesh/gumba.js';

// Create the GUMBA bundle for the room
const gumbaHub = new GumbaHub(identity, annex);
const bundle = gumbaHub.createBundle('qrl-official', {
  name: 'QRL Official',
  description: 'Official Quantum Resistant Ledger community',
});

// Create the YURT hub and publish the room
const yurtHub = new YurtHub(identity, gumbaHub, mesh, {
  endpoint: 'qrl-node.theqrl.org:8787',
});
yurtHub.start();

yurtHub.publishRoom('qrl-official', {
  name: 'QRL Official',
  description: 'Official Quantum Resistant Ledger community chat',
  tags: ['qrl', 'crypto', 'quantum', 'official'],
  visibility: 'public',
});

// Get the link to post on theqrl.org
const joinLink = yurtHub.getJoinLink('qrl-official');
console.log('Post this on the website:', joinLink);
// → yak://qrl-node.theqrl.org:8787/qrl-official

Now QRL can add a "Join Official Chat" button on their website that links directly to the room. Users with YakApp installed get a native experience. Browser users can use the HTTPS gateway.

Security Considerations

All entries are signed

Only the hosting node can create valid entries for its rooms. Signatures are verified before adding to directories.

Discovery ≠ Access

Finding a room in YURT doesn't grant access. GUMBA proofs are still required. YURT only handles visibility.

Spam dies naturally

Unsigned or invalid entries are rejected. Stale entries expire after 7 days. Nodes can filter by reputation.

Unlisted rooms are truly private

Rooms marked as "unlisted" never enter the gossip network. They only exist via direct link sharing.

Himalayan Protocol Family

YURT is part of the Himalayan Protocol Family for secure, decentralized communication:

  • ANNEX — E2E encrypted channels for content delivery
  • DOKO — Identity certificates for membership
  • GUMBA — Proof-based access control
  • YURT — Room discovery (this module)