Runtime acceptance and test map¶
Historical evidence note: PR numbers, commit SHAs, and published module versions cited below describe the repository history and artifacts before the clean-history reset. They are retained as audit context and do not prove that the current source checkouts passed those lanes or were released.
This matrix tracks the behavior corpus from OpenShell v0.1.4 and the backend checks required before Quarshell can call a runtime production-ready. It is an engineering gate, not a compatibility claim.
Status meanings¶
| Status | Meaning |
|---|---|
local tests |
Unit, protocol, or integration tests exist and pass in the current checkout. |
host gate open |
Real engine, daemon recovery, security boundary, or published artifact still needs acceptance on its target host. |
unsupported |
The request is rejected or withheld explicitly; there is no silent downgrade. |
open |
Implementation or behavior evidence is incomplete. |
API and user-visible behavior corpus¶
| Feature group | Coverage in this checkout | Test / evidence | Remaining gate |
|---|---|---|---|
| Public control protocol | Inventory is pinned to v0.1.4: 83 public RPCs, plus related compute, credential, middleware and interceptor services. Handler presence is shape coverage only. | tracked feature inventory | Per-method golden inputs/results, stream cancellation, metadata and error parity remain open. |
| Sandbox create and inspect | Gateway maps the pinned OpenShell create request once to BackendCreateRequest; preflight, create, lifecycle, rollback and recovery call registered modular driver.Backend implementations directly. VM exec, process/log/transfer, policy and platform watch use declared native extensions. No flat Spec or Engine adapter remains. |
rpc_sandbox_test.go, rpc_templates_test.go, runtime_recovery_test.go, rpc_exec_test.go, remote_compute_backend_test.go, rpc_watch_test.go; Driver backend contract and capability tests. |
Full pinned CLI/backend per-method behavior corpus remains open; stream cancellation/event resume parity needs further coverage. VM Gateway create remains fail-closed until the managed host supervisor and authenticated host/guest isolation contract are complete. |
| OCI image inputs | MicroVM accepts a registry reference or the staged rootfs tar path. Registry tags are resolved to manifest digests; the VM selects linux/<host-arch>, checks image config and compressed layer digests/sizes, applies whiteouts, and builds an immutable ext4 base. Cache identity includes source and selected manifest digests, platform, rootfs layout version and guest-agent digest. A 64 GiB default cache quota evicts only images without durable sandbox references or active create leases. Docker/Podman keychain credentials are used for private registries; local acceptance exercises a Docker credential helper. OCI Entrypoint, Cmd, Env, User and WorkingDir feed the in-memory launch spec; recovery fetches config by the selected immutable platform manifest digest. Image env/user are not persisted, reserved identity variables are filtered, and root identities fail closed. Linux workers start in private user/mount namespaces, make mount propagation private and receive no inherited Gateway environment; namespace root maps to the Gateway host account and is not a dedicated host UID. |
quarshell-driver-vm/vm/oci_image_test.go, quarshell-driver-vm/vm/launch_spec_test.go, quarshell-driver-vm/vm/live_acceptance_test.go, quarshell-driver-vm/vmguest/agent_linux_test.go, image_cache_test.go, rootfs_image_test.go, rootfs_path_test.go, worker_process_linux_test.go, vm_test.go |
Additional credential-helper implementations and TLS/auth variants on target hosts; dedicated host UID, fd-based mount allowlist, UID/GID mapping and persistence; Gateway/Linux KVM acceptance. |
| Lifecycle, restart and host↔guest protocol | Docker/Podman lifecycle, recovery and main-process restart policies have package and gateway coverage. VM control frames use protocol v1; both sides reject missing or unknown versions, and guest responses carry the supported version. start-workload waits for a private supervisor readiness marker written only after the supervisor starts the workload; the marker path is removed from the workload environment. Start and worker recovery rotate the per-sandbox token through a durable pending record; replay with the old token is accepted only for the matching candidate and rotation ID. The guest forwards the validated restart policy to its supervisor; macOS ARM64 live acceptance observed an on-failure restart with the current host and guest agent. A fresh VM driver can hydrate the launch spec of an already-running sandbox before adopting its worker, without persisting image environment or identity. |
quarshell-driver-vm/vm/control_test.go, quarshell-driver-vm/vm/state_test.go, quarshell-driver-vm/vm/lifecycle_test.go, quarshell-driver-vm/vmguest/agent_linux_test.go, quarshell-runtime/internal/app/supervisor/run_test_unix_test.go, quarshell-driver/tests/e2e, quarshell-gateway/tests/e2e, rpc_main_process_test.go, task vm:live-darwin |
Protocol upgrade negotiation and versioned service/worker control contracts; live daemon/Gateway outage and foreground-attach corpus. Gateway VM recovery remains open. |
| Exec, attach and TTY | VM exposes a separate full-duplex ExecTerminal SPI extension. The authenticated guest PTY streams stdin/stdout, applies window resize, delivers terminal control characters such as Ctrl-C, and reports normalized exit status. VM sessions expose a stable ID, reattach to the same guest process after the control stream drops, and terminate it by session ID while detached; detached output has a bounded replay tail. Gateway stores the VM session ID with the durable exec request hash and a retry of the same TTY request_id reattaches without relaunching. Canonical VM workloads with TTY=true retain a boot-scoped main-process PTY in the guest and reattach to the same PID after driver recreation; local HVF acceptance verifies input/output, 101×41 resize and process identity. Foreground TTY creates pass the command and AwaitMainProcessAttachment through the durable create record. The CLI attaches to that retained PTY through the additive Quarshell MainProcessService gRPC extension; Gateway returns the canonical process exit after the stream closes. HVF acceptance verifies that a short TTY workload retains output and exit until a late attachment closes. |
quarshell-driver-vm/vm/terminal.go, quarshell-driver-vm/vmguest/retained_terminal.go, quarshell-driver-vm/vm/live_acceptance_test.go::assertLiveMainProcessTTY, quarshell-driver-vm/vm/live_acceptance_test.go::TestLiveMicroVMLifecycle, quarshell-cli/internal/service/sandbox_gateway_test.go::TestRemoteSandboxCreateForegroundAttachesToCanonicalProcess, quarshell-sdk/go/klorq/exec_interactive.go::AttachMainProcessTTY, quarshell-gateway/internal/transport/applicationgrpc/main_process_test.go::TestAttachTTYStreamsCanonicalMainProcessAndExit; task vm:live-darwin |
Main-process attachment behavior for workloads without a TTY and the host-side RunningBoundary process handle remain incomplete. Hosted Linux/KVM acceptance and live interactive exec on Docker/Podman hosts remain open. |
| Logs, cursor and watch | Gateway log and event streaming are tested. | rpc_logs_test.go, rpc_watch_test.go |
Loss-aware resume, cursor expiry and reconnect parity against v0.1.4 fixtures. |
| Copy and upload backpressure | Driver and SDK copy paths have tests; rootfs staging uses the v0.1.4 workspace-scope request. | Driver transfer tests; rootfs_tar_test.go; rpc_rootfs_test.go |
Large upload backpressure, cancellation and bounded-memory acceptance on live engines. |
| Service forward and SSH | Gateway service and relay flows have tests; public SSH sessions are expiring and sandbox-scoped. SSH/TCP/peer relays and supervisor exit/finalize calls validate the shared durable owner epoch; active streams close within a 250 ms polling window after handoff to fence a stale Gateway replica. | rpc_services_test.go, rpc_ssh_test.go, tests/e2e/engine_connect_test.go, runtime_relay_test.go::TestRelayStreamRejectsPendingChannelFromStaleGatewayOwner, runtime_relay_test.go::TestActiveSupervisorRelayIsClosedAfterDurableOwnerHandoff, supervisor_lease_test.go::TestSupervisorLeaseRemainsValidUntilNonzeroMainExitIsFinalized |
Upstream host-supervisor process bootstrap and full attach/session replay semantics; published-binary smoke and daemon-restart acceptance per backend. |
| Provider CRUD and labels | Provider labels are persisted, returned and filtered before pagination. Selector validation follows the pinned equality-selector syntax. | rpc_providers_test.go, store/clone_test.go |
Paging-token binding and full imported-provider fixtures remain open. |
| Provider profiles and refresh | Profile parsing, credential refresh, external credential drivers, token exchange and secret redaction have local tests. | rpc_profiles_test.go, rpc_credentials_test.go, driver_registry_test.go |
Per-profile expected defaults and runtime effects remain open. |
| Operator credential export | v0.1.4 handler requires a verified mTLS peer with the operator certificate OU and rejects bearer auth. |
provider_credentials_export_test.go, grpc_auth_test.go |
Deployment with operator certificates, refresh/lifetime parity and audit review. |
| Endpoint-bound credentials | GetSandboxProviderEnvironment returns CREDENTIALS_WITHHELD until endpoint bindings are produced. Lint reports stable-placeholder support as false. |
rpc_credentials_test.go, rpc_profiles_test.go |
Implement policy-bound bindings, credential identity, stable handles, refresh and supervisor installation together. This is a release blocker. |
| Policy and egress | Policy validation, updates, active proxy decisions and credential placeholder rewriting have local tests. | rpc_policy_*_test.go, quarshell-proxy/proxy/*_test.go |
MicroVM live test reloads revision 2, observes broker acknowledgement and verifies allow/deny decisions. Docker/Podman target-host dual-stack, Gateway-to-VM live verification, Linux KVM and Podman 6 route gates remain open. |
| Workspace, RBAC and quotas | Workspace scoping and authorization paths have gateway tests. | rpc_workspaces_test.go, workspace_quota_test.go |
Complete auth-method and pagination corpus against the pinned CLI/SDK. |
| CLI and SDK parity | Go SDK methods and command dispatch build; standalone consumers have a dedicated test target. Gateway MicroVM exec now uses the pinned login shell by default and -c for --no-login-shell; guest tests cover quoting/profile behavior and the macOS ARM64 live lane verifies Alpine .profile behavior. |
quarshell-sdk/tests/consumer; CLI module tests; quarshell-driver-vm/vmguest/agent_linux_test.go; task vm:live-darwin |
Leaf commands, flags, output, timeout process termination, Python client and published dependency resolution. |
Backend gates¶
| Capability | Docker | Podman | MicroVM |
|---|---|---|---|
| Create, inspect, start, stop, delete | Docker-in-Docker E2E passed locally; supported host matrix remains open | Disposable Podman 5.8.7 lifecycle E2E passed; rootful/rootless target-host gate remains open | Driver-level live acceptance passed on macOS ARM64, including restart; Gateway create remains fail-closed pending host supervisor/isolation |
| CPU and memory limits | E2E resource admission passed; target daemon limits need host matrix | Resource behavior depends on host and user namespace | Live macOS ARM64 guest reports 2 vCPU and 981 MiB visible memory for a 1 GiB configuration; PID limit remains unsupported |
| Workspace persistence and ownership | E2E persistence and daemon recovery passed; host ownership and full daemon matrix remain open | Podman 5.8.7 userns/recovery cases passed with documented capability skips; ownership matrix on target Linux remains open | Driver live test covers persistent ext4 overlay. Gateway now selects a guest-overlay workspace and omits the host path; Gateway-to-VM persistence and ownership acceptance remain open. Host workspace mounts are outside the OpenShell v0.1.4 VM model |
| Network isolation and policy broker | Docker 28 DinD E2E creates an IPv6 isolated network, verifies the sandbox IPv6 address, then confirms a reachable host listener at the conventional IPv6 gateway address cannot be reached from the sandbox. On one macOS ARM64 Docker Desktop host, a dual-stack control sandbox reaches host listeners over host.docker.internal (IPv4) and the host ULA IPv6 address; the proxy-isolated sandbox reaches neither. The driver also rechecks workspace directory identity immediately before Engine create, and a regression confirms replacement during preparation fails before workload creation. Atomic daemon-side path pinning and the wider host matrix remain open because the Engine API accepts a path rather than a directory handle. |
Podman 5.8.7 lacks required blackhole-route/host-gateway isolation; Podman 6 target gate remains open | macOS ARM64 live probes deny host IPv4/IPv6 loopback and unmapped host-vsock port 5504; raw ICMP socket creation is denied with EPERM. Revision 2 reload/ack changes the broker decision; killing the broker stops the VM and allows durable recovery. Gateway acknowledgement integration, DNS and Linux KVM acceptance remain open |
| Interactive process and transfer | Package tests exist; live TTY, signal and large-file cases open | Package tests exist; live PTY, log driver and reconnect cases open | macOS ARM64 live driver verifies PTY stdin/output, 80×24→101×41 resize, Ctrl-C signal delivery and exit status; Gateway-to-VM and Linux KVM remain open |
| GPU / CDI / PID limits | Mapped where daemon supports the requested feature; target hardware evidence required | Native CDI/PID support varies by host; explicit capability rejection required otherwise | Explicitly unsupported pending implementation and target-host evidence |
| Recovery and cleanup | Gateway/daemon recovery suite exists; rerun on release runner | Rootless/rootful recovery suite exists; service and API restart lanes required | macOS ARM64 driver live test covers fresh-driver adoption, broker-loss stop/restart, worker-group crash/relaunch from persisted rootfs/overlay, stop/start and cleanup; Gateway restart recovery and orphan reaper remain open |
| Release artifacts | Build and published-binary smoke required | Build and published-binary smoke required | Linux KVM and macOS ARM64 package builds; live VM acceptance remains mandatory |
The MicroVM ValidateGatewayRuntime failure remains in place. On macOS ARM64,
driver-level TestLiveMicroVMLifecycle passed with libkrun/HVF, a Linux guest,
default-deny broker, exec/copy, supervisor readiness, an observed on-failure
restart, SSH relay with a TCP echo round-trip through guest loopback, a fresh
driver instance, stop/start and cleanup. This does not exercise Gateway
orchestration.
Builds or unit tests without a live hypervisor are not acceptance. Production
requires Gateway-to-workload acceptance on Linux KVM x86_64/aarch64 and full
Gateway acceptance on macOS ARM64.
Current local run: 2026-10-16¶
The latest task check passes after tools/modules.lock and workflow refs
were aligned with published core v0.3.0 and proto v0.2.0. It covers workspace
and image pins, formatting, lint, vet/govulncheck, and all Go tests.
task compat:inventory (13/18 open or blocked), task docs:strict, and
go test -race ./internal/mounts ./internal/docker also pass. GOWORK=off
task release:standalone and task release:artifacts pass.
task e2e:docker-desktop passed its macOS ARM64 workspace and dual-stack
host-boundary lanes. task e2e:docker passed using isolated Docker-in-Docker,
including Gateway-to-supervisor relay lifecycle and
create/start/inspect/exec/stop/delete plus proxy allow/deny. task e2e:podman
passed against disposable Podman 5.8.7 for supported rootful/rootless
user-namespace and recovery cases; rootful keep-id skipped because nested crun
lacks mqueue, rootful no-map is rootless-only, rootless private maps are
unsupported, and Gateway/proxy lanes skipped because Podman 5 lacks blackhole
routes. Podman 6.1.3 in a nested Docker Desktop runner failed in the required
rootful user-namespace lane because nested cgroup controls were unavailable and
the auto mapping lacked a subordinate ID range, before reaching proxy tests.
Podman 6.1.3 lifecycle, service recovery, pull policy, digest pinning, and
rootless service recovery passed in the same nested environment; those checks
do not replace the missing complete user-namespace and target-host acceptance.
The merged driver v0.3.0 CI also passed rootful Podman 6.1.3 lifecycle,
service recovery, pull-policy and digest-pinning tests, plus rootless lifecycle,
service recovery and the auto/host/keep-id/no-map user-namespace matrix
on Ubuntu runners. Those lanes do not run proxy-backed host-gateway or Gateway
relay probes, so Podman 6 isolation acceptance remains open.
Driver PR #19, merged at 34060264b5627a0aac4b83d3aa4bb76f1eee9119,
subsequently passed Podman 6.1.4 rootful and rootless proxy-isolation CI in
disposable service containers. Direct host-gateway denial, proxy allow/deny,
TCP/UDP probes, and broker-loss denial passed. These lanes do not include a
Gateway relay or native host; nested cgroup controls also exclude ID-map start
and resource-limit acceptance. Linux host validation is deferred by request.
A fresh Podman 6.1.4 AppleHVF machine completed guest boot but host SSH/API
forwarding through gvproxy was unreachable; the pre-existing machine still
fails Ignition while adding core. These attempts are not Podman 6 target-host
acceptance; a dedicated Linux runner is required. Driver v0.3.0 has been
published from merged PR #16; its CI passed Linux/macOS/Windows build and test,
lint/format, Linux VM artifact, and rootful/rootless Podman 6.1.3 lanes. Gateway
now resolves driver v0.3.0 and proto v0.2.0 from published tags, and its
standalone GOWORK=off test passes. The full task release:published still
fails only on CLI: it pins runtime v0.2.1 and SDK v0.2.0, which lack current
heartbeat/log and provider/service APIs. Core v0.3.0, proto v0.2.0, providers
v0.1.8, proxy v0.3.0, runtime v0.3.0, and driver v0.3.0 are published; SDK
v0.3.0 has a merged release PR awaiting its tag after the Gateway release.
Driver-level MicroVM lifecycle acceptance passed on macOS ARM64
using libkrun/HVF, covering exec/copy, deny policy, supervisor, SSH, driver
recovery and stop/start. The acceptance also kills the complete worker process
group, waits for durable state to report it stopped, restores the workload spec
through a fresh driver, and starts the VM again from its persisted rootfs and
overlay. It verifies on-failure by observing the supervisor begin a second
process instance after exit code 7. The Linux worker
namespace test binary cross-builds for amd64 and arm64, but the local Docker
runner blocks user namespace creation with EPERM; this is not Linux host
acceptance. Gateway-level MicroVM and Linux KVM acceptance remain open, so
Gateway runtime validation stays fail-closed.
The same macOS ARM64/HVF lane imports an Alpine rootfs through a Basic Auth
protected local OCI registry using an isolated Docker config. A test Docker
credential helper supplies auth to the VM's default keychain. The test starts a guest workload with
image Entrypoint/Cmd, Env, WorkingDir and User, and observes /opt/app,
UID 1000 and the image environment inside the running guest. Durable state omits
the test credential and image environment. After the registry tag moves, the
test stops and restores the workload and verifies that the original manifest
digest still supplies its config. Additional registry credential-helper
implementations and TLS/auth variants on target hosts, Linux KVM OCI pulls and
Gateway crash recovery remain open.
The latest macOS ARM64 live MicroVM run also exercises protocol v1, supervisor
readiness before workload start is acknowledged, durable retry-safe vsock
control-token rotation, and recovery after worker-group crash. Guest probes
deny host IPv4/IPv6 loopback and connection to unmapped host vsock port 5504;
the raw ICMP socket probe is rejected with EPERM on macOS ARM64. The guest
sees 2 vCPU and 981 MiB for a 1 GiB memory configuration. The live broker
reloads policy revision 2 and acknowledges it through the test harness: the
allowlisted endpoint passes policy evaluation, while another endpoint remains
denied. This does not exercise the Gateway status-report RPC. Workload identity now
travels through the post-hardening readiness handshake, is persisted by the VM
driver and is mapped to the OpenShell WorkloadIdentity status condition; unit
tests cover the Gateway projection, while Gateway-to-VM live verification is
still unavailable because VM creation remains fail-closed. Killing the live
policy broker stops the worker group, records durable stopped state and
permits relaunch after restoring the workload spec. Workspace host mounts, a
dedicated host UID, Gateway recovery and Linux KVM acceptance remain open. This driver-level evidence does not enable
the Gateway MicroVM runtime.
An additional subprocess test closes the parent-liveness pipe and verifies that
the worker terminates its process group; Gateway-launched VM and image-prep
workers receive this pipe so a crashed Gateway does not leave orphan VMs.
The same live lane verifies a full-duplex guest PTY: it observes the initial 80×24 size, resizes to 101×41, sends stdin, and interrupts a trapped command with Ctrl-C, observing exit code 42. One-shot TTY exec also sees the OCI image working directory and image environment. Gateway has unit coverage for the interactive compute relay, but no Gateway-to-VM live run is counted while the VM create gate remains closed.
Release test order¶
The 2026-10-18 test-plan update moves the shared E2E lane to Podman 6.1.4 and
enables the userns matrix in rootful CI. Strict mode allows only rootful
no-map and rootless private as documented skips. The updated workflows have
not run yet; the historical Podman 5.8.7 result and earlier nested Podman 6
failures remain separate evidence and do not validate this new configuration.
task workspace:check,task check, and race/vet/vulnerability gates.task compat:pin-check,task compat:proto, andtask compat:inventory.task e2e:dockeron the supported Docker host matrix.task e2e:podmanon dedicated rootful and rootless Podman 6 runners; proxy, Gateway, and required userns cases must pass except for the two stated mode-specific skips.- MicroVM Gateway-to-workload and security tests on Linux KVM x86_64/aarch64
and macOS ARM64; no synthetic pass when the hypervisor is unavailable.
task vm:live-darwinruns driver-level libkrun/HVF acceptance on macOS ARM64;quarshell-driver/scripts/run-live-kvm-acceptance.shruns the Linux lane. - Standalone Go/Python consumers, published artifact smoke, strict docs build, SBOM and signature checks.
The current compatibility register is
openshell_compatibility_gaps.json.
It records known gaps but cannot prove that every source behavior has been
entered. Open rows remain blocking until test evidence is attached.
