import { describe, test, expect } from 'vitest' import { createMuxSession, type MuxSession } from '../../mux/mux-session.js' import { createRelayNode } from '../../data-plane/relay-node.js' import { loadDataPlaneConfig } from '../../data-plane/config.js' import type { AgentListener, AgentTunnel } from '../../data-plane/agent-listener.js' import type { UpgradeDecision, UpgradeRequest } from '../../data-plane/upgrade.js' const config = loadDataPlaneConfig({ BASE_DOMAIN: 'term.example.com', TLS_CERT_PATH: '/c', TLS_KEY_PATH: '/k', AGENT_CA_CERT_PATH: '/ca', RELAY_NODE_ID: 'node-1', }) const noSchedule = () => ({ cancel: () => {} }) /** Build a real relay↔agent MuxSession pair; the agent echoes each DATA payload back verbatim. */ function wiredTunnel(hostId: string): AgentTunnel { let agent!: MuxSession const relay = createMuxSession({ role: 'relay', sendWire: (f) => agent.onWire(f), onOpen: () => {}, onData: () => {}, onClose: () => {}, onDead: () => {}, maxFrameBytes: 1024, initialWindowBytes: 1_000_000, schedule: noSchedule, }) agent = createMuxSession({ role: 'agent', sendWire: (f) => relay.onWire(f), onOpen: (_open, stream) => { // The agent dials its local ws://127.0.0.1:3000 (here: an echo) — OPAQUE bytes only. stream.onData((bytes) => stream.writeData(bytes)) }, onData: () => {}, onClose: () => {}, onDead: () => {}, maxFrameBytes: 1024, initialWindowBytes: 1_000_000, schedule: noSchedule, }) return { hostId, accountId: 'acct-1', session: relay, closeTunnel: () => relay.close() } } function listenerWith(tunnels: Map): AgentListener { return { attach: () => {}, tunnels: () => tunnels, close: () => {} } } function browserWs() { let onMsg: ((b: Uint8Array) => void) | null = null return { sent: [] as Uint8Array[], closedWith: undefined as number | undefined, send(b: Uint8Array) { this.sent.push(b) }, close(code?: number) { this.closedWith = code }, onMessage(h: (b: Uint8Array) => void) { onMsg = h }, onClose() {}, type: (b: Uint8Array) => onMsg?.(b), } } function okDecision(hostId: string): UpgradeDecision { return { ok: true, hostId, acceptedSubprotocol: 'term.relay.v1', open: { streamId: 0, subdomain: 'alice', requestPath: '/', originHeader: 'o', remoteAddrHash: 'h', capabilityTokenRef: 'jti' }, } } describe('data-plane integration (T13) — end-to-end opaque splice through a real MuxSession pair', () => { test('INV2: bytes round-trip browser → agent → browser byte-identical, never parsed', async () => { const tunnels = new Map([['host-A', wiredTunnel('host-A')]]) const node = createRelayNode({ config, listener: listenerWith(tunnels), authorize: async () => okDecision('host-A') }) const ws = browserWs() await node.handleBrowserUpgrade({} as UpgradeRequest, ws) const payload = new TextEncoder().encode('echo-me-🔒-ciphertext') ws.type(payload) expect(ws.sent).toHaveLength(1) expect([...ws.sent[0]!]).toEqual([...payload]) // opaque round-trip }) test('INV1: an upgrade authorized for a host not on this node cannot reach any tunnel', async () => { const tunnels = new Map([['host-A', wiredTunnel('host-A')]]) const node = createRelayNode({ config, listener: listenerWith(tunnels), authorize: async () => okDecision('host-B') }) const ws = browserWs() await node.handleBrowserUpgrade({} as UpgradeRequest, ws) expect(ws.closedWith).toBe(1013) // no tunnel for host-B; A is never reachable by another host's token expect(ws.sent).toHaveLength(0) }) })