diff --git a/NucleicBroker/Wslc/WslcFacade.cs b/NucleicBroker/Wslc/WslcFacade.cs index 34fae74..06bd7ea 100644 --- a/NucleicBroker/Wslc/WslcFacade.cs +++ b/NucleicBroker/Wslc/WslcFacade.cs @@ -27,10 +27,13 @@ namespace NucleicBroker.Wslc; // is the VM GUID an AF_HYPERV bind needs. Both IDLs are in the open-source WSL repo. The // internal one carries an explicit "ABI breaking changes are OK" warning. // -// So there are two ways to close the gaps — direct internal COM, or shelling out to -// `wslc.exe` — with a real stability-versus-fidelity trade-off between them, and it has NOT -// been decided. §13.1 lays it out. Whichever wins lives entirely inside this class: `IWslc` -// does not change, so nothing on the Swift side knows which surface answered. +// D13 (§13.1): this class binds BOTH surfaces — compat SDK for everything it covers, internal +// COM for those five. Shelling out to `wslc.exe` was considered and rejected (a spawn per call, +// scraped text, no events, a second mechanism to maintain). Because the internal ABI is +// explicitly unstable, bind it defensively: probe at startup, report what bound in the +// `capabilities` hello, and degrade — losing reattach, stats and the Terminal panel — rather +// than failing the sandbox. All of that lives inside this class: `IWslc` does not change, so +// nothing on the Swift side knows which surface answered. // // Also note: `ProcessSettings` has no uid/gid, so exec wraps argv in setpriv/su — which // §3.2 already anticipated as the fallback, so it costs nothing. diff --git a/spikes/README.md b/spikes/README.md index 3d27fa4..d1aefed 100644 --- a/spikes/README.md +++ b/spikes/README.md @@ -67,9 +67,9 @@ for, and nothing above it should move. These three are different: | Finding | Consequence | | --- | --- | -| No container enumeration, stats, pty or attach in the SDK | **Not fatal, and not CLI-only.** `wslcsdk.dll` wraps `WSLCCompat.idl` (the stable SDK surface), which genuinely lacks them; they all exist on `wslc.idl`, the service-internal COM interface `wslc.exe` calls — `ListContainers`, `Stats`, `ResizeTty`, `OpenContainer`/`Attach`, `OpenSessionByName`, and `IWSLCVirtualMachine::GetId` (the VM GUID for AF_HYPERV). Both IDLs are open source. Internal COM vs. CLI is an undecided trade-off — see §13.1. | -| No create-or-attach on `Session` | **Answered:** `IWSLCSessionManager::OpenSessionByName` / `EnterSession` / `ListSessions` exist on the internal interface. Reattach (§2.3) is mechanically possible; what remains is choosing the surface. | -| No gateway address anywhere on the API | Source it from `GetAdaptersAddresses` over the `vEthernet (WSL)` adapter — **or skip TCP entirely**: `IWSLCVirtualMachine::GetId` returns the VM GUID, so §5's AF_HYPERV/AF_VSOCK path (true vsock parity with macOS) is directly reachable rather than being upside. | +| No container enumeration, stats, pty or attach in the SDK | **Settled by D13.** `wslcsdk.dll` wraps `WSLCCompat.idl` (the stable SDK surface), which genuinely lacks them; they all exist on `wslc.idl`, the service-internal COM interface `wslc.exe` calls — `ListContainers`, `Stats`, `ResizeTty`, `OpenContainer`/`Attach`, `OpenSessionByName`, and `IWSLCVirtualMachine::GetId`. The broker binds both surfaces; no CLI. | +| No create-or-attach on `Session` | **Answered:** `IWSLCSessionManager::OpenSessionByName` / `EnterSession` / `ListSessions` on the internal interface. §2.3 reattach has its mechanism. | +| No gateway address anywhere on the API | **Skip TCP:** `IWSLCVirtualMachine::GetId` returns the VM GUID, so §5's AF_HYPERV/AF_VSOCK path (true vsock parity with macOS) should become primary at M1 (b). Gateway TCP stays as fallback, its address from `GetAdaptersAddresses` over `vEthernet (WSL)`. | | No uid on `ProcessSettings` | Recoverable, and already planned for: exec wraps argv in `setpriv`/`su agent -c`. Interceptors and nash don't care about the numeric uid (§3.2). | --- @@ -82,6 +82,9 @@ for, and nothing above it should move. These three are different: mounted vs. in-VM). Deliberately held back until `WslcApiDump` has run: written now, against guessed names, it would not compile, and fixing it blind is the mistake this whole approach exists to avoid. -- **`HvSocketSpike`** — M1 (b): AF_HYPERV host listener ↔ AF_VSOCK dial from inside a wslc - container, plus gateway-TCP reachability and default-firewall behaviour in NAT and mirrored - modes. Only worth building once a container can be started at all. +- **`HvSocketSpike`** — M1 (b), and now the *primary* control-plane spike rather than the + fallback one (D13): bind an AF_HYPERV listener on the VM GUID from + `IWSLCVirtualMachine::GetId` and dial AF_VSOCK from inside a wslc container. If vsock + traverses the container's namespaces, the Windows control plane gets true parity with macOS + and §5's firewall/NAT variance stops mattering. Measure gateway-TCP reachability in the same + run so the fallback stays evidenced.