OpportunitiesEntities
Docs
    Ring Platform

    Decentralized Self-building Future

    Sign In
    Entities
    Opportunities
    Store
    Docs
    Platform Concepts
    RING EconomySonoratek LLCGlobal ImpactAI Meets Web3
    Get Started
    Quick StartCalculatorRoadmap
    Privacy|Contact
    v1.104.17|Sonoratek LLC

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)
    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    WebRTC Calls & STUNner TURN

    Use Founder / Developer tabs in the docs sidebar to filter this page. Sidebar visibility is curated in lib/docs/audience-curated-docs.ts.

    Ring messenger can place 1:1 audio and video calls inside a direct conversation. Signaling rides the existing Tunnel channel conversation:{id}. Media uses the browser RTCPeerConnection. NAT traversal uses STUNner (STUN/TURN) on the cluster, with ICE servers delivered by an authenticated API — credentials never ship in NEXT_PUBLIC_*.

    LayerRole
    UIPhone / Video on conversation header → full-screen call overlay
    SignalingTunnel events call:invite … call:hangup on conversation:{id}
    ICEGET /api/webrtc/ice-servers (session required)
    TURNSTUNner Gateway TURN-UDP:3478 (e.g. turn.ring-platform.org)

    Related: Messaging · Peer Games · Tunnel Protocol · Real-time architecture

    Peer Games share a call ↔ game mutex (features/peer-games/lib/peer-game-mutex.ts). MessagesShell publishes setPeerCallBusy from the WebRTC phase so /games banner and game_request widgets refuse accept while a call is live. Cross-tab sync ships via BroadcastChannel (optional navigator.locks). Peer Games also reuse GET /api/webrtc/ice-servers for optimistic DataChannel move hints — Tunnel + DB remain board SSOT.

    Why this matters for your clone

    Members close deals faster when they can talk without leaving your Ring. Calls stay inside the same conversation that already carries opportunity, entity, or store context.

    Messaging

    Conversations, groups, and Tunnel live chat.

    Tunnel Protocol

    The realtime pipe calls reuse for invite / accept / hangup.

    Self-hosted deploy

    Where STUNner and env wiring live for k8s clones.

    Operator checklist (k3s / Ringdom cloud)

    1. STUNner control plane installed (stunner-system) and Gateway programmed in namespace stunner.

    Architecture

    Verified modules

    PathResponsibility
    app/api/webrtc/ice-servers/route.tsAuth’d ICE config from WEBRTC_* env
    features/chat/lib/fetch-ice-servers.tsClient fetch via apiClient
    features/chat/lib/call-types.tsSignal event / payload types
    hooks/use-webrtc-call.tsRTCPeerConnection + Tunnel publish/subscribe
    features/chat/components/call-overlay.tsxFull-screen controls (mute / camera / end)

    Backlog

    Related documentation

    Related documentation

    Real-Time Messaging

    Depends-on: calls start from direct conversation headers in the messenger.

    Peer Games

    Same-workflow: shared call/game mutex (BroadcastChannel); ICE route reused for optimistic DataChannel move hints.

    Tunnel Protocol

    Depends-on: call:invite … call:hangup ride conversation:{id}.

    Push Notifications with FCM (Ring-Powered)

    Same-workflow: CALL_INVITE offline OS banner (data-only FCM, 90s TTL, RFC no-op on Chrome).

    WebRTC Calls & STUNner TURN

    Use Founder / Developer tabs in the docs sidebar to filter this page. Sidebar visibility is curated in lib/docs/audience-curated-docs.ts.

    Ring messenger can place 1:1 audio and video calls inside a direct conversation. Signaling rides the existing Tunnel channel conversation:{id}. Media uses the browser RTCPeerConnection. NAT traversal uses STUNner (STUN/TURN) on the cluster, with ICE servers delivered by an authenticated API — credentials never ship in NEXT_PUBLIC_*.

    LayerRole
    UIPhone / Video on conversation header → full-screen call overlay
    SignalingTunnel events call:invite … call:hangup on conversation:{id}
    ICEGET /api/webrtc/ice-servers (session required)
    TURNSTUNner Gateway TURN-UDP:3478 (e.g. turn.ring-platform.org)

    Related: Messaging · Peer Games · Tunnel Protocol · Real-time architecture

    Peer Games share a call ↔ game mutex (features/peer-games/lib/peer-game-mutex.ts). MessagesShell publishes setPeerCallBusy from the WebRTC phase so /games banner and game_request widgets refuse accept while a call is live. Cross-tab sync ships via BroadcastChannel (optional navigator.locks). Peer Games also reuse GET /api/webrtc/ice-servers for optimistic DataChannel move hints — Tunnel + DB remain board SSOT.

    Why this matters for your clone

    Members close deals faster when they can talk without leaving your Ring. Calls stay inside the same conversation that already carries opportunity, entity, or store context.

    Messaging

    Conversations, groups, and Tunnel live chat.

    Tunnel Protocol

    The realtime pipe calls reuse for invite / accept / hangup.

    Self-hosted deploy

    Where STUNner and env wiring live for k8s clones.

    Operator checklist (k3s / Ringdom cloud)

    1. STUNner control plane installed (stunner-system) and Gateway programmed in namespace stunner.

    Architecture

    Verified modules

    PathResponsibility
    app/api/webrtc/ice-servers/route.tsAuth’d ICE config from WEBRTC_* env
    features/chat/lib/fetch-ice-servers.tsClient fetch via apiClient
    features/chat/lib/call-types.tsSignal event / payload types
    hooks/use-webrtc-call.tsRTCPeerConnection + Tunnel publish/subscribe
    features/chat/components/call-overlay.tsxFull-screen controls (mute / camera / end)

    Backlog

    Related documentation

    Related documentation

    Real-Time Messaging

    Depends-on: calls start from direct conversation headers in the messenger.

    Peer Games

    Same-workflow: shared call/game mutex (BroadcastChannel); ICE route reused for optimistic DataChannel move hints.

    Tunnel Protocol

    Depends-on: call:invite … call:hangup ride conversation:{id}.

    Push Notifications with FCM (Ring-Powered)

    Same-workflow: CALL_INVITE offline OS banner (data-only FCM, 90s TTL, RFC no-op on Chrome).

    WebRTC Calls & STUNner TURN

    Use Founder / Developer tabs in the docs sidebar to filter this page. Sidebar visibility is curated in lib/docs/audience-curated-docs.ts.

    Ring messenger can place 1:1 audio and video calls inside a direct conversation. Signaling rides the existing Tunnel channel conversation:{id}. Media uses the browser RTCPeerConnection. NAT traversal uses STUNner (STUN/TURN) on the cluster, with ICE servers delivered by an authenticated API — credentials never ship in NEXT_PUBLIC_*.

    LayerRole
    UIPhone / Video on conversation header → full-screen call overlay
    SignalingTunnel events call:invite … call:hangup on conversation:{id}
    ICEGET /api/webrtc/ice-servers (session required)
    TURNSTUNner Gateway TURN-UDP:3478 (e.g. turn.ring-platform.org)

    Related: Messaging · Peer Games · Tunnel Protocol · Real-time architecture

    Peer Games share a call ↔ game mutex (features/peer-games/lib/peer-game-mutex.ts). MessagesShell publishes setPeerCallBusy from the WebRTC phase so /games banner and game_request widgets refuse accept while a call is live. Cross-tab sync ships via BroadcastChannel (optional navigator.locks). Peer Games also reuse GET /api/webrtc/ice-servers for optimistic DataChannel move hints — Tunnel + DB remain board SSOT.

    Why this matters for your clone

    Members close deals faster when they can talk without leaving your Ring. Calls stay inside the same conversation that already carries opportunity, entity, or store context.

    Messaging

    Conversations, groups, and Tunnel live chat.

    Tunnel Protocol

    The realtime pipe calls reuse for invite / accept / hangup.

    Self-hosted deploy

    Where STUNner and env wiring live for k8s clones.

    Operator checklist (k3s / Ringdom cloud)

    1. STUNner control plane installed (stunner-system) and Gateway programmed in namespace stunner.

    Architecture

    Verified modules

    PathResponsibility
    app/api/webrtc/ice-servers/route.tsAuth’d ICE config from WEBRTC_* env
    features/chat/lib/fetch-ice-servers.tsClient fetch via apiClient
    features/chat/lib/call-types.tsSignal event / payload types
    hooks/use-webrtc-call.tsRTCPeerConnection + Tunnel publish/subscribe
    features/chat/components/call-overlay.tsxFull-screen controls (mute / camera / end)

    Backlog

    Related documentation

    Related documentation

    Real-Time Messaging

    Depends-on: calls start from direct conversation headers in the messenger.

    Peer Games

    Same-workflow: shared call/game mutex (BroadcastChannel); ICE route reused for optimistic DataChannel move hints.

    Tunnel Protocol

    Depends-on: call:invite … call:hangup ride conversation:{id}.

    Push Notifications with FCM (Ring-Powered)

    Same-workflow: CALL_INVITE offline OS banner (data-only FCM, 90s TTL, RFC no-op on Chrome).

  1. Public UDP 3478 reachable (host firewall / cloud firewall).
  2. DNS for TURN host (example production: turn.ring-platform.org A/AAAA → node LB IP).
  3. App ConfigMap / Secret wired: WEBRTC_STUN_URL, WEBRTC_TURN_URL, WEBRTC_TURN_USERNAME, WEBRTC_TURN_CREDENTIAL.
  4. Members use direct chats with Tunnel connected — Phone / Video appear in the header.
  5. Typical scenarios

    • Two matched professionals jump from text to a short voice call without switching apps.
    • A vendor clarifies an order face-to-face over video while the thread stays the SSOT.
    • Strict NATs still connect because TURN relays via STUNner (when credentials are configured).

    Calls require a live Tunnel session. If realtime is disconnected, the UI refuses to start a call — fix Tunnel first (Tunnel Protocol).

    features/chat/components/conversation-header.tsx
    Phone / Video actions (direct only)
    features/messages/components/messages-shell.tsxWires hook + overlay
    infrastructure/k3s-or/stunner/GatewayClass, GatewayConfig, Gateway manifests
    k8s/ENV-PROD-WIRING.mdProd env table for WEBRTC_*

    ICE API

    GET /api/webrtc/ice-servers — requires Auth.js session (401 if anonymous).

    Response shape (verified):

    STUN falls back to stun:stun.l.google.com:19302 when WEBRTC_STUN_URL is unset. TURN is added only when all of WEBRTC_TURN_URL, WEBRTC_TURN_USERNAME, and WEBRTC_TURN_CREDENTIAL are set.

    Env vars (verified)

    VariableWhereNotes
    WEBRTC_STUN_URLConfigMapOptional; Google STUN default in route
    WEBRTC_TURN_URLConfigMape.g. turn:turn.ring-platform.org:3478?transport=udp
    WEBRTC_TURN_USERNAMESecret ring-platform-org-secretsMatches STUNner auth Secret
    WEBRTC_TURN_CREDENTIALSecretNever NEXT_PUBLIC_*

    Examples: k8s/secrets.example.yaml, wiring notes: k8s/ENV-PROD-WIRING.md.
    env.local.template does not yet list these keys — use the k8s examples for local/prod parity.

    Tunnel signaling events

    Published on channel conversation:{conversationId} (same channel as typing):

    EventPurpose
    call:inviteOutgoing ring
    call:accept / call:rejectCallee decision
    call:offer / call:answerSDP
    call:iceICE candidates
    call:hangupTear down

    Subscribe with useTunnelChannel — do not raw-subscribe in effects (Tunnel Protocol).

    STUNner install order (k3s-or)

    1. 1

      Install operator (pulls Gateway API + STUNner CRDs):

    2. 2

      Create auth Secret (type=static, username, password) and apply infrastructure/k3s-or/stunner/gateway.yaml (GatewayClass + GatewayConfig + Gateway with protocol TURN-UDP).

    3. 3

      Wire app Secret/ConfigMap + ensure Deployment env refs for WEBRTC_TURN_USERNAME / WEBRTC_TURN_CREDENTIAL (k8s/deployment.yaml). Restart the app Deployment.

    4. 4

      Smoke: external STUN Binding to :3478; authenticated GET /api/webrtc/ice-servers; two browsers on the same direct conversation.

    Listener protocol must be TURN-UDP, not bare UDP. Realm in GatewayConfig is alphanumeric + hyphen (e.g. ring-platform-org). Empty UDPRoute backendRefs are invalid — peer TURN does not need a UDPRoute until an SFU (LiveKit) exists.

    Scope of the shipped MVP

    • In: 1:1 direct audio/video; overlay controls; ICE via server route; STUNner TURN foundation.
    • Out (see backlog): incoming call when the peer is not viewing that thread; group/multi-party; LiveKit SFU; call system messages; IPv6 TURN path hardening.

    Connect Platform’s RTVS / FastTransponder stack is not ported — only control UX patterns (mute / camera / end) were absorbed.

    Messaging API

    See-also: conversation and typing HTTP contracts.

    Real Time

    Deep-dive: TunnelProvider ownership and consumers.

    json
    
    {
      "success": true,
      "data": {
        "iceServers": [
          { "urls": "stun:…" },
          { "urls": "turn:…", "username": "…", "credential": "…" }
        ],
        "turnConfigured": true
      }
    }
  6. Public UDP 3478 reachable (host firewall / cloud firewall).
  7. DNS for TURN host (example production: turn.ring-platform.org A/AAAA → node LB IP).
  8. App ConfigMap / Secret wired: WEBRTC_STUN_URL, WEBRTC_TURN_URL, WEBRTC_TURN_USERNAME, WEBRTC_TURN_CREDENTIAL.
  9. Members use direct chats with Tunnel connected — Phone / Video appear in the header.
  10. Typical scenarios

    • Two matched professionals jump from text to a short voice call without switching apps.
    • A vendor clarifies an order face-to-face over video while the thread stays the SSOT.
    • Strict NATs still connect because TURN relays via STUNner (when credentials are configured).

    Calls require a live Tunnel session. If realtime is disconnected, the UI refuses to start a call — fix Tunnel first (Tunnel Protocol).

    features/chat/components/conversation-header.tsx
    Phone / Video actions (direct only)
    features/messages/components/messages-shell.tsxWires hook + overlay
    infrastructure/k3s-or/stunner/GatewayClass, GatewayConfig, Gateway manifests
    k8s/ENV-PROD-WIRING.mdProd env table for WEBRTC_*

    ICE API

    GET /api/webrtc/ice-servers — requires Auth.js session (401 if anonymous).

    Response shape (verified):

    STUN falls back to stun:stun.l.google.com:19302 when WEBRTC_STUN_URL is unset. TURN is added only when all of WEBRTC_TURN_URL, WEBRTC_TURN_USERNAME, and WEBRTC_TURN_CREDENTIAL are set.

    Env vars (verified)

    VariableWhereNotes
    WEBRTC_STUN_URLConfigMapOptional; Google STUN default in route
    WEBRTC_TURN_URLConfigMape.g. turn:turn.ring-platform.org:3478?transport=udp
    WEBRTC_TURN_USERNAMESecret ring-platform-org-secretsMatches STUNner auth Secret
    WEBRTC_TURN_CREDENTIALSecretNever NEXT_PUBLIC_*

    Examples: k8s/secrets.example.yaml, wiring notes: k8s/ENV-PROD-WIRING.md.
    env.local.template does not yet list these keys — use the k8s examples for local/prod parity.

    Tunnel signaling events

    Published on channel conversation:{conversationId} (same channel as typing):

    EventPurpose
    call:inviteOutgoing ring
    call:accept / call:rejectCallee decision
    call:offer / call:answerSDP
    call:iceICE candidates
    call:hangupTear down

    Subscribe with useTunnelChannel — do not raw-subscribe in effects (Tunnel Protocol).

    STUNner install order (k3s-or)

    1. 1

      Install operator (pulls Gateway API + STUNner CRDs):

    2. 2

      Create auth Secret (type=static, username, password) and apply infrastructure/k3s-or/stunner/gateway.yaml (GatewayClass + GatewayConfig + Gateway with protocol TURN-UDP).

    3. 3

      Wire app Secret/ConfigMap + ensure Deployment env refs for WEBRTC_TURN_USERNAME / WEBRTC_TURN_CREDENTIAL (k8s/deployment.yaml). Restart the app Deployment.

    4. 4

      Smoke: external STUN Binding to :3478; authenticated GET /api/webrtc/ice-servers; two browsers on the same direct conversation.

    Listener protocol must be TURN-UDP, not bare UDP. Realm in GatewayConfig is alphanumeric + hyphen (e.g. ring-platform-org). Empty UDPRoute backendRefs are invalid — peer TURN does not need a UDPRoute until an SFU (LiveKit) exists.

    Scope of the shipped MVP

    • In: 1:1 direct audio/video; overlay controls; ICE via server route; STUNner TURN foundation.
    • Out (see backlog): incoming call when the peer is not viewing that thread; group/multi-party; LiveKit SFU; call system messages; IPv6 TURN path hardening.

    Connect Platform’s RTVS / FastTransponder stack is not ported — only control UX patterns (mute / camera / end) were absorbed.

    Messaging API

    See-also: conversation and typing HTTP contracts.

    Real Time

    Deep-dive: TunnelProvider ownership and consumers.

    json
    
    {
      "success": true,
      "data": {
        "iceServers": [
          { "urls": "stun:…" },
          { "urls": "turn:…", "username": "…", "credential": "…" }
        ],
        "turnConfigured": true
      }
    }
  11. Public UDP 3478 reachable (host firewall / cloud firewall).
  12. DNS for TURN host (example production: turn.ring-platform.org A/AAAA → node LB IP).
  13. App ConfigMap / Secret wired: WEBRTC_STUN_URL, WEBRTC_TURN_URL, WEBRTC_TURN_USERNAME, WEBRTC_TURN_CREDENTIAL.
  14. Members use direct chats with Tunnel connected — Phone / Video appear in the header.
  15. Typical scenarios

    • Two matched professionals jump from text to a short voice call without switching apps.
    • A vendor clarifies an order face-to-face over video while the thread stays the SSOT.
    • Strict NATs still connect because TURN relays via STUNner (when credentials are configured).

    Calls require a live Tunnel session. If realtime is disconnected, the UI refuses to start a call — fix Tunnel first (Tunnel Protocol).

    features/chat/components/conversation-header.tsx
    Phone / Video actions (direct only)
    features/messages/components/messages-shell.tsxWires hook + overlay
    infrastructure/k3s-or/stunner/GatewayClass, GatewayConfig, Gateway manifests
    k8s/ENV-PROD-WIRING.mdProd env table for WEBRTC_*

    ICE API

    GET /api/webrtc/ice-servers — requires Auth.js session (401 if anonymous).

    Response shape (verified):

    STUN falls back to stun:stun.l.google.com:19302 when WEBRTC_STUN_URL is unset. TURN is added only when all of WEBRTC_TURN_URL, WEBRTC_TURN_USERNAME, and WEBRTC_TURN_CREDENTIAL are set.

    Env vars (verified)

    VariableWhereNotes
    WEBRTC_STUN_URLConfigMapOptional; Google STUN default in route
    WEBRTC_TURN_URLConfigMape.g. turn:turn.ring-platform.org:3478?transport=udp
    WEBRTC_TURN_USERNAMESecret ring-platform-org-secretsMatches STUNner auth Secret
    WEBRTC_TURN_CREDENTIALSecretNever NEXT_PUBLIC_*

    Examples: k8s/secrets.example.yaml, wiring notes: k8s/ENV-PROD-WIRING.md.
    env.local.template does not yet list these keys — use the k8s examples for local/prod parity.

    Tunnel signaling events

    Published on channel conversation:{conversationId} (same channel as typing):

    EventPurpose
    call:inviteOutgoing ring
    call:accept / call:rejectCallee decision
    call:offer / call:answerSDP
    call:iceICE candidates
    call:hangupTear down

    Subscribe with useTunnelChannel — do not raw-subscribe in effects (Tunnel Protocol).

    STUNner install order (k3s-or)

    1. 1

      Install operator (pulls Gateway API + STUNner CRDs):

    2. 2

      Create auth Secret (type=static, username, password) and apply infrastructure/k3s-or/stunner/gateway.yaml (GatewayClass + GatewayConfig + Gateway with protocol TURN-UDP).

    3. 3

      Wire app Secret/ConfigMap + ensure Deployment env refs for WEBRTC_TURN_USERNAME / WEBRTC_TURN_CREDENTIAL (k8s/deployment.yaml). Restart the app Deployment.

    4. 4

      Smoke: external STUN Binding to :3478; authenticated GET /api/webrtc/ice-servers; two browsers on the same direct conversation.

    Listener protocol must be TURN-UDP, not bare UDP. Realm in GatewayConfig is alphanumeric + hyphen (e.g. ring-platform-org). Empty UDPRoute backendRefs are invalid — peer TURN does not need a UDPRoute until an SFU (LiveKit) exists.

    Scope of the shipped MVP

    • In: 1:1 direct audio/video; overlay controls; ICE via server route; STUNner TURN foundation.
    • Out (see backlog): incoming call when the peer is not viewing that thread; group/multi-party; LiveKit SFU; call system messages; IPv6 TURN path hardening.

    Connect Platform’s RTVS / FastTransponder stack is not ported — only control UX patterns (mute / camera / end) were absorbed.

    Messaging API

    See-also: conversation and typing HTTP contracts.

    Real Time

    Deep-dive: TunnelProvider ownership and consumers.

    json
    
    {
      "success": true,
      "data": {
        "iceServers": [
          { "urls": "stun:…" },
          { "urls": "turn:…", "username": "…", "credential": "…" }
        ],
        "turnConfigured": true
      }
    }
    1. Docs
    2. /Features
    3. /WebRTC Calls & STUNner TURN

    Updated Aug 16, 20265 min listen

    1. Docs
    2. /Features
    3. /WebRTC Calls & STUNner TURN

    Updated Aug 16, 20265 min listen

    1. Docs
    2. /Features
    3. /WebRTC Calls & STUNner TURN

    Updated Aug 16, 20265 min listen