M1 (headless core) of the VirtualHere passthrough plugin: operator-authored rules bracket a
USB-over-IP binding around a punktfunk session, so a wheel/HOTAS/pad on the couch shows up on
the host while streaming and returns the moment it stops.
Integration only — nothing from VirtualHere is vendored, bundled or downloaded; the plugin
drives a client the operator installs and licenses themselves.
The transport is platform-split, on M0 spike evidence (2026-07-30, RTX box, client v6.0.2):
- Windows speaks \\.\pipe\vhclient directly. LocalService — the runner's principal —
round-trips it (HELP 2166 B, LIST 258 B, identical to an admin baseline), while the
vendor's `vhui64.exe -t` wrapper hangs forever (0 bytes, both LocalService and the
interactive console session). Each pipe connection gets its own instance, so
request/response is correlated; safe.
- Linux/macOS shells out to `-t`, because there the IPC is two FIFOs and the response FIFO
is an uncorrelated global — reading it ourselves would steal other consumers' replies.
Never stranding a device is the core promise, so it is layered: the journal is written
BEFORE every USE (a crash leaves a superset of reality, never a subset), reconcile-on-start
unconditionally hands back everything the journal names, plus a watchdog and a release on
clean shutdown.
Ownership is tracked per binding rather than as a flag: only the owning trigger's end
releases, so a second couch's stream stopping cannot hand back the first couch's wheel.
Security: only the operator names devices — nothing on the wire influences which device
binds. Attaching USB to the host is an input-trust escalation, and a couch that could name
its own device could attach a virtual keyboard. Addresses are regex-validated before they
reach a verb and the exec backend passes argv, never a shell string.
28 tests cover the parser, matcher, ownership policy and the pipe framing (over a unix
socket, so it runs on any CI host). Design: planning/design/virtualhere-plugin.md.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
17 lines
332 B
JSON
17 lines
332 B
JSON
{
|
|
"compilerOptions": {
|
|
"target": "ES2022",
|
|
"module": "ESNext",
|
|
"moduleResolution": "bundler",
|
|
"lib": ["ES2022"],
|
|
"strict": true,
|
|
"noUncheckedIndexedAccess": true,
|
|
"verbatimModuleSyntax": true,
|
|
"skipLibCheck": true,
|
|
"noEmit": true,
|
|
"resolveJsonModule": true,
|
|
"types": ["bun"]
|
|
},
|
|
"include": ["src", "test"]
|
|
}
|