From 4cb81b2682d847e2512f19b4125e5643f60c12ec Mon Sep 17 00:00:00 2001 From: salamisandwich77 Date: Mon, 24 Aug 2026 16:17:04 +0700 Subject: [PATCH 1/6] docs: add the optional OpenShell microVM provider Adds the OpenShell provider page on top of the base sandbox section: the supported platforms and their published assets, the prepared VM cache, the OCI registry mode for development, registry CA trust on each platform, and the security properties and limitations. Restores the sidebar entry and the four cross-references from the native provider, provisioning, configuration, and sandbox-execution pages. The page states what this provider costs relative to the default: it needs a prepared image cache and a hypervisor, and OpenBox publishes a complete asset set only for Apple Silicon macOS and x86_64 glibc Linux. --- .../temporal-python/configuration.md | 2 +- .../temporal-python/native-provider.md | 5 +- .../temporal-python/openshell-provider.md | 262 ++++++++++++++++++ .../temporal-python/provisioning.md | 1 + .../authorize/sandbox-execution.md | 3 +- website/sidebars.js | 5 + 6 files changed, 275 insertions(+), 3 deletions(-) create mode 100644 website/docs/developer-guide/temporal-python/openshell-provider.md diff --git a/website/docs/developer-guide/temporal-python/configuration.md b/website/docs/developer-guide/temporal-python/configuration.md index 5f9090e..f0878db 100644 --- a/website/docs/developer-guide/temporal-python/configuration.md +++ b/website/docs/developer-guide/temporal-python/configuration.md @@ -206,7 +206,7 @@ plugin = OpenBoxPlugin( For a registered command, `CONSTRAIN` selects sandbox execution and aborts the corresponding host action before its side effect. Policy routing uses `constraints: ["run_in_sandbox"]`; a behavioral `CONSTRAIN` can select a registered replacement profile. Ordinary Temporal operations that cannot enforce `CONSTRAIN` fail closed. Keep all OpenBox setup in the same plugin initializer; there is no separate Worker path for sandboxed commands. -The sandbox runtime defaults to the `native` provider. Provision it with `obs provision --provider native --yes` (or omit `--provider` because `native` is the default), then load `~/.config/openbox-sandbox/agent.env`. +The sandbox runtime defaults to the `native` provider. Provision it with `obs provision --provider native --yes` (or omit `--provider` because `native` is the default), then load `~/.config/openbox-sandbox/agent.env`. For a guest-kernel boundary, provision the optional [OpenShell Provider (VM)](/developer-guide/temporal-python/openshell-provider) explicitly. See [Governed Sandbox Commands](/developer-guide/temporal-python/concept) for registry construction, native Worker composition, result bounds, and the zero-host deployment requirement. diff --git a/website/docs/developer-guide/temporal-python/native-provider.md b/website/docs/developer-guide/temporal-python/native-provider.md index bbd32e8..2b0237f 100644 --- a/website/docs/developer-guide/temporal-python/native-provider.md +++ b/website/docs/developer-guide/temporal-python/native-provider.md @@ -22,6 +22,8 @@ The native provider uses these platform controls: - **macOS:** Seatbelt through `/usr/bin/sandbox-exec`. - **Linux:** bubblewrap (`bwrap`). +Use the optional [OpenShell provider (VM)](./openshell-provider) when you require a guest-kernel boundary. + ## Requirements | Host | Requirements | @@ -93,7 +95,7 @@ Bubblewrap cannot filter destination addresses in a shared network namespace. Th Without another kernel network control, the allowlist cannot stop clients that bypass the proxy. -Use the deny-network template for bypass-resistant native Linux isolation. +Use the deny-network template for bypass-resistant native Linux isolation. Use the [OpenShell provider (VM)](./openshell-provider) if you require a network allowlist and a stronger Linux network boundary. ### Linux violation telemetry @@ -118,5 +120,6 @@ A clean rerun removes the runtime state that the launcher owns and recompiles th ## Related pages - [Governed Sandbox Commands](./concept): Registration of Temporal profiles and behavioral interception. +- [OpenShell Provider (VM)](./openshell-provider): The optional OpenShell provider with microVM isolation. - [Sandbox Execution](/trust-lifecycle/authorize/sandbox-execution): The lifecycle and evidence model. - [Error Handling](./error-handling): Fail-closed command outcomes. diff --git a/website/docs/developer-guide/temporal-python/openshell-provider.md b/website/docs/developer-guide/temporal-python/openshell-provider.md new file mode 100644 index 0000000..b917546 --- /dev/null +++ b/website/docs/developer-guide/temporal-python/openshell-provider.md @@ -0,0 +1,262 @@ +--- +title: OpenShell Provider (VM) +sidebar_label: OpenShell Provider (VM) +sidebar_position: 2 +description: "Provision the optional OpenShell microVM provider on macOS or Linux." +llms_description: OpenShell microVM provisioning, prepared caches, zot registry, CA trust, and platforms +slug: openshell-provider +tags: + - sdk + - temporal + - governance +--- + +# OpenShell Provider (VM) + +The optional OpenShell provider (`openshell`) runs admitted commands in a libkrun microVM with a guest kernel. + +## Isolation boundary + +The OpenShell provider uses these platform controls: + +- **macOS:** Hypervisor.framework. +- **Linux:** KVM. + +Select this provider with `--provider openshell` or `OPENBOX_PROVIDER=openshell`. The launcher never selects the OpenShell provider as a fallback from the default [native provider (`native`)](./native-provider). + +After a failure of the OpenShell provider, OpenBox does not retry the command under the native provider (`native`) or on the host. + +## Selection guidance + +Use the OpenShell provider when one of these requirements applies: + +- The command requires a VM boundary instead of a host operating system sandbox. +- A Linux network allowlist must stop clients that bypass `HTTP_PROXY` and `HTTPS_PROXY`. +- The command requires a prepared Linux guest image. +- Your deployment requires VM-backed isolation. + +Use the native provider (`native`) when you require a shorter local setup and lower startup cost. The native provider does not require an image cache. It also provides native filtering for each domain on macOS. + +The OpenShell provider adds a gateway, VM driver, guest image, cache lifecycle, and platform requirements. + +## Supported platforms + +| Host | VM boundary | Release support | Prepared cache | OCI and zot assets for development | +|---|---|---|---|---| +| macOS on Apple Silicon | Hypervisor.framework | Supported | `prepared-vm-cache-darwin-arm64.tar.gz` | `openbox-sandbox-dev-darwin-arm64-oci.tar.gz` and `zot-darwin-arm64` | +| Linux x86_64 with glibc 2.28 or later | KVM (`/dev/kvm`) | Supported | `prepared-vm-cache-linux-x86_64.tar.gz` | `openbox-sandbox-dev-linux-x86_64-oci.tar.gz` and `zot-linux-x86_64` | +| Linux arm64 | KVM | Incomplete. OpenShell can fetch aarch64 dependencies, but OpenBox does not publish the matching cache and pinned zot assets. | Not published | Not published | +| Intel macOS | Not available | OpenBox does not publish a VM bundle or cache. | Not published | Not published | +| Windows | Not available | Not supported directly. WSL2 requires readable nested `/dev/kvm`. | Not published | Not published | + +A launcher binary does not prove that a complete VM asset set exists. OpenBox publishes complete provider assets for Apple Silicon macOS and x86_64 glibc Linux. + +## Requirements + +### macOS + +The macOS host requires: + +- Apple Silicon. +- A `1` response from `sysctl -n kern.hv_support`. +- Xcode Command Line Tools, including `codesign`. +- Developer mode enabled with `sudo DevToolsSecurity -enable`. +- OpenSSL and `curl`. +- `e2fsprogs`, including `mkfs.ext4` or `mke2fs`, and `debugfs`. + +The launcher applies an ad hoc signature to the VM driver. The signature includes the `com.apple.security.hypervisor` entitlement. + +Provisioning installs `e2fsprogs` when Homebrew is available. Otherwise, install it before you retry: + +```bash +brew install e2fsprogs +``` + +### Linux + +The Linux host requires: + +- x86_64 with glibc 2.28 or later. +- Read access to `/dev/kvm`. +- OpenSSL, `curl`, and `e2fsprogs`. + +The released VM binaries do not support musl or Alpine Linux. + +If `/dev/kvm` exists but is not readable, add the operator to the `kvm` group according to your host policy. Then log out and log in again. + +Provisioning stops before the VM starts when `/dev/kvm` is inaccessible. + +## Install and provision + +Download the release assets as described in [Provisioning](./provisioning), plus two that only this provider needs: the OpenShell bundle and the prepared VM cache. + +OpenShell is a pinned external runtime. The hosted bundle locks OpenShell `0.0.88`. Alternatively, it accepts the corresponding approved source marker. The launcher verifies the OpenShell release assets. + +Provision this provider explicitly: + +```bash +obs provision --provider openshell --yes +``` + +`--yes` accepts non-privileged defaults. It does not bypass these checks: + +- KVM access +- VM driver signing +- `e2fsprogs` availability +- Asset verification +- Required CA trust + +Provisioning performs these actions: + +1. Starts the OpenShell gateway and VM driver. +2. Starts the loopback service with mTLS. +3. Verifies the selected policy and image identity. +4. Prepares or warms the image cache. +5. Runs a create, ready, and delete warm lifecycle. +6. Writes the same provider-neutral `agent.env` that the native provider writes. + +An application needs no code change when a registered command switches providers. + +## Prepared VM caches + +A cold image pull and ext4 conversion can take minutes. The release provides these caches for the supported platforms: + +- `prepared-vm-cache-darwin-arm64.tar.gz` +- `prepared-vm-cache-linux-x86_64.tar.gz` + +`obs provision` uses the matching cache by default. It verifies the cache with the checksum data that the release locks. It extracts the cache into VM driver state for each user. + +Then it runs a warm sandbox lifecycle. This lifecycle verifies that the driver accepts the cache. + +The cache uses these identity controls: + +- The state directory belongs to the current user and gateway. +- The `cache-image` file contains the expected sandbox image identity. +- The VM driver keys prepared content by immutable image identity, not by a mutable tag. + +Do not use a cache from another platform, architecture, user, gateway state layout, or image identity. + +A normal `--clean-rerun` preserves prepared images. Use `--purge-cache` for a full reset: + +```bash +obs provision --provider openshell --clean-rerun --purge-cache --yes +``` + +Skip cache use only during diagnosis: + +```bash +obs provision --provider openshell --no-vm-cache --yes +obs provision --provider openshell --skip-warm-cache --yes +``` + +If the prepared cache is missing, invalid, or rejected, provisioning can build it through the documented runtime fallback. Provisioning does not switch sandbox providers. + +## OCI registry mode for development + +The development release can serve the sandbox image without Docker or Podman. `obs update --dev --all` downloads these assets: + +- The platform-specific OpenBox OCI layout. +- The platform-specific service and policy assets. +- The prepared VM cache, when published. +- The pinned official zot `v2.1.20` binary for the platform. + +The launcher downloads zot from `project-zot/zot`. It verifies the binary against its platform pin. + +Download the assets, then provision the development release: + +```bash +obs update --dev --all +obs provision --provider openshell --dev --yes +``` + +When the OCI layout and zot are present, provisioning performs these actions: + +1. Extracts the OCI layout into runtime state that the launcher owns. +2. Generates a local TLS certificate for `127.0.0.1` and `localhost`. +3. Starts zot with HTTPS on loopback. The default port is `15000`. +4. Reads the registry manifest digest. +5. Configures a digest-pinned image reference in this form: `127.0.0.1:/openbox-sandboxes-dev@sha256:...`. + +Docker and Podman are optional. A container engine provides a fallback when the cache and registry assets cannot provide the development image. + +The container engine loads the development image locally. + +## Registry CA trust + +The OpenShell VM driver verifies registry HTTPS certificates. The host must trust the local zot certificate. + +The registry CA is separate from the mTLS identities for the SDK, the service, and the OpenShell gateway. + +### macOS trust + +Provisioning first tries to add the certificate to the login keychain. If that keychain is locked or rejects the certificate, the launcher requests `sudo` access. + +The launcher then tries the system keychain. + +If both operations fail, provisioning stops. It prints this one-time command: + +```bash +sudo security add-trusted-cert -d -r trustRoot \ + -k /Library/Keychains/System.keychain \ + "$HOME/.local/state/openbox-sandbox/zot/tls/cert.pem" +``` + +Confirm that the path contains the certificate that the launcher owns. Then provision the provider again. + +Alternatively, unlock the login keychain instead of changing system trust. + +### Linux trust + +Provisioning writes a CA copy to: + +```text +~/.local/state/openbox-sandbox/certs/openbox-registry-ca.crt +``` + +When passwordless authorization is available, provisioning copies the CA under `/usr/local/share/ca-certificates/`. It then runs `update-ca-certificates`. + +If you cannot update the system trust, install the CA that the launcher owns according to your distribution policy. Then provision the provider again. + +The VM driver can reject the registry until the host trusts the CA. + +## Security properties + +The OpenShell provider retains the provider-neutral lifecycle and admission controls: + +- It executes an exact registered argument vector without a shell. +- It verifies immutable policy and image identities. +- It bounds command output and execution time. +- It uses mTLS between the service for the SDK and the runtime boundary. +- It performs create, ready, execute, delete, and terminal-absence checks that the request owns. +- It never uses host execution after a `CONSTRAIN` dispatch. + +The VM supplies a guest-kernel and hardware isolation boundary. Enforcement of the policy inside the guest depends on the pinned OpenShell image, supervisor, and policy. + +A prepared cache reduces startup time. It does not replace identity verification. + +## Limitations + +- The OpenShell provider has higher startup and resource costs than the native provider (`native`). +- Cache warming requires `e2fsprogs`, even without a container engine. +- Registry mode requires host CA trust. `--yes` does not bypass this requirement. +- Linux requires readable KVM and compatible glibc. +- A cache miss can slow the first request or require the container engine fallback. +- OpenBox does not publish a complete VM path for Windows or Intel macOS. + +## Operations + +Use these commands to inspect, verify, provision again, or remove the provider: + +```bash +obs status +obs provision --provider openshell --clean-rerun --yes +obs uninstall +``` + +`obs --verify-runtime` checks local artifact and version compatibility only. It does not connect to the gateway or create a VM. + +## Related pages + +- [Governed Sandbox Commands](./concept): Shared profiles, interception, results, and evidence. +- [Native Provider](./native-provider): The default native provider and its platform limits. +- [Sandbox Execution](/trust-lifecycle/authorize/sandbox-execution): The governance model that is independent of the provider. diff --git a/website/docs/developer-guide/temporal-python/provisioning.md b/website/docs/developer-guide/temporal-python/provisioning.md index 449483e..02a4ced 100644 --- a/website/docs/developer-guide/temporal-python/provisioning.md +++ b/website/docs/developer-guide/temporal-python/provisioning.md @@ -137,3 +137,4 @@ Load the generated provider-neutral values into the Worker process, as shown in ## Provider guides - [Native Provider](./native-provider): Requirements, network behavior, and limitations for Seatbelt and bubblewrap. +- [OpenShell Provider (VM)](./openshell-provider): Requirements for microVMs, prepared caches, registry mode, and CA trust. diff --git a/website/docs/trust-lifecycle/authorize/sandbox-execution.md b/website/docs/trust-lifecycle/authorize/sandbox-execution.md index 2a8915d..6332f11 100644 --- a/website/docs/trust-lifecycle/authorize/sandbox-execution.md +++ b/website/docs/trust-lifecycle/authorize/sandbox-execution.md @@ -81,7 +81,7 @@ The sandbox service and its mTLS credentials run in infrastructure that you cont The local service owns scope creation, execution, cleanup, and restart reconciliation for each request. -Provider selection is explicit. A provider startup or execution failure does not cause fallback. +The optional [OpenShell Provider (VM)](/developer-guide/temporal-python/openshell-provider) uses Hypervisor.framework or KVM to provide a guest-kernel boundary. Provider selection is explicit. A provider startup or execution failure does not cause fallback. ## Configuration @@ -119,3 +119,4 @@ Treat a command as indeterminate when cleanup or terminal absence is uncertain. - [Authorize Phase](/trust-lifecycle/authorize): Location of `CONSTRAIN` in the authorization pipeline. - [Governed Sandbox Commands](/developer-guide/temporal-python/concept): Temporal interception, profiles, and results. - [Native Provider](/developer-guide/temporal-python/native-provider): Native installation, verification, and limitations. +- [OpenShell Provider (VM)](/developer-guide/temporal-python/openshell-provider): Optional microVM provider. diff --git a/website/sidebars.js b/website/sidebars.js index 078abc4..58caadf 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -475,6 +475,11 @@ const sidebars = { id: 'developer-guide/temporal-python/native-provider', className: 'sidebar-item--diff', }, + { + type: 'doc', + id: 'developer-guide/temporal-python/openshell-provider', + className: 'sidebar-item--diff', + }, ], }, { From b328506030799a6cd2ed5ba0ff557a15f8cfc12f Mon Sep 17 00:00:00 2001 From: salamisandwich77 Date: Tue, 25 Aug 2026 18:30:12 +0700 Subject: [PATCH 2/6] docs: drop --yes from the OpenShell page The flag did nothing and has now been removed from the launcher, so a command carrying it fails rather than being ignored. The page also described it as accepting defaults and not bypassing the KVM, signing, and CA-trust checks; provisioning never prompts, and those checks stand on their own. --- .../temporal-python/openshell-provider.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/website/docs/developer-guide/temporal-python/openshell-provider.md b/website/docs/developer-guide/temporal-python/openshell-provider.md index b917546..1d0c1ed 100644 --- a/website/docs/developer-guide/temporal-python/openshell-provider.md +++ b/website/docs/developer-guide/temporal-python/openshell-provider.md @@ -95,10 +95,10 @@ OpenShell is a pinned external runtime. The hosted bundle locks OpenShell `0.0.8 Provision this provider explicitly: ```bash -obs provision --provider openshell --yes +obs provision --provider openshell ``` -`--yes` accepts non-privileged defaults. It does not bypass these checks: +Provisioning never prompts, and it does not bypass these checks: - KVM access - VM driver signing @@ -139,14 +139,14 @@ Do not use a cache from another platform, architecture, user, gateway state layo A normal `--clean-rerun` preserves prepared images. Use `--purge-cache` for a full reset: ```bash -obs provision --provider openshell --clean-rerun --purge-cache --yes +obs provision --provider openshell --clean-rerun --purge-cache ``` Skip cache use only during diagnosis: ```bash -obs provision --provider openshell --no-vm-cache --yes -obs provision --provider openshell --skip-warm-cache --yes +obs provision --provider openshell --no-vm-cache +obs provision --provider openshell --skip-warm-cache ``` If the prepared cache is missing, invalid, or rejected, provisioning can build it through the documented runtime fallback. Provisioning does not switch sandbox providers. @@ -166,7 +166,7 @@ Download the assets, then provision the development release: ```bash obs update --dev --all -obs provision --provider openshell --dev --yes +obs provision --provider openshell --dev ``` When the OCI layout and zot are present, provisioning performs these actions: @@ -238,7 +238,7 @@ A prepared cache reduces startup time. It does not replace identity verification - The OpenShell provider has higher startup and resource costs than the native provider (`native`). - Cache warming requires `e2fsprogs`, even without a container engine. -- Registry mode requires host CA trust. `--yes` does not bypass this requirement. +- Registry mode requires host CA trust. Provisioning does not bypass this requirement. - Linux requires readable KVM and compatible glibc. - A cache miss can slow the first request or require the container engine fallback. - OpenBox does not publish a complete VM path for Windows or Intel macOS. @@ -249,7 +249,7 @@ Use these commands to inspect, verify, provision again, or remove the provider: ```bash obs status -obs provision --provider openshell --clean-rerun --yes +obs provision --provider openshell --clean-rerun obs uninstall ``` From 9a70cdb7aa8edb1bd605fb92fab35848c35a8de2 Mon Sep 17 00:00:00 2001 From: salamisandwich77 Date: Wed, 26 Aug 2026 14:22:30 +0700 Subject: [PATCH 3/6] docs: make the Quick Start steps survive a first read Four things stopped the page working as written. The published SDK installs without error and does not contain `openbox.sandbox`, so the example died at an import in step 4 with nothing on the page explaining it. Step 3 now states that plainly and gives the editable install that does work. `temporal server start-dev` was a clause inside a sentence about other requirements. It is a hard prerequisite for step 4, so it is a command block of its own. `uv init` writes a `main.py` that `uv run python .` ignores, which is confusing next to an example made of two other files. The page says to remove it. Troubleshooting named an error the example cannot produce: it reads the boundary values from the environment directly, so a missing one raises `KeyError`, not the SDK's message. That entry is corrected, and entries for the missing module and for a port still held by an earlier service are added. --- .../temporal-python/quick-start.md | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/website/docs/developer-guide/temporal-python/quick-start.md b/website/docs/developer-guide/temporal-python/quick-start.md index 3e8470a..971f976 100644 --- a/website/docs/developer-guide/temporal-python/quick-start.md +++ b/website/docs/developer-guide/temporal-python/quick-start.md @@ -19,7 +19,13 @@ A `CONSTRAIN` verdict stops a Temporal activity before its body runs and execute | macOS 26 on Apple Silicon | `curl` and `/usr/bin/sandbox-exec` | Both ship with macOS. Install nothing. | | Linux x86_64 | `curl` and the `bwrap` binary | Install the `bubblewrap` package. The kernel must permit unprivileged namespaces. | -You also need `uv`, a running `temporal server start-dev`, and an `OPENBOX_API_KEY` from a [registered agent](/dashboard/agents/registering-agents). +You also need `uv` and an `OPENBOX_API_KEY` from a [registered agent](/dashboard/agents/registering-agents). + +A Temporal server must be running before step 4. Leave this in its own terminal: + +```bash +temporal server start-dev +``` ## 1. Provision the sandbox @@ -62,9 +68,25 @@ Without this rule the verdict is `ALLOW` and the activity runs on the host. ```bash uv init +rm main.py uv add openbox-temporal-sdk-python temporalio httpx ``` +`uv init` writes a `main.py`. Remove it, because `uv run python .` runs +`__main__.py`. + +:::caution The sandbox module is not in the published SDK yet +`openbox-temporal-sdk-python` 1.4.0 installs without error, but it does not +contain `openbox.sandbox`, which this example imports. Step 4 then stops at +`ModuleNotFoundError: No module named 'openbox.sandbox'`. Until a release +carries that module, install the SDK from a checkout that has it: + +```bash +uv add --editable /path/to/openbox-sdk-python +uv add --editable /path/to/openbox-temporal-sdk-python +``` +::: + The example is two files, `workflow.py` and `__main__.py`. The workflow goes in its own module. The Worker re-imports the workflow module inside the Temporal workflow sandbox, and that sandbox rejects a module that can perform I/O. Keeping the workflow away from `httpx` and the OpenBox imports satisfies it. @@ -246,9 +268,16 @@ No rule matched, so the verdict was `ALLOW` and the body ran on the host. Check The Worker has no sandbox configuration. Confirm that one `OpenBoxPlugin` receives `sandbox=SandboxConfig(...)`, that the requested profile exists in the registry, and that `agent.env` is loaded in the Worker process. -### `missing required env var: OPENBOX_SANDBOX_ENDPOINT` +### `KeyError: 'OPENBOX_SANDBOX_CONFIG_PATH'` The shell did not source `agent.env`, or it sourced the file without `set -a`. +The example reads the boundary values straight from the environment, so the +first missing one raises `KeyError`. Run the `set -a` line from step 4 in the +same shell as the Worker. + +### `ModuleNotFoundError: No module named 'openbox.sandbox'` + +The installed SDK does not carry the sandbox module. See the note in step 3. ### The request to `example.com` is refused @@ -262,6 +291,16 @@ The loaded environment and the provisioned policy differ. ./obs provision --clean-rerun ``` +### `sandbox service port 17443 remains occupied` + +A service is still listening, and the launcher will not signal a process it +cannot identify as its own. This happens when a PID file was removed while the +service kept running. Stop the listener, then provision again: + +```bash +lsof -nP -iTCP:17443 -sTCP:LISTEN -t | xargs kill +``` + ### Provisioning fails Provisioning fails closed when it cannot verify a release asset, the policy, or the provider. Confirm every asset came from one release, verify `SHA256SUMS`, then provision again with `--clean-rerun`. There is no provider fallback. From 01c19c9f762fe421c11e433712a693e65e9ba2f9 Mon Sep 17 00:00:00 2001 From: salamisandwich77 Date: Wed, 26 Aug 2026 14:26:25 +0700 Subject: [PATCH 4/6] docs: document the SDK install as it will ship The page carried a caution that the published SDK lacks openbox.sandbox and told the reader to install from a local checkout. The sandbox work is treated as merged, so the documented install is the plain one. --- .../temporal-python/quick-start.md | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/website/docs/developer-guide/temporal-python/quick-start.md b/website/docs/developer-guide/temporal-python/quick-start.md index 971f976..880426d 100644 --- a/website/docs/developer-guide/temporal-python/quick-start.md +++ b/website/docs/developer-guide/temporal-python/quick-start.md @@ -75,18 +75,6 @@ uv add openbox-temporal-sdk-python temporalio httpx `uv init` writes a `main.py`. Remove it, because `uv run python .` runs `__main__.py`. -:::caution The sandbox module is not in the published SDK yet -`openbox-temporal-sdk-python` 1.4.0 installs without error, but it does not -contain `openbox.sandbox`, which this example imports. Step 4 then stops at -`ModuleNotFoundError: No module named 'openbox.sandbox'`. Until a release -carries that module, install the SDK from a checkout that has it: - -```bash -uv add --editable /path/to/openbox-sdk-python -uv add --editable /path/to/openbox-temporal-sdk-python -``` -::: - The example is two files, `workflow.py` and `__main__.py`. The workflow goes in its own module. The Worker re-imports the workflow module inside the Temporal workflow sandbox, and that sandbox rejects a module that can perform I/O. Keeping the workflow away from `httpx` and the OpenBox imports satisfies it. @@ -275,9 +263,6 @@ The example reads the boundary values straight from the environment, so the first missing one raises `KeyError`. Run the `set -a` line from step 4 in the same shell as the Worker. -### `ModuleNotFoundError: No module named 'openbox.sandbox'` - -The installed SDK does not carry the sandbox module. See the note in step 3. ### The request to `example.com` is refused From 1f4313c173a8aed25824cf5c758395ea37241876 Mon Sep 17 00:00:00 2001 From: salamisandwich77 Date: Wed, 26 Aug 2026 14:31:50 +0700 Subject: [PATCH 5/6] docs: configure the plugin the way it is actually configured Configuration listed seven environment variables and said parameters override them. The package reads the process environment once, in sandbox/deployment.py, and that read has nothing to do with plugin configuration. Setting OPENBOX_GOVERNANCE_TIMEOUT, OPENBOX_ENABLED, OPENBOX_GOVERNANCE_POLICY, OPENBOX_SEND_START_EVENT or OPENBOX_SEND_ACTIVITY_START_EVENT changed nothing. The plugin takes constructor parameters. OPENBOX_URL and OPENBOX_API_KEY are conventional names that your own code reads and passes in, which is why the example does exactly that. The walkthrough's .env carried four of the inert variables, including OPENBOX_GOVERNANCE_MAX_RETRIES, which is not a parameter either. Also relabels a constructor signature in the SDK reference as text, since it is an illustration rather than code that parses. --- .../temporal-python/configuration.md | 31 ++++++++++--------- .../integration-walkthrough.mdx | 4 --- .../temporal-python/sdk-reference.md | 2 +- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/website/docs/developer-guide/temporal-python/configuration.md b/website/docs/developer-guide/temporal-python/configuration.md index 5767a0f..0e2179f 100644 --- a/website/docs/developer-guide/temporal-python/configuration.md +++ b/website/docs/developer-guide/temporal-python/configuration.md @@ -12,25 +12,26 @@ tags: The sole OpenBox integration surface is the native Temporal `Worker(..., plugins=[OpenBoxPlugin(...)])` shape. The plugin initializer owns all OpenBox Worker, Workflow, and Activity setup. -The plugin can be configured via environment variables or constructor parameters. +The plugin is configured with constructor parameters. It does not read +environment variables: the package reads the process environment in exactly one +place, and that place is unrelated to plugin configuration. -## Environment Variables +## Credentials -| Variable | Required | Default | Description | -| ----------------------------------- | -------- | ----------- | --------------------------------------------------------- | -| `OPENBOX_URL` | Yes | - | OpenBox Core API URL (HTTPS required for non-localhost) | -| `OPENBOX_API_KEY` | Yes | - | API key for authentication (`obx_live_*` or `obx_test_*`) | -| `OPENBOX_ENABLED` | No | `true` | Enable/disable governance | -| `OPENBOX_GOVERNANCE_TIMEOUT` | No | `30.0` | Seconds to wait for governance evaluation | -| `OPENBOX_GOVERNANCE_POLICY` | No | `fail_open` | Behavior when API unreachable | -| `OPENBOX_SEND_START_EVENT` | No | `true` | Send WorkflowStarted events | -| `OPENBOX_SEND_ACTIVITY_START_EVENT` | No | `true` | Send ActivityStarted events | +`OPENBOX_URL` and `OPENBOX_API_KEY` are the conventional names for the two +values every deployment needs. Your own code reads them and passes them in, so +the key never appears in source: -## Plugin Parameters - -Parameters passed to `OpenBoxPlugin()` override environment variables: +```python +OpenBoxPlugin( + openbox_url=os.environ["OPENBOX_URL"], + openbox_api_key=os.environ["OPENBOX_API_KEY"], +) +``` -See **[Example: Full Configuration](#example-full-configuration)** for a complete example. +Everything else is a parameter with a default. Setting a variable such as +`OPENBOX_GOVERNANCE_TIMEOUT` in the environment has no effect; pass +`governance_timeout` instead. ## Configuration Options diff --git a/website/docs/developer-guide/temporal-python/integration-walkthrough.mdx b/website/docs/developer-guide/temporal-python/integration-walkthrough.mdx index a36f45d..354a644 100644 --- a/website/docs/developer-guide/temporal-python/integration-walkthrough.mdx +++ b/website/docs/developer-guide/temporal-python/integration-walkthrough.mdx @@ -87,10 +87,6 @@ TEMPORAL_ADDRESS=localhost:7233 # OpenBox (use the API key from Part 2) OPENBOX_URL=https://core.openbox.ai OPENBOX_API_KEY=your-openbox-api-key -OPENBOX_GOVERNANCE_ENABLED=true -OPENBOX_GOVERNANCE_TIMEOUT=30.0 -OPENBOX_GOVERNANCE_MAX_RETRIES=1 -OPENBOX_GOVERNANCE_POLICY=fail_open ``` ## Part 4: Run the Demo diff --git a/website/docs/developer-guide/temporal-python/sdk-reference.md b/website/docs/developer-guide/temporal-python/sdk-reference.md index 20f1961..9034a29 100644 --- a/website/docs/developer-guide/temporal-python/sdk-reference.md +++ b/website/docs/developer-guide/temporal-python/sdk-reference.md @@ -54,7 +54,7 @@ See: ## Plugin Usage -```python +```text from openbox import OpenBoxPlugin from openbox.sandbox import SandboxConfig From 4ee28a004187b43645000cd98a426a8b9f961004 Mon Sep 17 00:00:00 2001 From: salamisandwich77 Date: Wed, 26 Aug 2026 14:35:46 +0700 Subject: [PATCH 6/6] docs: show how to drive plugin options from the environment Saying the variables have no effect answered half the question. The SDK's own README documents OPENBOX_GOVERNANCE_TIMEOUT and OPENBOX_GOVERNANCE_POLICY as names an application reads and passes in, the same way the examples already treat OPENBOX_URL and OPENBOX_API_KEY. The page now shows that pattern. --- .../temporal-python/configuration.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/website/docs/developer-guide/temporal-python/configuration.md b/website/docs/developer-guide/temporal-python/configuration.md index 0e2179f..f3149fb 100644 --- a/website/docs/developer-guide/temporal-python/configuration.md +++ b/website/docs/developer-guide/temporal-python/configuration.md @@ -29,9 +29,20 @@ OpenBoxPlugin( ) ``` -Everything else is a parameter with a default. Setting a variable such as -`OPENBOX_GOVERNANCE_TIMEOUT` in the environment has no effect; pass -`governance_timeout` instead. +Everything else is a parameter with a default. To drive any of them from the +environment, read the variable yourself and pass the value in: + +```python +OpenBoxPlugin( + openbox_url=os.environ["OPENBOX_URL"], + openbox_api_key=os.environ["OPENBOX_API_KEY"], + governance_timeout=float(os.getenv("OPENBOX_GOVERNANCE_TIMEOUT", "30.0")), + governance_policy=os.getenv("OPENBOX_GOVERNANCE_POLICY", "fail_open"), +) +``` + +Setting those variables without reading them changes nothing, because the +plugin never looks at them. ## Configuration Options