release-1.2.0-rc.1
opensandbox-group/OpenSandboxrelease-1.2.0-rc.1Oct 15, 2026by github-actions[bot]
Upgrading?
Full Release Notes
First release candidate on the `1.2.0` line, carrying everything merged since `release-1.1.1` — the headline is OSEP-0024: auto-pause and wake-on-access for fast sandboxes, landing end to end. Images publish now; SDK/CLI packages ship at the `1.2.0` stable bump. Please test and report issues. ## Highlights - Auto-pause and wake-on-access for fast sandboxes (OSEP-0024) lands end to end: ingress activity tracking and the wake path, the server-side idle sweeper, the opt-in `lifecycle.idlePolicy` create field, and the wake-retry contract in all five SDKs — off by default, additive only ([#2156](https://github.com/opensandbox-group/OpenSandbox/pull/2156) [#2180](https://github.com/opensandbox-group/OpenSandbox/pull/2180) [#2192](https://github.com/opensandbox-group/OpenSandbox/pull/2192) [#2198](https://github.com/opensandbox-group/OpenSandbox/pull/2198) [#2218](https://github.com/opensandbox-group/OpenSandbox/pull/2218)) - Egress sidecar (experimental, opt-in): live credential-bound Vault admission, HTTP/2 support with bounded drain, atomic policy-file persistence, and runtime fault containment ([#2176](https://github.com/opensandbox-group/OpenSandbox/pull/2176) [#2201](https://github.com/opensandbox-group/OpenSandbox/pull/2201) [#2182](https://github.com/opensandbox-group/OpenSandbox/pull/2182) [#2162](https://github.com/opensandbox-group/OpenSandbox/pull/2162) [#2172](https://github.com/opensandbox-group/OpenSandbox/pull/2172)) - SDK reliability: file uploads and downloads are no longer aborted at the 30-second request timeout in any of the five SDKs; execd now reports sandbox-scoped CPU/memory and OOM kills ([#2165](https://github.com/opensandbox-group/OpenSandbox/pull/2165) [#2186](https://github.com/opensandbox-group/OpenSandbox/pull/2186) [#2196](https://github.com/opensandbox-group/OpenSandbox/pull/2196) [#2206](https://github.com/opensandbox-group/OpenSandbox/pull/2206) [#2191](https://github.com/opensandbox-group/OpenSandbox/pull/2191) [#2200](https://github.com/opensandbox-group/OpenSandbox/pull/2200)) ## Server - Implement the server side of OSEP-0024 auto-pause for fast sandboxes: the lifecycle create field `lifecycle.idlePolicy` (`idleTimeoutSeconds` 30–86400, `onIdle: pause`, `wakeOnAccess`, optional `activeProbe`) validates with pydantic bounds and persists as the reserved `sandbox.opensandbox.io/idle-policy` Sandbox CR annotation (annotation-write failure stays fail-safe — the sandbox is created unpolicied); an idle sweeper enumerates opted-in fsb sandboxes from the informer cache, checks activity in Redis (monotonic-max writes, missing-key tombstones can only delay a pause), takes a per-sandbox pause lock with re-verify under lock, and issues an idempotent FastPath `PauseSandbox`; a declared `activeProbe` executes through the ingress gateway and a busy answer records ordinary activity; an `OpenSandbox-Skip-Activity: skip` sentinel suppresses the observation for one request and is stripped on both gateway and server-proxy hops ([#2192](https://github.com/opensandbox-group/OpenSandbox/pull/2192) [#2181](https://github.com/opensandbox-group/OpenSandbox/pull/2181)) - Configure idle-pause under the new lifecycle-automation umbrella: `[idle_pause]` becomes `[automation.idle_pause]` and the redundant `redis.enabled` gate is removed — `redis.dsn` is required (validated at load) when `enabled = true`, failing loudly instead of silently not starting the sweeper; `configuration.md` is rewritten for conciseness and now documents `ingress.secure_access` and the missing env-var overrides ([#2215](https://github.com/opensandbox-group/OpenSandbox/pull/2215)) - Default BatchSandbox pods to `restartPolicy: Never`: a kubelet in-place container restart recreated the main container from its image — wiping the writable layer and in-memory state — while the sandbox kept reporting `Succeed`; restarting is never a meaningful recovery for a sandbox, so the honest default is no restart, which also makes the controller's terminal-failure path reachable. An explicit `restartPolicy` in the template still wins, the Windows profile keeps forcing `Always` (multi-phase installation relies on it), and pool mode is unchanged ([#2128](https://github.com/opensandbox-group/OpenSandbox/pull/2128)) - Treat `pasta`/`slirp4netns`/`none` as container-runtime network modes and pass them straight through, making podman's kernel-level networking selectable — on Windows 11 + WSL2 where netavark breaks bridge mode, `pasta` was the only working network and previously failed create with a 400 asking for a user-defined Docker network; `networkPolicy` is now rejected for these modes since there is no bridge for the egress sidecar to attach to (previously silently accepted for `none`) ([#2203](https://github.com/opensandbox-group/OpenSandbox/pull/2203)) - Parse Docker timestamps whose fractional second is not 3 or 6 digits: Docker writes RFC3339Nano (trailing zeros dropped), Python 3.10's `fromisoformat` rejects 5-digit fractions, and the helper fell back to `datetime.now()` — so `createdAt` and `status.lastTransitionAt` silently reported the current time; the fraction is now zero-padded to 6 digits ([#2220](https://github.com/opensandbox-group/OpenSandbox/pull/2220)) ## SDKs Code changes below ride the `1.2.0` stable release — rc ships no SDK packages. - Add the OSEP-0024 SDK contract to all five languages: a typed `lifecycle.idlePolicy` create field (`IdlePolicy`/`ActivityProbe` models with client-side fail-fast validation mirroring the server: timeout 30–86400 s, `onIdle: "pause"` pairing, probe path/timeout bounds; wired through both standard and template create) and the wake-retry contract — on a `503` carrying the gateway-owned `OpenSandbox-Wake: expired` marker (its presence proves the request was parked and never forwarded, making any-method retry safe), the SDK resends after `Retry-After` under a bounded budget (default 5 attempts / 60 s, per-client knobs), exhaustion raises a typed wake-timeout exception carrying attempts and waited time, the server-side resume is never canceled, bare `503` handling is unchanged, and SSE/streaming transports bypass wake retry ([#2198](https://github.com/opensandbox-group/OpenSandbox/pull/2198) [#2218](https://github.com/opensandbox-group/OpenSandbox/pull/2218)) - Stop capping file uploads and downloads at the request timeout (30 s default) in all four remaining SDKs — the whole-call timeout (`http.Client.Timeout`, OkHttp `callTimeout`, `AbortController`, `HttpClient.Timeout`) covered sending the request body and reading the response, so any large or slow transfer failed mid-flight even while healthy; transfers now run on a dedicated client with no whole-call deadline that still bounds the wait for response headers, so a stalled transfer still fails instead of hanging ([#2165](https://github.com/opensandbox-group/OpenSandbox/pull/2165) [#2186](https://github.com/opensandbox-group/OpenSandbox/pull/2186) [#2196](https://github.com/opensandbox-group/OpenSandbox/pull/2196) [#2206](https://github.com/opensandbox-group/OpenSandbox/pull/2206)) - Suppress `sandbox.create` client metrics for client-pool warmup creates in Go, Python, and JavaScript, aligning with Kotlin: warmup traffic (hardcoded `skipHealthCheck`, hundreds of ms) previously mixed into user-facing create-latency metrics and dragged p50/p99 down; direct-create from pool acquire and user-facing creates keep reporting ([#2199](https://github.com/opensandbox-group/OpenSandbox/pull/2199)) ### Python - Clean up cancelled async pool startup: cancelling `SandboxPoolAsync.start()` mid-await left the instance stuck in `STARTING`, where a subsequent `start()` silently returned and startup-owned resources skipped cleanup; cancellation now reuses the reconciliation cleanup path, moves to `STOPPED`, and re-raises so the caller can retry ([#2209](https://github.com/opensandbox-group/OpenSandbox/pull/2209)) - Stop reporting failed file replacements as successful: the ordinary filesystem adapters caught and discarded the generated client's `JSONDecodeError`, so an empty or non-JSON HTTP 400/500 from `replace_contents()` returned success and an agent could keep building on an unapplied edit; the catch is removed and the documented `SandboxException` failure contract is restored (isolated-session adapters keep their empty-body compatibility catch) ([#2222](https://github.com/opensandbox-group/OpenSandbox/pull/2222)) ### Go - Strip all `OPEN-SANDBOX-*`/`OPENSANDBOX-*` headers and every configured authentication header (including `X-EXECD-ACCESS-TOKEN`, `X-API-Key`, and custom `WithAuthHeader` names) on cross-origin redirects, comparing each destination against the initial request's scheme, host, and effective port so credentials cannot reappear on later foreign-origin hops; applied across lifecycle, execd, egress, file transfers, SSE, and creation metrics while preserving custom `CheckRedirect` policies ([#2178](https://github.com/opensandbox-group/OpenSandbox/pull/2178)) ## Controller - Retain a BatchSandbox until cleanup completes: a deleted sandbox could disappear from the lifecycle API (GET 404) while its owned pod still ran, letting a replacement sandbox write the same persistent directory before the old writer exited; deletion now uses foreground cascading deletion alongside the existing task-cleanup and pool-release finalizers, and TTL reconciliation stops once deletion is accepted — `DELETE` still returns 204 when accepted, queries report `Stopping` during managed cleanup, and 404 arrives only after the runtime is gone; all five SDKs' `kill` docs and logs describe the accepted-deletion semantics ([#2154](https://github.com/opensandbox-group/OpenSandbox/pull/2154)) ## Execd - Report OOM kills via cgroupfs polling: kernel-side evidence was out of reach from inside a sandbox (no `CAP_SYSLOG`, no `/dev/kmsg`), so OOM events were unobservable; execd now polls the sandbox cgroup every 5 s and diffs the kernel OOM kill counter (`memory.events` on v2, best-effort on v1) — the hierarchical counters cover nested cgroups like bwrap isolated sessions — exporting `execd.system.oom.kills` with a `local`/`descendant` level attribute plus structured warn logs with best-effort victim attribution; the watcher runs independently of OTLP export and needs no capabilities ([#2191](https://github.com/opensandbox-group/OpenSandbox/pull/2191)) - Report sandbox-scoped CPU/memory metrics: `GET /metrics` and the `execd.system.cpu.usage`/`execd.system.memory.usage_bytes` gauges read `/proc` through gopsutil, which inside a container describes the host — dashboards showed host-wide memory and CPU; when the sandbox cgroup carries configured limits, usage now comes from the sandbox's own cgroup (`cpu.stat`/`cpu.max`, `memory.current`/`memory.max`, v1 fallback, hybrid hosts prefer v1), with the previous host view kept for unlimitied guests such as fast-sandbox microVMs; the wire format is unchanged ([#2200](https://github.com/opensandbox-group/OpenSandbox/pull/2200)) - Percent-encode quotes and backslashes in `Content-Disposition`: a filename containing `"` or `\` produced a quoted-string no standard parser accepts (`mime.ParseMediaType` rejected it and clients got no filename at all); such names now route through the same `filename*=UTF-8''` encoding as non-ASCII names ([#2161](https://github.com/opensandbox-group/OpenSandbox/pull/2161)) - Parse the `Range` header before setting download headers: a malformed range answered 416 with the file's `Content-Disposition` and `Content-Length` still attached, truncating the JSON body or dropping it entirely — surfacing in the Python SDK as a connection error instead of a 416 `SandboxApiException`; the error response is now a clean JSON 416, and 200/206 responses are unchanged ([#2216](https://github.com/opensandbox-group/OpenSandbox/pull/2216)) ## Networking ### egress All items below concern the default-off OSEP-0023 experimental revision runtime; legacy and DNS-only deployments are unchanged. - Add experimental live credential-bound Vault admission: Vault mutations flow through the revision transaction and install the private authenticated snapshot before publishing the public result; bound HTTPS connections are admitted and header credentials injected only after exact request matching with SNI/HTTP/1 authority agreement (ECH-extension ClientHellos stay opaque), with per-request credential rotation, fencing of removed bindings on existing connections, and transport retirement at the drain deadline; scope is exact-host HTTPS on 443 with HTTP/1.1 and inline header credentials ([#2176](https://github.com/opensandbox-group/OpenSandbox/pull/2176)) - Acknowledge live Policy revisions before publication: the Policy API and automatic `deny.always`/`allow.always` reloads now commit in order — optional file persistence, nft application, exact receiver acknowledgement or reconciled readback, then proxy publication and API success — with fail-closed recovery when the receiver fails after nft has taken effect, and 30-second drain deadlines on policy-only updates that never extend across later revisions ([#2182](https://github.com/opensandbox-group/OpenSandbox/pull/2182)) - Add experimental HTTP/2 admission and bounded drain: snapshots bind atomically to actual client stream IDs at requestheaders, post-fence requests get `REFUSED_STREAM` before reaching origin, GOAWAY waits for outstanding output obligations while expiry uses abnormal closure, and a once-only mitmdump exit fallback covers unverifiable cleanup ownership; the adapter is pinned to CPython 3.10/3.11 and rejects configured chained upstream proxies ([#2201](https://github.com/opensandbox-group/OpenSandbox/pull/2201)) - Contain runtime recovery faults in the sidecar network namespace: an unexpected MITM exit now triggers an independent, read-back-verified IPv4/IPv6 fence pinned to the original namespace for the process lifetime — blocking all input/output/forward traffic including existing connections and loopback — with `QuarantineConfirmed` reported only after real rule readback; normal successful mutations never introduce a fence ([#2172](https://github.com/opensandbox-group/OpenSandbox/pull/2172)) - Persist experimental revision policy files atomically: writes go through a same-directory temporary inode with fsync + rename + directory fsync, restores put back the exact previous bytes (or synchronized absence), and unsupported storage — file bind mounts, read-only or symlinked paths, hardlinks, unsafe ownership, unsupported SELinux/IMA metadata — is rejected before the original is touched; operators must provide an existing egress-owned, exclusively written directory mount ([#2162](https://github.com/opensandbox-group/OpenSandbox/pull/2162)) - Classify nft apply effects before policy recovery: local construction, pre-start cancellation, and start failures are Unchanged (state preserved, retry allowed after restore), successful execution is Committed, and every post-start or unclassified error is Unknown — closing writer admission and latching recovery before best-effort restoration; the missing-table fallback retains both errors and never downgrades an Unknown result ([#2167](https://github.com/opensandbox-group/OpenSandbox/pull/2167)) ### ingress - Implement OSEP-0024 activity tracking and wake-on-access: with `--activity-enabled`, every routed request records a monotonic activity timestamp to Redis — fire-and-forget, never on the hot path — with per-replica write coalescing, Lua monotonic-max updates so out-of-order writes never regress the newest observation, and pipeline batching; with `--wake-enabled`, a request routed to a paused fast sandbox is parked instead of answered 503: one `ResumeSandbox` per replica per sandbox under a checkpoint-fenced singleflight, a bounded parking lot and budget (overflow/timeouts answer 503 + `Retry-After` while the restore continues, never canceled), and stale-route re-entry replayed on a fresh route only when safely replayable; with both flags unset, behavior is byte-identical to today ([#2156](https://github.com/opensandbox-group/OpenSandbox/pull/2156)) - Complete OSEP-0024 wake hardening: post-forward stale-route replay is restricted to idempotent methods with reproducible bodies (a forwarded `POST` is never silently re-executed); the pre-forward wake-timeout answer carries the OSEP-defined marker (`503` + `Retry-After: 1` + `OpenSandbox-Wake: expired` + a `sandbox_wake_timeout` body naming the sandbox), stripped from every upstream response so a sandbox cannot forge provenance; a separate restore permit (`--wake-restore-max`, held to flight terminal) bounds concurrent restores independently of the parking lot; and wake now requires the per-sandbox `lifecycle.idlePolicy` opt-in read strictly from the Sandbox CR annotation — missing or malformed means no policy and today's permanent 503, never an implicit opt-in; `gateway.wake.*` chart values wire the flags and add read-only RBAC only when enabled ([#2180](https://github.com/opensandbox-group/OpenSandbox/pull/2180)) ## Fast Sandbox - Make sandbox deletion reliable: deletion now sends a fenced Fastlet delete before any runtime-absence check, so a missing registry entry, transport failure, or empty inspect response is no longer treated as proof the sandbox is gone (which could orphan the microVM while the CR disappeared); the Fastlet records a per-identity tombstone so a delayed create cannot revive a deleted sandbox, and the cleanup finalizer is persisted at CR creation ([#2214](https://github.com/opensandbox-group/OpenSandbox/pull/2214)) - Make create placement recover faster: after proven rejections FastPath refreshes its candidate list within a bounded budget (excluding Fastlets already tried) and waits up to 2 s for assignment status to catch up before switching, and a process-local create tracker stops a deleted or replaced Fastlet pod from blocking the new assignment's projection or racing pod-loss recovery — the first-create happy path is unchanged ([#2214](https://github.com/opensandbox-group/OpenSandbox/pull/2214)) - Batch guest NAT updates: new guest-VM slots prepare dedicated DNAT/SNAT chains and restore replaces only those chains in one `iptables-restore --noflush` batch, so reapplying the same guest address no longer accumulates rules, with a new `fast_sandbox_network_guest_apply_stage_latency_seconds` metric separating the apply stages ([#2214](https://github.com/opensandbox-group/OpenSandbox/pull/2214)) ## Misc - Console: land the first slice of a new optional web console — a FastAPI BFF with httpOnly sessions and tenant/admin login proxying the lifecycle `/sandboxes` API (with a `runtimeSummary` on list/get), plus a React SPA covering tenant overview, sandbox list/create/detail, renew/delete, and the endpoint; first of five planned console PRs, with the admin UI to follow ([#2129](https://github.com/opensandbox-group/OpenSandbox/pull/2129)) - CLI: coerce config-file values to their declared types so a numeric `api_key` no longer silently resolves to null (breaking every command with a `ValidationError`) and a numeric `defaults.timeout` no longer crashes `sandbox create` ([#2169](https://github.com/opensandbox-group/OpenSandbox/pull/2169)); keep output writable on non-UTF-8 streams — GBK/cp1252/C-locale users could not run any `osb` command because emoji rendering raised `UnicodeEncodeError`, often after the work was already done; streams now escape unencodable characters and YAML output is re-dumped escaped to stay valid ([#2187](https://github.com/opensandbox-group/OpenSandbox/pull/2187)); write installed skills where each tool actually reads them — the `claude` target now writes `.claude/skills/<name>/SKILL.md` (the previous flat file was silently never loaded), and global `cline`/`copilot` targets write `~/.cline/rules/opensandbox-<name>.md` and `~/.copilot/copilot-instructions.md`; previously installed inert files are not migrated ([#2194](https://github.com/opensandbox-group/OpenSandbox/pull/2194) [#2208](https://github.com/opensandbox-group/OpenSandbox/pull/2208)) - Fast-sandbox integration environment: drive the verify stages through the published `osb` CLI instead of raw `curl` (template build, sandbox create/kill, endpoint fetch, pause/resume, snapshot create/get/list/delete/restore, renew), with `server_api` kept only for calls the CLI does not expose (networkpolicy replace PUT, RFC 7396 merge-patch, the snapshot re-entry code fence, gateway probes) ([#2171](https://github.com/opensandbox-group/OpenSandbox/pull/2171)); add an opt-in `IDLE_PAUSE=1` profile that deploys ephemeral Redis, enables the `[automation.idle_pause]` sweeper and gateway activity/wake values, and verifies the full auto-pause → wake-on-access loop on `up`, plus an SDK e2e suite and a nightly KVM workflow job ([#2202](https://github.com/opensandbox-group/OpenSandbox/pull/2202)) - Docs: accept and document OSEP-0024 — the proposal itself ([#2152](https://github.com/opensandbox-group/OpenSandbox/pull/2152)) plus an architecture page and user guide covering enablement, the `idlePolicy` field reference, the activity-probe contract, SDK wake-retry behavior, and an interactive diagram ([#2217](https://github.com/opensandbox-group/OpenSandbox/pull/2217)); unify component telemetry metrics from seven scattered locations into one reference at `docs/guides/telemetry.md` ([#2205](https://github.com/opensandbox-group/OpenSandbox/pull/2205)); refresh the network architecture pages with restyled SVG diagrams, a condensed egress page, and the network-isolation guide relocation ([#2210](https://github.com/opensandbox-group/OpenSandbox/pull/2210)); align CONTRIBUTING with the code (Go 1.25, Gin — not Beego) ([#2175](https://github.com/opensandbox-group/OpenSandbox/pull/2175)), dedupe `AGENTS.md` rules and state the architecture-vs-guides placement rule once ([#2211](https://github.com/opensandbox-group/OpenSandbox/pull/2211)), and fix the "shared Fastlet egress profile" misnomer to "shared egress process per Fastlet pod" with a note that gRPC ends at FastPath ([#2225](https://github.com/opensandbox-group/OpenSandbox/pull/2225)) - Tests/CI: align the node-agent log-collection e2e assertion with execd's preserved trailing newline ([#2164](https://github.com/opensandbox-group/OpenSandbox/pull/2164)); make the umbrella release workflow dispatch-only by dropping the weekly scheduled dry-run ([#2223](https://github.com/opensandbox-group/OpenSandbox/pull/2223)) - release: bump platform version to `1.2.0-rc.1` across charts and image references ## Upgrade & Compatibility - Behavior change: BatchSandbox pods now default to `restartPolicy: Never` (implicit `Always` → `Never`) — deployments that relied on the implicit default and want restarts must set `restartPolicy: Always` explicitly in their `batchsandbox_template_file` (a startup warning will note the trade-off) ([#2128](https://github.com/opensandbox-group/OpenSandbox/pull/2128)) - Behavior change: deleted sandboxes stay queryable in `Stopping` until runtime cleanup completes, and only then return 404 — clients sharing a persistent directory should wait for the 404 before starting a replacement ([#2154](https://github.com/opensandbox-group/OpenSandbox/pull/2154)) - Behavior change: execd CPU/memory metrics report sandbox-scoped values when the sandbox cgroup has limits configured (previously host-wide); `GET /metrics` field semantics and OTel metric names are unchanged, but dashboards will shift ([#2200](https://github.com/opensandbox-group/OpenSandbox/pull/2200)) - Behavior change: `networkPolicy` is rejected for Docker network modes `none`/`pasta`/`slirp4netns` — previously accepted silently for `none` ([#2203](https://github.com/opensandbox-group/OpenSandbox/pull/2203)) - Images: `opensandbox/<component>:release-1.2.0-rc.1` (all three registries) - Packages: unchanged — SDK/CLI artifacts publish at the `1.2.0` stable release - Charts: render from this tag (`helm template ./manifests/charts/opensandbox`) - Kubernetes: supported range v1.21 – v1.34 (charts declare `kubeVersion: ">=1.21.1-0"`) - Skew: server ↔ CLI/SDK same line supported; ±1 minor warns ## 👥 Contributors Thanks to these contributors ❤️ - @Dev-next-gen - @GodBlf - @JasonBuildAI - @Jinzhengxu - @Jun516 - @Pangjiping - @acodercat - @comqx - @hpliStartAgain - @kittimzhe - @mengdehong - @ranjianghong526-hash - @ratishjain12 - @zw11591-sketch ## Artifacts - Images: `opensandbox/<component>:release-1.2.0-rc.1` (Docker Hub / GHCR / ACR) ## Installation ```bash # Platform (Kubernetes) — render the chart at this tag and apply git clone https://github.com/opensandbox-group/OpenSandbox cd OpenSandbox git checkout release-1.2.0-rc.1 helm dependency build manifests/charts/opensandbox # package file:// sub-charts (not committed) # the default render needs required values (server env / api key) and the # ingress gateway — see docs/deployment before applying helm template ./manifests/charts/opensandbox | kubectl apply -f - # or point your GitOps platform (Argo / Flux) at the repo path + tag ``` Verify what you installed against the BOM: see [Release Verification](https://open-sandbox.ai/community/release-verification).
Related Repositories
public-apis/public-apis★ 491,131
A collective list of free APIs
NousResearch/hermes-agent★ 255,913
The agent that grows with you
yt-dlp/yt-dlp★ 200,005
A feature-rich command-line audio/video downloader
microsoft/markitdown★ 191,484
Python tool for converting files and office documents to Markdown.
Significant-Gravitas/AutoGPT★ 187,700
AutoGPT is the vision of accessible AI for everyone, to use and to build on. Our mission is to provide the tools, so that you can focus on what matters.