Skip to content

Commit bcd517b

Browse files
jamieknvidiapkhodade-NVgburachasshailendra-nvdrew
authored
feat(driver-mxc): native Windows MXC compute driver + server wiring (NVIDIA#2721)
* feat(driver): add MXC compute driver for Windows isolation sessions Introduces the openshell-driver-mxc crate implementing ComputeDriver backed by Microsoft MXC isolation sessions (Windows only). Wires the new driver into the server's build_compute_runtime dispatch and adds the Mxc variant to ComputeDriverKind. Also adds a local protobuf-src stub (tools/protobuf-src-local) to unblock Windows builds that lack MSYS2/MinGW, and pins the zig Windows x64 toolchain in mise.lock. (cherry picked from commit 4f70122) Signed-off-by: Jamie King <jamiek@nvidia.com> * wip(mxc): checkpoint hung-agent work (recon, policy_map embed, A1 wiring, demo artifacts) Safety checkpoint of uncommitted work from the background agent run that stalled mid-Step-7. Includes: mxc-driver-recon.md (Step 0.5), policy_map.rs (~876L embedded mapper), A1 policy-threading edits across driver.rs/policy.rs/mxc.rs/compute/mod.rs, and examples/ (demo.yaml + mxc-gateway.toml). Not yet verified to compile end-to-end; to be reorganized into the skill's Step 11 commit sequence. (cherry picked from commit 38e42c0) Signed-off-by: Jamie King <jamiek@nvidia.com> * test(mxc): fix lifecycle and policy unit-test compile drift - Bring futures::StreamExt into scope for the watch-stream `.next()` call in driver::lifecycle_tests so the negative policy proof test compiles. - Bind a local `mapper` and drop the unused/deprecated NetworkBinary in the embedded-mapper network-policy rejection test. Signed-off-by: Jamie King <jamiek@nvidia.com> (cherry picked from commit 039b0ba) Signed-off-by: Jamie King <jamiek@nvidia.com> * fix(mxc): downgrade missing sandbox_token to debug log The gateway mints `sandbox_token` only when a sandbox-JWT issuer is configured. There is no in-sandbox supervisor on MXC (supervisor-removal design — D1/D4), so no component ever consumes the token; requiring it on the driver side blocks the demo's `--disable-tls` smoke gateway with a spurious `invalid_argument`. Log the absence and proceed instead. Signed-off-by: Jamie King <jamiek@nvidia.com> (cherry picked from commit cea2097) Signed-off-by: Jamie King <jamiek@nvidia.com> * fix(mxc): keep sandbox Ready after a successful one-shot agent exec monitor_exec demoted Ready->Error on exit 0 (reason ExecCompleted), so the positive demo (write hello.txt + exit) landed in Error phase. Keep Ready=True (reason AgentCompleted) on success; only non-zero exits go to ExecFailed. Tighten the positive lifecycle test to assert the terminal condition stays Ready=True/AgentCompleted. Verified live via gateway mock round-trip: phase now Provisioning->Ready with no demotion. (cherry picked from commit 54ab030) Signed-off-by: Jamie King <jamiek@nvidia.com> * feat(mxc): add processContainer backend for default-deny enforcement Add a backend selector to the MXC driver (isolation_session default | process_container). process_container drives a one-shot AppContainer that is genuinely default-deny: a write to any ungranted path is denied by the OS, unlike isolation_session which is grant-only and cannot deny. The lifecycle forks on the flag - isolation_session keeps provision/start/exec, process_container runs a single ephemeral container via run_oneshot. Also: run-demo.ps1 gains -Backend and hardens the CLI register/create calls; docs corrected to state isolation_session does NOT deny out-of-policy writes and that the negative proof requires process_container. Verified end-to-end on a real demo box (gateway -> CLI -> driver -> MXC): in-policy write succeeds, out-of-policy write denied (PermissionDenied), OVERALL: PASS. (cherry picked from commit c6cde38) Signed-off-by: Jamie King <jamiek@nvidia.com> * refactor(driver-mxc): embed policy mapper as a module; remove standalone crate Adopt the proto-based mapper (map_to_mxc) as the single source of truth, embedded in openshell-driver-mxc as a Windows-gated `policy_map` module. Rewire EmbeddedPolicyMapper to call it directly on the typed SandboxPolicy, deleting the serde_yaml proto->YAML bridge. Move the CLI to a windows-gated example and the parity tests into the crate; delete openshell-policy-mapper. - gate policy_map + seam Windows-only (MXC is Windows-only) - drop serde_yaml; add dev-deps openshell-policy, clap, anyhow - normalize mapped paths to Windows form in the seam, in one place - docs: add driver-mxc to AGENTS.md table; correct design doc section 17 test lane Signed-off-by: Giedrius Burachas <gburachas@nvidia.com> (cherry picked from commit f22f9c7) Signed-off-by: Jamie King <jamiek@nvidia.com> * feat(driver-mxc): implement lossless split_policy for proxy-delegated egress Signed-off-by: Giedrius Burachas <gburachas@nvidia.com> (cherry picked from commit 96d6afa) Signed-off-by: Jamie King <jamiek@nvidia.com> * feat(driver-mxc): implement Pattern-C governed-egress split through the policy seam - split_policy: SocketAddr proxy_redirect (replaces bare port), processcontainer containment guard naming MXC M1, version preserved in the trimmed proxy_policy, delegation reported as an info loss item - seam: MappedConfig carries trimmed_policy + proxy_addr; MapCtx.egress selects the split path; coarse path unchanged when egress is disabled - driver: [openshell.drivers.mxc] egress_proxy / egress_proxy_addr config, validated at create (isolation_session rejected until M1); lifecycle threads the redirect into provision and stores the trimmed policy per sandbox, emitting an EgressRedirect platform event - mxc: optional MxcNetwork block (defaultPolicy=block + proxy) in provision and one-shot configs; mock records configs for test assertions - tests: lossless-invariant suite over all example policies (validate + serialize round-trip), split lifecycle proof, M1 rejection; example gains --split --proxy-addr writing mxc-config.json / trimmed-policy.yaml / loss-report.json Signed-off-by: Giedrius Burachas <gburachas@nvidia.com> (cherry picked from commit 34d54ad) Signed-off-by: Jamie King <jamiek@nvidia.com> * fix(driver-mxc): emit MXC network.proxy as {localhost: port} Verified against the real wxc-exec 0.6.0-alpha via --dry-run: MXC accepts only the {localhost: N} proxy shape (the form the design doc specifies) and rejects {host, port} with a parse error. Schema 0.6.0-alpha can express only a loopback port, so non-127.0.0.1 redirect addresses are now rejected: split_policy emits an error loss (no proxy block) and the driver refuses egress_proxy_addr values off 127.0.0.1. Per-sandbox attribution must use per-sandbox ports until the schema widens. Signed-off-by: Giedrius Burachas <gburachas@nvidia.com> (cherry picked from commit edde8d5) Signed-off-by: Jamie King <jamiek@nvidia.com> * fix(driver-mxc): serialize isolation_session stop/deprovision as unit variants Empirical contract finding from the real test lane (build 26300.8553, wxc-exec 2026-06-10): the stop and deprovision experimental blocks are unit variants in the wxc-exec schema and must serialize as null; sending {} is rejected with malformed_request (invalid type: map, expected unit), while provision/start accept maps. The production invoker, the real-lane test, the probe script, and the e2e runner all sent {} - the driver could provision and run an agent but never stop or delete an isolation-session sandbox against this build. Pinned by a unit test. Signed-off-by: Giedrius Burachas <gburachas@nvidia.com> (cherry picked from commit 0df39ca) Signed-off-by: Jamie King <jamiek@nvidia.com> * test(driver-mxc): add Tier-0 mapper coverage matrix with schema drift guard Three-quadrant, table-driven matrix (38 tests): mappable fields assert exact MXC output; every OpenShell field MXC cannot express asserts a loss item with the expected severity (and seam rejection on error); an empty policy asserts the restrictive default-deny posture for every MXC knob OpenShell does not control. The handled_fields_inventory drift guard serializes a fully-populated policy and compares its YAML keys against the mapper-handled field lists, so a new openshell-policy field fails the suite until consciously mapped, delegated, or reported as loss. Re-exports the policy seam types for integration tests; adds serde_yml, base64, serde_json as dev-dependencies. Signed-off-by: Giedrius Burachas <gburachas@nvidia.com> (cherry picked from commit 91807f9) Signed-off-by: Jamie King <jamiek@nvidia.com> * feat(driver-mxc): inject agent_env into sandbox process.env Add MxcComputeConfig.agent_env: each entry is either KEY=VALUE (verbatim) or a bare KEY resolved from the gateway host environment at launch, keeping secrets (e.g. inference API keys) out of the config file. Wire it into the agent process so gateway-launched agents can authenticate to cloud endpoints (process.env was previously hardcoded empty). Unit-tested via resolve_agent_env_passthrough_and_host_lookup. Also add a gateway-driven cloud-inference (T1) test harness: mxc-inference.toml (agent_env + curl agent), inference.yaml policy, and run-inference-test.ps1 which starts the gateway, creates an isolation_session sandbox, runs an authenticated Nemotron call, and bundles redacted results. Documented agent_env in mxc-gateway.toml. Validated end-to-end on the test box (chat HTTP 200 + completion via the gateway). (cherry picked from commit 94d9e82) Signed-off-by: Jamie King <jamiek@nvidia.com> * test(driver-mxc): avoid unsafe env mutation in resolve_agent_env test Replace std::env::{set,remove}_var (unsafe + racy under parallel test execution in edition 2024) with a read-only PATH lookup. Preserves all three behaviors under test and drops the #[allow(unsafe_code)]. (cherry picked from commit ac5766e) Signed-off-by: Jamie King <jamiek@nvidia.com> * fix(mxc): adapt MXC driver to current GitHub OpenShell API The MXC driver crate was authored on GitLab against an earlier proto/core API. Adapt it to the API on GitHub main: - build_capabilities_response no longer takes supports_interactive_session - DriverSandboxSpec.gpu (bool) is now resource_requirements; detect GPU via effective_driver_gpu_count(driver_gpu_requirements(..)) - DriverSandbox gained a `workspace` field - SandboxPolicy gained `network_middlewares`: pass it through the proxy split, emit a loss item on the coarse MXC path, and account for it in the mapper drift-guard test Verified: cargo check + 75 mock-based tests pass (lib 27, examples 10, policy_mapper_matrix 38). Signed-off-by: Jamie King <jamiek@nvidia.com> * feat(server): wire the MXC compute driver into the gateway on Windows Register openshell-driver-mxc as the Windows-only in-process compute backend so compute_driver = "mxc" resolves to a working runtime: - ComputeRuntime::new_mxc, adapted to the current 11-arg from_driver - mxc_policy_sink A1 side channel, staged in create_sandbox before dispatch - mxc_config_from_context loader and the Mxc dispatch arm (Windows constructs; other targets return an explicit "Windows-only" error) - Windows-gated openshell-driver-mxc dependency - Mxc arms for the telemetry, config-file required-fields, and CLI reserved-builtin matches to keep them exhaustive/correct Verified with cargo check --workspace --features openshell-prover/bundled-z3 on x86_64-pc-windows-msvc, stacked on PR NVIDIA#2496. Signed-off-by: Jamie King <jamiek@nvidia.com> * fix(driver-mxc): implement GetGatewayListenerRequirements for NVIDIA#2496 base Signed-off-by: Jamie King <jamiek@nvidia.com> * test(driver-mxc): add probe-gated real wxc-exec test lane (no mocks) - tests/wxc_exec_real.rs: ignored-by-default integration tests against a real wxc-exec. Six --dry-run contract tests run wherever the binary exists (they caught the network.proxy shape mismatch); enforcement tests (processcontainer default-deny positive/negative, isolation session lifecycle round trip with a deprovision drop-guard) probe the backend and SKIP with a recorded reason where it is not live. - examples/probe-mxc-host.ps1: classifies a host (OS build, --probe, per-backend trial) and emits a JSON capability verdict. - examples/run-mxc-e2e.ps1 + e2e-policies/: scenario runner generalizing run-demo.ps1 (fs-rw, fs-readonly, fs-default-deny-empty, network-policy-rejected) with PASS/FAIL/SKIP gating and a stale OPENSHELL_MXC_MOCK_WXC guard in real mode. - tasks/windows.toml: windows:test:mxc-real:x64, windows:e2e:mxc, windows:e2e:mxc:mock. Signed-off-by: Giedrius Burachas <gburachas@nvidia.com> (cherry picked from commit 49afafe) Signed-off-by: Jamie King <jamiek@nvidia.com> * fix(driver-mxc): address PR review feedback Signed-off-by: Shailendra Singh <shailendras@nvidia.com> * docs: defer public MXC documentation Signed-off-by: Drew Newberry <385+drew@users.noreply.github.com> * fix(driver-mxc): build Windows capabilities response Signed-off-by: Drew Newberry <385+drew@users.noreply.github.com> * fix(server): gate in-tree tracing on Windows Signed-off-by: Drew Newberry <385+drew@users.noreply.github.com> * test(windows): fix cross-platform test assumptions Signed-off-by: Drew Newberry <385+drew@users.noreply.github.com> * test(windows): verify process and PEM portably Signed-off-by: Drew Newberry <385+drew@users.noreply.github.com> * test(windows): keep lifecycle command in policy Signed-off-by: Drew Newberry <385+drew@users.noreply.github.com> --------- Signed-off-by: Jamie King <jamiek@nvidia.com> Signed-off-by: Giedrius Burachas <gburachas@nvidia.com> Signed-off-by: Shailendra Singh <shailendras@nvidia.com> Signed-off-by: Drew Newberry <385+drew@users.noreply.github.com> Co-authored-by: Prashant K <pkhodade@nvidia.com> Co-authored-by: Giedrius Burachas <gburachas@nvidia.com> Co-authored-by: Shailendra Singh <shailendras@nvidia.com> Co-authored-by: Drew Newberry <385+drew@users.noreply.github.com>
1 parent 56088d0 commit bcd517b

40 files changed

Lines changed: 7761 additions & 43 deletions

‎.agents/skills/openshell-cli/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ stopped. Delete remains the operation that removes retained state.
371371

372372
This is the most important multi-step workflow. It enables a tight feedback cycle where sandbox policy is refined based on observed activity.
373373

374-
**Key concept**: Policies have static fields (immutable after creation: `filesystem_policy`, `landlock`, `process`) and two dynamic fields: `network_policies` and `network_middlewares`. Both dynamic fields can be updated without recreating the sandbox.
374+
**Key concept**: Policies have static fields (immutable after creation: `filesystem_policy`, `landlock`, `process`) and two dynamic fields: `network_policies` and `network_middlewares`. Both dynamic fields can be updated without recreating the sandbox when the selected compute driver supports live policy updates. MXC rejects live policy replacement and merge updates; delete and recreate an MXC sandbox instead.
375375

376376
An endpoint with omitted `protocol` retains explicit-proxy behavior. Explicit
377377
`protocol: tcp` requests policy DNS and transparent TCP and currently requires
@@ -441,7 +441,7 @@ Edit `current-policy.yaml` to allow the blocked actions. **For policy content au
441441
- Binary matching patterns
442442
- Ordered `network_middlewares`, host selection, HTTP and WebSocket bindings, and `fail_open` or `fail_closed` behavior
443443

444-
`network_policies` and `network_middlewares` can be modified at runtime. If `filesystem_policy`, `landlock`, or `process` need changes, the sandbox must be recreated. Built-in middleware such as `openshell/regex` needs no gateway registration. An operator-run middleware must already be registered under `[[openshell.supervisor.middleware]]`; changing that static registration requires a gateway restart.
444+
`network_policies` and `network_middlewares` can be modified at runtime when the selected compute driver supports live policy updates. MXC rejects live policy replacement and merge updates; delete and recreate an MXC sandbox instead. If `filesystem_policy`, `landlock`, or `process` need changes, the sandbox must be recreated. Built-in middleware such as `openshell/regex` needs no gateway registration. An operator-run middleware must already be registered under `[[openshell.supervisor.middleware]]`; changing that static registration requires a gateway restart.
445445

446446
Middleware can inspect parsed HTTP request bodies and complete client-to-upstream WebSocket text messages over both `ws://` and `wss://` when the implementation advertises the matching binding. The built-in `openshell/regex` advertises both bindings and applies its fixed patterns to UTF-8 text. A host-matched HTTP-only attachment can inspect the upgrade GET but does not join the WebSocket chain; look for `binding_not_selected` coverage. Binary messages pass under both `on_error` modes and active stages emit `unsupported_message_type` coverage; upstream-to-client messages remain uninspected. A broken fail-open WebSocket stage is disabled for the rest of that connection; inspect sandbox OCSF logs for `openshell.middleware.websocket_stage_disabled`.
447447

‎.agents/skills/openshell-cli/cli-reference.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ The sandbox name defaults to the last-used sandbox.
381381

382382
### `openshell policy update [name]`
383383

384-
Incrementally merge live network policy changes into the current sandbox policy. Multiple flags in one invocation are applied as one atomic batch and create at most one new revision.
384+
Incrementally merge live network policy changes into the current sandbox policy when the selected compute driver supports live updates. Multiple flags in one invocation are applied as one atomic batch and create at most one new revision. MXC rejects live policy merges; delete and recreate an MXC sandbox instead.
385385

386386
| Flag | Default | Description |
387387
|------|---------|-------------|
@@ -411,7 +411,7 @@ Notes:
411411

412412
### `openshell policy set [name] --policy <PATH>`
413413

414-
Replace the full policy on a live sandbox. Only the dynamic `network_policies` field can be changed at runtime.
414+
Replace the full policy on a live sandbox when the selected compute driver supports live updates. Only the dynamic `network_policies` field can be changed at runtime. MXC rejects live policy replacement; delete and recreate an MXC sandbox instead.
415415

416416
| Flag | Default | Description |
417417
|------|---------|-------------|

‎Cargo.lock‎

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎architecture/README.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ bridge networks, port mappings, NAT traversal, or bespoke tunnels. The common
141141
runtime requirement is narrower: the supervisor must be able to reach the
142142
gateway.
143143

144+
The Windows MXC driver is an explicit exception. It launches and monitors a
145+
one-shot workload in the driver, self-reports readiness, and does not expose a
146+
supervisor session, interactive connect, live policy delivery, or governed egress.
147+
144148
The gateway delivers desired state; the sandbox applies it locally. Policy,
145149
settings, credentials, and inference routes flow from the gateway to the
146150
supervisor. The supervisor validates and applies what can change at runtime,

‎architecture/windows-msvc-build.md‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
# Windows MSVC Build Design
22

33
This page records the design decisions for the native Windows MSVC build lane.
4-
It is intentionally build-only. It does not make Windows a Docker, Kubernetes,
5-
Podman, or VM runtime host.
4+
It provides the native build lane and validates the in-process MXC compute
5+
driver. It does not make Windows a Docker, Kubernetes, Podman, or VM runtime host.
66

77
## Goals
88

99
- Compile the OpenShell gateway and CLI for `x86_64-pc-windows-msvc` and `aarch64-pc-windows-msvc`.
1010
- Keep the Linux and macOS build paths unchanged.
1111
- Preserve gateway configuration parsing for all existing compute driver names.
12+
- Build and test the in-process MXC driver on supported Windows hosts.
1213
- Return clear unsupported errors when a Windows gateway is configured to use Docker, Kubernetes, Podman, or VM.
1314
- Keep dedicated `windows:*` validation tasks while allowing the repository-wide
1415
`pre-commit` task to delegate compiler-bearing Rust checks to the native
@@ -18,7 +19,7 @@ Podman, or VM runtime host.
1819

1920
- Do not support Docker Desktop, WSL, Hyper-V, Podman machine, Podman Desktop, Kubernetes, or VM-backed sandbox execution on Windows.
2021
- Do not ship Windows standalone binaries for Docker, Kubernetes, Podman, or VM drivers.
21-
- Do not implement named-pipe driver IPC, Windows services, MSI packaging, Credential Manager integration, DPAPI integration, or MXC policy translation in this build lane.
22+
- Do not implement named-pipe driver IPC, Windows services, MSI packaging, Credential Manager integration, or DPAPI integration in this lane.
2223

2324
## Unsupported Driver Strategy
2425

@@ -42,6 +43,7 @@ on Windows.
4243
| Kubernetes | Driver crate excluded; server config contract retained. | Gateway construction returns unsupported. |
4344
| Podman | Driver crate excluded; server config contract retained. | Gateway construction returns unsupported. |
4445
| VM | Driver crate excluded from workspace validation. | Gateway construction returns unsupported. |
46+
| MXC | Driver links into the native gateway and runs in Windows validation. | `process_container` is default-deny; grant-only `isolation_session` requires explicit configuration. |
4547

4648
This keeps Windows behavior explicit without carrying runtime dependencies or
4749
creating misleading Windows driver artifacts.
@@ -62,7 +64,7 @@ Windows validation is exposed through `tasks/windows.toml`:
6264
| `windows:check:arm64` | Check the ARM64 MSVC gateway/CLI build graph. |
6365
| `windows:build:x64` | Build release x64 `openshell-gateway.exe` and `openshell.exe`. |
6466
| `windows:build:arm64` | Build release ARM64 `openshell-gateway.exe` and `openshell.exe`. |
65-
| `windows:test:x64` | Run native x64 workspace tests, excluding unsupported Windows packages as top-level test targets. |
67+
| `windows:test:x64` | Run native x64 workspace tests, including MXC mapper and lifecycle tests, while excluding unsupported Windows packages as top-level test targets. |
6668
| `windows:test:arm64` | Run native ARM64 workspace tests with the same package exclusions. |
6769
| `windows:test:unsupported:x64` | Run focused server/runtime tests for unsupported driver contracts. |
6870
| `windows:test:unsupported:arm64` | Run the same focused contracts natively on ARM64. |
@@ -159,5 +161,5 @@ A successful Windows build report should include:
159161
- Focused unsupported-driver contract test status.
160162
- Artifact size and SHA256 for each Windows binary.
161163

162-
Warnings from Linux-only dead code are acceptable in this build-only phase when
164+
Warnings from Linux-only dead code are acceptable in the native Windows lane when
163165
they come from code paths intentionally disabled on Windows.

‎crates/openshell-core/src/config.rs‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ pub enum ComputeDriverKind {
126126
Vm,
127127
Docker,
128128
Podman,
129+
/// Microsoft MXC isolation session (Windows only).
130+
Mxc,
129131
}
130132

131133
impl ComputeDriverKind {
@@ -136,6 +138,7 @@ impl ComputeDriverKind {
136138
Self::Vm => "vm",
137139
Self::Docker => "docker",
138140
Self::Podman => "podman",
141+
Self::Mxc => "mxc",
139142
}
140143
}
141144
}
@@ -176,8 +179,9 @@ impl FromStr for ComputeDriverKind {
176179
"vm" => Ok(Self::Vm),
177180
"docker" => Ok(Self::Docker),
178181
"podman" => Ok(Self::Podman),
182+
"mxc" => Ok(Self::Mxc),
179183
other => Err(format!(
180-
"unsupported compute driver '{other}'. expected one of: kubernetes, vm, docker, podman"
184+
"unsupported compute driver '{other}'. expected one of: kubernetes, vm, docker, podman, mxc"
181185
)),
182186
}
183187
}

‎crates/openshell-core/src/telemetry.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ pub enum TelemetryComputeDriver {
165165
Kubernetes,
166166
Podman,
167167
Vm,
168+
Mxc,
168169
Unknown,
169170
}
170171

@@ -176,6 +177,7 @@ impl TelemetryComputeDriver {
176177
Self::Kubernetes => "kubernetes",
177178
Self::Podman => "podman",
178179
Self::Vm => "vm",
180+
Self::Mxc => "mxc",
179181
Self::Unknown => "unknown",
180182
}
181183
}
@@ -187,6 +189,7 @@ impl TelemetryComputeDriver {
187189
"k8s" | "kubernetes" => Self::Kubernetes,
188190
"podman" => Self::Podman,
189191
"vm" => Self::Vm,
192+
"mxc" => Self::Mxc,
190193
_ => Self::Unknown,
191194
}
192195
}
@@ -198,6 +201,7 @@ impl TelemetryComputeDriver {
198201
Some(crate::ComputeDriverKind::Kubernetes) => Self::Kubernetes,
199202
Some(crate::ComputeDriverKind::Podman) => Self::Podman,
200203
Some(crate::ComputeDriverKind::Vm) => Self::Vm,
204+
Some(crate::ComputeDriverKind::Mxc) => Self::Mxc,
201205
None => Self::Unknown,
202206
}
203207
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
[package]
5+
name = "openshell-driver-mxc"
6+
description = "MXC (Windows isolation session) compute driver for OpenShell"
7+
version.workspace = true
8+
edition.workspace = true
9+
rust-version.workspace = true
10+
license.workspace = true
11+
repository.workspace = true
12+
13+
[lib]
14+
name = "openshell_driver_mxc"
15+
16+
[dependencies]
17+
openshell-core = { path = "../openshell-core" }
18+
tokio = { workspace = true }
19+
tonic = { workspace = true }
20+
futures = { workspace = true }
21+
tokio-stream = { workspace = true }
22+
serde = { workspace = true }
23+
serde_json = { workspace = true }
24+
base64 = { workspace = true }
25+
tracing = { workspace = true }
26+
thiserror = { workspace = true }
27+
uuid = { workspace = true }
28+
29+
[dev-dependencies]
30+
tokio = { workspace = true }
31+
# tempfile is not a workspace dependency; 3.27 is already resolved in Cargo.lock.
32+
tempfile = "3"
33+
# Used by Windows-only integration tests to parse policy YAML into the typed
34+
# proto. Inert on non-Windows.
35+
openshell-policy = { path = "../openshell-policy" }
36+
# Needed by the real-wxc integration test (wxc_exec_real.rs) which builds
37+
# --config-base64 payloads without going through the async WxcExecInvoker.
38+
# base64 and serde_json are already [dependencies] but dev-dependency resolution
39+
# is independent; explicit entries make them visible to integration tests.
40+
base64 = { workspace = true }
41+
serde_json = { workspace = true }
42+
# Used by the drift guard test (handled_fields_inventory) to parse YAML into a
43+
# generic serde_json::Value for key enumeration.
44+
serde_yml = { workspace = true }
45+
46+
[lints]
47+
workspace = true
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# openshell-driver-mxc
2+
3+
OpenShell compute driver backed by **Microsoft MXC** (`wxc-exec`) on Windows.
4+
5+
## Design
6+
7+
This driver implements the gateway's `ComputeDriver` contract as an in-process
8+
library linked into `openshell-gateway`. `process_container` launches a one-shot
9+
AppContainer and is the default. The opt-in `isolation_session` backend uses the
10+
state-aware `provision` → `start` → `exec` → `stop` → `deprovision` lifecycle.
11+
The driver launches and monitors the configured workload itself and self-reports
12+
readiness; there is no in-sandbox supervisor or `ConnectSupervisor` relay.
13+
14+
## Capability Matrix
15+
16+
| Capability | MXC driver |
17+
|---|---|
18+
| Filesystem policy | Read-only/read-write grants come only from `SandboxPolicy`. `process_container` enforces default-deny; `isolation_session` is an explicit grant-only compatibility mode. |
19+
| Network policy | Rejected synchronously during sandbox creation until an enforcing egress path is bound. |
20+
| Process policy | Unsupported; MXC supplies OS isolation only. |
21+
| Interactive exec/connect/forward | Unsupported; the configured workload runs in-driver. |
22+
| Restart durability | Unsupported; the in-memory registry cannot recover live sessions. |
23+
24+
The filesystem enforcement proof has two paths:
25+
26+
- A write to a path granted by the sandbox policy succeeds.
27+
- A `process_container` write outside the sandbox policy fails with Windows access denied, and the driver reports the failed workload.
28+
29+
## Configuration (`[openshell.drivers.mxc]`)
30+
31+
Gateway configuration contains only host runtime settings:
32+
33+
```toml
34+
[openshell.drivers.mxc]
35+
wxc_exec_path = "C:\\path\\to\\wxc-exec.exe"
36+
# Default: process_container. isolation_session is grant-only and opt-in.
37+
backend = "process_container"
38+
default_configuration_id = "composable"
39+
pc_least_privilege = false
40+
pc_capabilities = []
41+
debug = false
42+
```
43+
44+
Supply workload settings for each sandbox. The public config is keyed by driver name; the gateway forwards only the inner `mxc` object to the driver:
45+
46+
```powershell
47+
$config = '{"mxc":{"command":["cmd","/c","echo hello > C:\\\\work\\\\demo\\\\hello.txt"],"cwd":"C:\\\\work\\\\demo"}}'
48+
openshell sandbox create --name mxc-demo --policy demo.yaml `
49+
--driver-config-json $config --env MODE=demo --no-tty
50+
```
51+
52+
The `command` array is required and preserves Windows argument boundaries. `cwd` is optional. Environment variables come from the standard sandbox and template environment maps; the driver never copies values from the gateway host environment.
53+
54+
Network policy and live policy replacement or merge updates are rejected while the gateway uses MXC. Delete and recreate the sandbox to apply a different filesystem policy.
55+
56+
## Prerequisites (live runs)
57+
58+
- Windows 11 Insider build ≥ 26300.8553
59+
- `IsoSessionApp.dll` present and registered
60+
- `wxc-exec.exe` built with `--features isolation_session`
61+
62+
For off-box smoke tests against the in-process mock shim (no `wxc-exec`,
63+
no isolation session needed), set `OPENSHELL_MXC_MOCK_WXC=1`.
64+
65+
## Policy mapping
66+
67+
The production driver maps the typed `SandboxPolicy` to MXC configuration before it inserts a registry entry or invokes `wxc-exec`. Mapping failure therefore returns from `CreateSandbox` without leaving a partial sandbox.
68+
69+
`EmbeddedPolicyMapper` calls the embedded [`policy_map`](src/policy_map/) module directly and normalizes filesystem paths to Windows form. It does not add gateway-configured host paths. The policy supplied for the sandbox is the only source of filesystem grants.
70+
71+
The mapper retains an internal policy-splitting seam for future development, but the runtime exposes no governed-egress switch. Any network rule fails closed until an enforcing proxy is implemented and bound to the sandbox lifecycle.
72+
73+
Parity and matrix tests under [`tests/`](tests/) cover the mapper on the Windows MSVC lane. The driver performs this mapping automatically; there is no separate policy-export command or example.
74+
75+
## Packaging the demo for the demo box
76+
77+
Use [`examples/package-demo.ps1`](examples/package-demo.ps1) to assemble
78+
the gateway EXE, CLI EXE, runtime DLLs (`libz3.dll`), `demo.yaml`, the
79+
gateway config, and the runbook into one folder, then copy that folder to
80+
the demo Windows host and follow `mxc-demo-runbook.md` inside it. The
81+
script prints a SHA256 manifest so the operator can sanity-check what
82+
landed before moving it.
83+
84+
## Real-MXC test lane
85+
86+
Three tasks drive real `wxc-exec.exe` hardware; all are **skip-safe** — any test
87+
or scenario that requires an absent binary or backend prints a SKIP reason and
88+
exits 0 rather than failing.
89+
90+
| Task | What it runs | When to use |
91+
|---|---|---|
92+
| `windows:test:mxc-real:x64` | `tests/wxc_exec_real.rs` — Tier-2 invoker tests with `--ignored --test-threads=1` | Pre-merge on any Windows host that has `wxc-exec`; dry-run tests always pass; enforcement tests probe-gate themselves |
93+
| `windows:e2e:mxc` | `examples/run-mxc-e2e.ps1` — Tier-3 scenario runner, real binary, probe-gated | Demo box / nightly; needs the gateway + CLI binaries in the script directory |
94+
| `windows:e2e:mxc:mock` | Same runner with `-Mock` — wiring-only, no real `wxc-exec` needed | Any Windows host (CI, dev machine); validates wiring and the network-reject scenario |
95+
96+
**Probe script:** `examples/probe-mxc-host.ps1` is an operator/CI preflight that emits a JSON capability report
97+
(OS build, wxc-exec path/version, dry-run exit code, per-backend trial result,
98+
and a `verdicts` object). Run it before the real-MXC lane to understand what
99+
will PASS vs SKIP on a given host:
100+
101+
```powershell
102+
powershell -NoProfile -ExecutionPolicy Bypass `
103+
-File crates/openshell-driver-mxc/examples/probe-mxc-host.ps1
104+
```
105+
106+
**Skip semantics:** tests in `wxc_exec_real.rs` are marked
107+
`#[ignore = "requires real wxc-exec"]` — the standard `windows:test:x64` suite
108+
never runs them. `OPENSHELL_WXC_EXEC_PATH` overrides the default
109+
`C:\mxc\wxc-exec.exe` lookup. See `docs4gtb/mxc-box-capabilities.md` for the
110+
empirical capability snapshot of the development box (build 26200, processcontainer
111+
velocity keys not enabled, isolation_session absent).
112+
113+
## Deferred work
114+
115+
- **Interactive exec/connect/forward** → `adapt-openshell-gateway-windows`
116+
- **Governed egress** remains fail-closed until an enforcing proxy is implemented and bound to sandbox lifecycle.
117+
- **Restart durability** (deprovision orphaned sessions on startup) → follow-on
118+
- **GPU passthrough** → not pursued in host-side-governance design

0 commit comments

Comments
 (0)