Riftix Console Bridge

Protocol Reference

All envelopes, RPC methods, events, and error codes.

Constants

NAMESPACE            = "__riftix_bridge"  // envelope tag
PROTOCOL_VERSION     = 1
DEFAULT_RPC_TIMEOUT_MS         = 10_000  // 10s
DEFAULT_HANDSHAKE_TIMEOUT_MS   = 10_000  // 10s
DEFAULT_HELLO_RETRY_INTERVAL_MS = 100    // 100ms

Envelopes

All envelopes carry __riftix_bridge: "__riftix_bridge" as a discriminator. Use isEnvelope(value) from @riftix/console-bridge-types to narrow unknown postMessage data.

hello (client → host)

{
  __riftix_bridge: "__riftix_bridge";
  kind: "hello";
  protocolVersion: 1;
  capabilities: readonly string[];
}

Sent by the client on load, retried every DEFAULT_HELLO_RETRY_INTERVAL_MS until ready is received or the handshake times out.

ready (host → client)

{
  __riftix_bridge: "__riftix_bridge";
  kind: "ready";
  protocolVersion: 1;
  capabilities: readonly string[];
  context: HostContext;
}

Carries the initial context snapshot so the client can paint before the first context:changed event.

req (client → host)

{
  __riftix_bridge: "__riftix_bridge";
  kind: "req";
  id: string;             // crypto.randomUUID()
  method: BridgeMethodName;
  payload: BridgeMethodRequest<method>;
}

res (host → client)

// Success
{
  __riftix_bridge: "__riftix_bridge";
  kind: "res";
  id: string;
  ok: true;
  data: BridgeMethodResponse<method>;
}

// Failure
{
  __riftix_bridge: "__riftix_bridge";
  kind: "res";
  id: string;
  ok: false;
  error: BridgeErrorPayload;
}

event (host → client)

{
  __riftix_bridge: "__riftix_bridge";
  kind: "event";
  event: BridgeEventName;
  payload: BridgeEventPayload<event>;
}

RPC Methods

Navigate the host shell to a route.

// Request
{ to: string; replace?: boolean }

// Response
void

Update the page title displayed in the host navbar.

// Request
{ title: string; subtitle?: string }

// Response
void

Replace the breadcrumb trail for this product in the host navbar. An empty array clears the breadcrumbs.

// Request
{ crumbs: ReadonlyArray<BridgeBreadcrumb> }

// Response
void

BridgeBreadcrumb:

{ label: string; href?: string }

This RPC is handled automatically by the host — you do not need to register a handler for it. The built-in handler calls channel._applyClientBreadcrumbs(crumbs).

Report the iframe's current URL to the host. Sent automatically by the snippet on page load and on every subsequent URL change (pushState, replaceState, popstate). You do not call this manually — it is driven by setupLocationSync inside the snippet.

// Request
{ path: string }   // pathname + search + hash, e.g. "/invoices/123?tab=summary"

// Response
void

This RPC is handled automatically by the host — you do not need to register a handler for it. The built-in handler calls channel._applyClientLocation(payload.path), which stores the path and fires any onLocationChanged subscribers (e.g. ConsoleIframe's onLocation prop).

toast.show

Show a toast notification in the host shell.

// Request
{
  message: string;
  variant?: "info" | "success" | "warning" | "error";
  durationMs?: number;
}

// Response
void

modal.confirm

Open a confirmation dialog in the host shell and return the user's choice.

// Request
{
  title: string;
  body: string;
  confirmLabel?: string;
  cancelLabel?: string;
  destructive?: boolean;
}

// Response
boolean  // true = confirmed, false = cancelled

Events

context:changed

Fired when the host context changes. Carries the full new snapshot.

payload: HostContext
// { theme: "light" | "dark"; locale: string }

authorization:changed

Fired when authorization changes, including immediately after handshake (may be null if no auth has been issued for this product yet).

payload: BridgeAuthorization | null

BridgeAuthorization:

{
  clientId:       string;   // product ID
  organizationId: string;   // tenant / organization ID
  token:          string;   // JWT or opaque bearer token
  expiresAt:      number;   // Unix ms timestamp
}

Sent by the host when it wants the running iframe to navigate to a specific path — for example when the user hits the browser back/forward buttons at the host level, or when the host URL is updated programmatically after the iframe is already running.

The snippet handles this automatically: it calls history.pushState or history.replaceState and then dispatches a synthetic popstate event so in-page routers (TanStack Router, React Router, etc.) pick up the change.

payload: {
  path:     string;    // target path within the product, e.g. "/invoices/123"
  replace?: boolean;   // true → replaceState, false/absent → pushState
}

Send from the host via channel.emit("navigation:navigate", { path, replace }) or host.broadcast("navigation:navigate", { path, replace }).


Error Codes

enum BridgeErrorCode {
  HANDSHAKE_TIMEOUT         // client: handshake not completed within 10s
  PROTOCOL_VERSION_MISMATCH // host drops hello with wrong protocolVersion
  METHOD_NOT_FOUND          // host: no handler registered for method
  INVALID_ORIGIN            // host: message from unexpected origin
  HANDLER_ERROR             // host: registered handler threw
  TIMEOUT                   // client: req timed out waiting for res
  DISCONNECTED              // channel disposed before res arrived
  INVALID_ENVELOPE          // malformed envelope shape
}

BridgeError (thrown on the client for failed RPCs):

class BridgeError extends Error {
  readonly code: BridgeErrorCode;
  readonly details: unknown;
}

On this page