Unified Websocket Runtime Contract
April 15, 2026 ยท View on GitHub
For topology selection, migration, daemon install, and operator rollout guidance, see remote-websocket-rollout.md. This document specifies the wire contract itself.
The websocket runtime contract is the single execution contract shared by both websocket transport topologies:
ws_listener: the control plane dials the machine listener directlyws_reverse: the machine daemon keeps a machine-channel session open and tunnels runtime envelopes throughtype=runtime
The contract is implemented in:
- domain model:
internal/domain/websocketruntime/contracts.go - protocol server/client:
internal/infra/machinetransport/runtime_protocol.go - shared contract suite:
internal/infra/machinetransport/runtime_contract_test.go
Message Model
Every runtime frame is a JSON envelope:
{
"version": 1,
"type": "request|response|event|hello|hello_ack",
"request_id": "uuid",
"operation": "probe|preflight|workspace_prepare|workspace_reset|artifact_sync|command_open|session_input|session_signal|session_close|process_start|process_status|session_output|session_exit",
"payload": {},
"error": {
"code": "invalid_request|protocol_version|workspace|artifact_sync|preflight|session_not_found|process_start|process_signal|transport_unavailable|unauthorized|unsupported|internal",
"class": "auth|misconfiguration|transient|unsupported|internal",
"message": "human readable detail",
"retryable": false,
"details": {}
}
}
Handshake:
- Client sends
hellowith supported protocol versions and declared capabilities. - Server replies with
hello_ack, selecting one protocol version and echoing supported operations. - All later
requestmessages are scoped byrequest_idand answered by a matchingresponse. - Long-running session output and exits arrive as
eventenvelopes.
Operations
The contract covers all execution-critical runtime actions:
- Reachability and probe:
probe - Binary and CLI preflight:
preflight - Workspace lifecycle:
workspace_prepare,workspace_reset - Artifact movement:
artifact_sync - Command sessions:
command_open,session_input,session_signal,session_close - Process lifecycle:
process_start,process_status,session_output,session_exit
Upper layers should target these operations rather than branching on websocket topology.
Versioning And Compatibility
versionis mandatory on every envelope.- Runtime peers must reject unknown protocol versions with
error.code=protocol_versionanderror.class=unsupported. - New protocol revisions must be additive where possible:
- new operations may be introduced without changing existing operation semantics
- new payload fields should be optional for older peers
- removing or repurposing an existing operation requires a new protocol version
hellonegotiation is the compatibility gate. A peer may only use operations that were acknowledged inhello_ack.
Error Taxonomy
The contract separates orchestration-facing error classes from operation-specific error codes.
auth: credentials or authorization problems that require operator/user actionmisconfiguration: fixable input or environment issues such as bad workspace roots, invalid requests, or missing binariestransient: retryable runtime or transport failuresunsupported: protocol/version/capability mismatchesinternal: unexpected implementation failures
Recommended interpretation:
- UX may surface
authandmisconfigurationas user-fixable guidance - orchestrators may retry only when
retryable=true, typically fortransient unsupportedshould stop rollout until both peers are upgraded to a compatible contract
Reverse Session Recovery
Reverse websocket keeps exactly one active machine-channel runtime relay per machine.
- a newer daemon registration replaces the previous reverse runtime relay for that machine
- in-flight command or process sessions on the replaced relay terminate immediately with a transport error instead of falling back to SSH
- disconnects, heartbeat timeouts, and server shutdown close the reverse runtime client and fail in-flight sessions with a clear disconnect cause
- once the daemon reconnects, new runtime requests attach to the new relay session; upper layers decide whether to retry, but the transport contract does not silently change execution planes
Validation
TestUnifiedWebsocketRuntimeContractSuite runs the same suite against:
- a direct listener websocket runtime
- a reverse machine-channel websocket runtime participant
The suite verifies:
- handshake and version negotiation
- probe and preflight
- workspace prepare/reset
- artifact sync
- command session open/stream/close
- process start/status/interrupt/exit
TestReverseRuntimeRelayRegisterReplacesExistingClientSessions and
TestReverseRuntimeRelayRemoveDisconnectsManagedSessions cover the
replacement/disconnect semantics for reverse-connected runtime sessions.