# cellos-host-windows

A Windows [`CellBackend`](../cellos-core/src/ports.rs) for CellOS. It isolates a
cell inside a Windows **Job Object** — the closest native analogue to a Linux
cgroup-v2 leaf — for hosts that cannot run the Linux-only backends (Firecracker,
gVisor).

Select it at runtime with:

```powershell
$env:CELLOS_CELL_BACKEND = "windows"
```

On a non-Windows host this value fails closed at supervisor startup.

## What it does

For each cell the backend creates a Job Object and uses it to:

| Concern | Mechanism |
| --- | --- |
| Process-tree containment | the workload + every descendant are job members |
| Memory cap | `spec.run.limits.memoryMaxBytes` → `JOB_OBJECT_LIMIT_JOB_MEMORY` |
| CPU cap | `spec.run.limits.cpuMax` → hard `JOBOBJECT_CPU_RATE_CONTROL_INFORMATION` |
| Residue-free teardown | `JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE` + `TerminateJobObject` |

The backend **owns execution**: when the spec declares `run.argv` it spawns the
workload itself (cleared environment, fixed `PATH`), assigns it to the job, and
surfaces the exit code through `wait_for_in_vm_exit` — the same posture as the
gVisor backend. A cell with no `run.argv` still gets a job (containment +
teardown) and defers execution to the supervisor.

## Honest scope (v1)

A Job Object is **process-level containment, not a virtualization boundary.** It
has no separate kernel, no syscall emulation, no filesystem mount namespace, and
no network-egress enforcement. Its isolation tier matches the Linux proprietary
(cgroup-only) backend — weaker than gVisor, far weaker than a Firecracker
microVM. For a hardware/syscall boundary, run the cell on Linux with
`CELLOS_CELL_BACKEND=firecracker` (or `gvisor`).

Two gaps are enforced **fail-closed** rather than ignored:

- **Network egress is not enforced.** A spec that declares
  `authority.egressRules` gets a per-cell `tracing::warn`. `nft_rules_applied`
  is always `None`.
- **`secretDelivery: env` + `secretRefs` is refused.** Because the backend owns
  execution, the supervisor's env secret-injection path is bypassed; `create`
  returns `InvalidSpec` instead of running the workload without its secrets. Use
  a broker-socket delivery mode (the default `runtimeLeasedBroker`), where the
  child fetches secrets over a socket.

### Known limitation: spawn→assign race

The workload is assigned to its job immediately *after* spawn, leaving a
sub-millisecond window in which the child could spawn a grandchild outside the
job. `TerminateJobObject` plus kill-on-close still bound the tree, and the
assigned child's own descendants are always contained. A future revision can
close the window with `CREATE_SUSPENDED` + resume once the supervisor exposes a
thread handle.

## Platform gating

The real implementation (`backend.rs`, `job.rs`) compiles only on Windows; the
`windows` crate dependency is pinned to `cfg(windows)`. On other targets the
crate exposes a stub `WindowsCellBackend` whose methods return a `Host` error,
so `cargo check --workspace` stays green on Linux/macOS CI.
