// Remote Machine Bridge — Tauri IPC adapter for multi-machine management import { invoke } from '@tauri-apps/api/core'; import { listen, type UnlistenFn } from '@tauri-apps/api/event'; export interface RemoteMachineConfig { label: string; url: string; token: string; auto_connect: boolean; /** SPKI SHA-256 pin(s) for certificate verification. Empty = TOFU on first connect. */ spki_pins?: string[]; } export interface RemoteMachineInfo { id: string; label: string; url: string; status: string; auto_connect: boolean; /** Currently stored SPKI pin hashes (hex-encoded SHA-256) */ spki_pins: string[]; } // --- Machine management --- export async function listRemoteMachines(): Promise { return invoke('remote_list'); } export async function addRemoteMachine(config: RemoteMachineConfig): Promise { return invoke('remote_add', { config }); } export async function removeRemoteMachine(machineId: string): Promise { return invoke('remote_remove', { machineId }); } export async function connectRemoteMachine(machineId: string): Promise { return invoke('remote_connect', { machineId }); } export async function disconnectRemoteMachine(machineId: string): Promise { return invoke('remote_disconnect', { machineId }); } // --- SPKI certificate pinning --- /** Probe a relay server's TLS certificate and return its SHA-256 hash (hex-encoded). */ export async function probeSpki(url: string): Promise { return invoke('remote_probe_spki', { url }); } /** Add an SPKI pin hash to a machine's trusted pins. */ export async function addSpkiPin(machineId: string, pin: string): Promise { return invoke('remote_add_pin', { machineId, pin }); } /** Remove an SPKI pin hash from a machine's trusted pins. */ export async function removeSpkiPin(machineId: string, pin: string): Promise { return invoke('remote_remove_pin', { machineId, pin }); } // --- Remote event listeners --- export interface RemoteSidecarMessage { machineId: string; sessionId?: string; event?: Record; } export interface RemotePtyData { machineId: string; sessionId?: string; data?: string; } export interface RemotePtyExit { machineId: string; sessionId?: string; } export interface RemoteMachineEvent { machineId: string; payload?: unknown; error?: unknown; } export async function onRemoteSidecarMessage( callback: (msg: RemoteSidecarMessage) => void, ): Promise { return listen('remote-sidecar-message', (event) => { callback(event.payload); }); } export async function onRemotePtyData( callback: (msg: RemotePtyData) => void, ): Promise { return listen('remote-pty-data', (event) => { callback(event.payload); }); } export async function onRemotePtyExit( callback: (msg: RemotePtyExit) => void, ): Promise { return listen('remote-pty-exit', (event) => { callback(event.payload); }); } export async function onRemoteMachineReady( callback: (msg: RemoteMachineEvent) => void, ): Promise { return listen('remote-machine-ready', (event) => { callback(event.payload); }); } export async function onRemoteMachineDisconnected( callback: (msg: RemoteMachineEvent) => void, ): Promise { return listen('remote-machine-disconnected', (event) => { callback(event.payload); }); } export async function onRemoteStateSync( callback: (msg: RemoteMachineEvent) => void, ): Promise { return listen('remote-state-sync', (event) => { callback(event.payload); }); } export async function onRemoteError( callback: (msg: RemoteMachineEvent) => void, ): Promise { return listen('remote-error', (event) => { callback(event.payload); }); } export interface RemoteReconnectingEvent { machineId: string; backoffSecs: number; } export async function onRemoteMachineReconnecting( callback: (msg: RemoteReconnectingEvent) => void, ): Promise { return listen('remote-machine-reconnecting', (event) => { callback(event.payload); }); } export async function onRemoteMachineReconnectReady( callback: (msg: RemoteMachineEvent) => void, ): Promise { return listen('remote-machine-reconnect-ready', (event) => { callback(event.payload); }); } // --- SPKI TOFU event --- export interface RemoteSpkiTofuEvent { machineId: string; hash: string; } /** Listen for TOFU (Trust On First Use) events when a new SPKI pin is auto-stored. */ export async function onRemoteSpkiTofu( callback: (msg: RemoteSpkiTofuEvent) => void, ): Promise { return listen('remote-spki-tofu', (event) => { callback(event.payload); }); }