Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ The Rust workspace (`src/`) implements multiple sandboxing backends behind the `

### Config flow

1. User provides JSON config (file or base64) → `config_parser.rs` deserializes into intermediate `Raw*` structs → validates and maps to `CodexRequest` (the internal execution model in `models.rs`)
2. `CodexRequest` includes the containment backend selection, process config, filesystem/network policies, and optional experimental features
1. User provides JSON config (file or base64) → `config_parser.rs` deserializes into intermediate `Raw*` structs → validates and maps to `ExecutionRequest` (the internal execution model in `models.rs`)
2. `ExecutionRequest` includes the containment backend selection, process config, filesystem/network policies, and optional experimental features
3. The appropriate `ScriptRunner` implementation executes the process and returns `ScriptResponse`

### TypeScript layers
Expand Down
10 changes: 5 additions & 5 deletions docs/authoring-a-new-feature.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,10 @@ Add tests to verify:
- Missing optional fields use defaults
- Unknown fields under `experimental` are ignored (forward compatibility)

Also ensure that `convert_raw_config()` populates `CodexRequest.experimental`:
Also ensure that `convert_raw_config()` populates `ExecutionRequest.experimental`:

```rust
Ok(CodexRequest {
Ok(ExecutionRequest {
// ... existing fields ...
experimental, // ← include the parsed experimental config
})
Expand All @@ -261,7 +261,7 @@ Ok(CodexRequest {
## Step 4: Implement the feature in the runner

> The `--experimental` CLI flag and `experimental_enabled` field on
> `CodexRequest` already exist from when `compartments` was added. No changes
> `ExecutionRequest` already exist from when `compartments` was added. No changes
> needed in `main.rs`.

The full flow is:
Expand All @@ -278,7 +278,7 @@ In the appropriate runner (`appcontainer.rs`, `lxc_runner.rs`, etc.), guard
your feature behind `experimental_enabled`:

```rust
fn run(&mut self, request: &CodexRequest, logger: &mut Logger) -> ScriptResponse {
fn run(&mut self, request: &ExecutionRequest, logger: &mut Logger) -> ScriptResponse {
// ... normal execution (filesystem, network, etc.) ...

if request.experimental_enabled {
Expand Down Expand Up @@ -367,7 +367,7 @@ When your experimental feature is ready to ship:

1. Move the property from `experimental` to a top-level property in the schema
(e.g., `experimental.gpuIsolation` → `gpuIsolation`)
2. Move the struct from `ExperimentalConfig` to `CodexRequest`
2. Move the struct from `ExperimentalConfig` to `ExecutionRequest`
3. Move the field from `RawExperimental` to `RawConfig`
4. Remove the `if request.experimental_enabled` guard
5. Bump the minor version
Expand Down
2 changes: 1 addition & 1 deletion docs/base-process-container/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ In `src/wxc_common/src/base_container_runner.rs`, update
`build_sandbox_spec` to include your new data:

```rust
fn build_sandbox_spec(request: &CodexRequest) -> Vec<u8> {
fn build_sandbox_spec(request: &ExecutionRequest) -> Vec<u8> {
// ... existing code ...

let spec = SandboxSpec::create(
Expand Down
12 changes: 6 additions & 6 deletions docs/bwrap-support/bubblewrap-backend-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Key advantages over LXC for MXC:

MXC's `ScriptRunner` trait requires only:
```rust
fn execute(&mut self, request: &CodexRequest, logger: &mut Logger) -> ScriptResponse;
fn execute(&mut self, request: &ExecutionRequest, logger: &mut Logger) -> ScriptResponse;
```
Plus optional `validate_runner()`. This is a perfect fit for bwrap, which is fundamentally
"run a command in a namespace sandbox" — a single `std::process::Command` invocation.
Expand Down Expand Up @@ -70,7 +70,7 @@ Bubblewrap,
```

No `BubblewrapConfig` struct needed for now — the runner uses only the shared
`ContainerPolicy` fields on `CodexRequest` (filesystem paths, network policy, env, etc.).
`ContainerPolicy` fields on `ExecutionRequest` (filesystem paths, network policy, env, etc.).
A backend-specific config can be added later under `ExperimentalConfig` if needed.

### 3. Config Parser Changes
Expand Down Expand Up @@ -117,20 +117,20 @@ Add `bwrap_common` to workspace `members` in `src/Cargo.toml`.

### 5. BubblewrapScriptRunner Implementation

Core design — translate `CodexRequest` into a `bwrap` command line:
Core design — translate `ExecutionRequest` into a `bwrap` command line:

```rust
pub struct BubblewrapScriptRunner;

impl ScriptRunner for BubblewrapScriptRunner {
fn validate_runner(&self, request: &CodexRequest) -> Result<(), ScriptResponse> {
fn validate_runner(&self, request: &ExecutionRequest) -> Result<(), ScriptResponse> {
// Check bwrap is on PATH
// Check user namespaces are enabled (cat /proc/sys/kernel/unprivileged_userns_clone)
// Validate filesystem paths exist
// Reject allowedHosts/blockedHosts (not supported by bwrap)
}

fn execute(&mut self, request: &CodexRequest, logger: &mut Logger) -> ScriptResponse {
fn execute(&mut self, request: &ExecutionRequest, logger: &mut Logger) -> ScriptResponse {
let mut cmd = std::process::Command::new("bwrap");

// Namespace isolation (all unshared by default)
Expand Down Expand Up @@ -336,7 +336,7 @@ policy gap is a design decision, not an implementation challenge.
- `src/Cargo.toml` — add `bwrap_common` to workspace members + dependencies
- `src/lxc/Cargo.toml` — add `bwrap_common` dependency
- `src/lxc/src/main.rs` — add dispatch arm for `ContainmentBackend::Bubblewrap`
- `src/wxc_common/src/models.rs` — add `Bubblewrap` variant, `BubblewrapConfig` struct, wire into `ExperimentalConfig` and `CodexRequest`
- `src/wxc_common/src/models.rs` — add `Bubblewrap` variant, `BubblewrapConfig` struct, wire into `ExperimentalConfig` and `ExecutionRequest`
- `src/wxc_common/src/config_parser.rs` — add `RawBubblewrap`, parsing, containment match arm

### Schema (modify)
Expand Down
2 changes: 1 addition & 1 deletion docs/diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ wxc-exec.exe --experimental my-config.json

## What Gets Logged

- Input JSON config and parsed `CodexRequest` (env values redacted, script truncated)
- Input JSON config and parsed `ExecutionRequest` (env values redacted, script truncated)
- Sandbox spec details (size, UI flags, capabilities, filesystem/network policy)
- Process lifecycle (command line, identity, child PID, exit code, elapsed time)
- Section markers for key execution stages
Expand Down
2 changes: 1 addition & 1 deletion docs/isolation-session/initial-bringup-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ versions and stating that the bindings must be regenerated.
|---|---:|---|---|
| Config parsing | ~8 | `config_parser.rs` | `"isolation_session"` containment value, `experimental.isolation_session` section, `configurationId` values + defaults |
| Policy validation | ~15 | `isolation_session_runner.rs` | Phase-specific behaviour: provision accepts `readwritePaths` / `readonlyPaths` and rejects `deniedPaths`; non-provision phases reject every filesystem field; network and proxy are rejected at every phase |
| Option building | ~6 | `isolation_session_runner.rs` | `CodexRequest` → `ProcessOptions` mapping (timeout, cwd, env vars, redirect flags) |
| Option building | ~6 | `isolation_session_runner.rs` | `ExecutionRequest` → `ProcessOptions` mapping (timeout, cwd, env vars, redirect flags) |
| Feature unavailable | 1 | `isolation_session_runner.rs` | Runner returns a clean error on machines without the IsolationSession feature enabled, so the test passes everywhere |

These ~22 backend-specific tests run alongside the existing workspace tests
Expand Down
4 changes: 2 additions & 2 deletions docs/nanvix-microvm/nanvix-integration-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ All variants are surfaced via stderr output. Preflight and Platform errors preve

### Config Field Mapping

| JSON Field | Rust Field (`CodexRequest`) | NanVix Behavior |
| JSON Field | Rust Field (`ExecutionRequest`) | NanVix Behavior |
|------------|---------------------------|----------------|
| `process.commandLine` | `script_code: String` | ✅ **Used** — raw Python source code (not a shell command) |
| `process.timeout` | `script_timeout: u32` | ✅ **Used** — script execution timeout in ms |
Expand Down Expand Up @@ -238,7 +238,7 @@ Setup scripts (PowerShell & Bash) will download matching pre-release binaries an
**Goal:** Add NanVix as a functional containment backend in `wxc-exec.exe`.

**What changed:**
- `models.rs` — Added `MicroVm` variant to `ContainmentBackend`, added `NanVixConfig` struct, added `nanvix_config` field to `CodexRequest`
- `models.rs` — Added `MicroVm` variant to `ContainmentBackend`, added `NanVixConfig` struct, added `nanvix_config` field to `ExecutionRequest`
- `config_parser.rs` — Added `RawNanVix` serde struct, `"microvm"` containment parsing, NanVix config section parsing
- `error.rs` — Added `WxcError::NanVix(String)` variant
- `nanvix_runner.rs` — **NEW** — `NanVixScriptRunner` implementing `ScriptRunner` trait
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,37 +222,37 @@ pub trait StatefulSandboxBackend {
// Default body mints `<ID_PREFIX>:<random-token>`; override for native provision.
fn provision(
&mut self,
request: &CodexRequest,
request: &ExecutionRequest,
config: Option<Self::ProvisionConfig>,
) -> Result<ProvisionResult<Self::ProvisionMetadata>, MxcError> { /* ... */ }

// Default body returns Ok with no metadata.
fn start(
&mut self,
sandbox_id: &str,
request: &CodexRequest,
request: &ExecutionRequest,
config: Option<Self::StartConfig>,
) -> Result<StartResult<Self::StartMetadata>, MxcError> { /* ... */ }

// Required.
fn exec(
&mut self,
sandbox_id: &str,
request: &CodexRequest,
request: &ExecutionRequest,
config: Option<Self::ExecConfig>,
) -> Result<ExecHandle, MxcError>;

fn stop(
&mut self,
sandbox_id: &str,
request: &CodexRequest,
request: &ExecutionRequest,
config: Option<Self::StopConfig>,
) -> Result<StopResult<Self::StopMetadata>, MxcError> { /* ... */ }

fn deprovision(
&mut self,
sandbox_id: &str,
request: &CodexRequest,
request: &ExecutionRequest,
config: Option<Self::DeprovisionConfig>,
) -> Result<DeprovisionResult<Self::DeprovisionMetadata>, MxcError> { /* ... */ }

Expand All @@ -264,14 +264,14 @@ Backends declare two consts (`ID_PREFIX` for sandbox-id routing, `BACKEND_KEY` f
wire-format `containment` value and `experimental.<BACKEND_KEY>.<phase>` deserialisation
— see reference §5), per-phase config and metadata as associated types (use `()` for
phases that don't need either), and override only the methods they care about — `exec`
is the only required method. Trait methods take `&CodexRequest` (the existing one-shot
is the only required method. Trait methods take `&ExecutionRequest` (the existing one-shot
domain model from `wxc_common::models`) plus `sandbox_id` for non-provision phases and
an optional backend-specific typed config; cross-cutting policy fields flow through
`request.policy` (a `ContainerPolicy`) and per-exec process info flows through
`request.script_code` / `request.working_directory` / `request.script_timeout` /
`request.env`. There is no Rust `ProcessConfig` / `FilesystemConfig` / `NetworkConfig`
/ `UiConfig` wrapper struct — those names exist as TypeScript SDK interfaces only. See
"Why the trait reuses `CodexRequest`" in main doc §9.2 for the rationale.
"Why the trait reuses `ExecutionRequest`" in main doc §9.2 for the rationale.

A backend's participation mode (ephemeral-only, state-aware-only, both) is declared by
which traits it implements. State-aware backends additionally register their
Expand Down Expand Up @@ -312,7 +312,7 @@ const { sandboxId } = await provisionSandbox(
```

```rust
// Parser deserializes the JSON above into a CodexRequest with
// Parser deserializes the JSON above into an ExecutionRequest with
// request.policy.readwrite_paths = ["C:\\workspace"]
// request.policy.default_network_policy = NetworkPolicy::Allow
// request.policy.allowed_hosts = ["api.anthropic.com"]
Expand Down
Loading
Loading