Skip to content
Draft
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
14 changes: 10 additions & 4 deletions .agents/skills/debug-openshell-cluster/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ The target deployment flow is:
4. The CLI registers a reachable gateway endpoint with `openshell gateway add`.
5. The gateway creates sandboxes through the selected compute driver.

The standard gateway binary explicitly installs its compiled Docker, Podman,
Kubernetes, and VM registrations at startup. With no configured driver, the
The `openshell-gateway` composition crate explicitly installs its compiled
Docker, Podman, Kubernetes, and VM registrations at startup; `openshell-server`
does not link compute-driver crates. With no configured driver, the
gateway probes only installed registrations in priority order (Kubernetes,
Podman, then Docker); VM has no probe and remains opt-in. A custom gateway
binary may install a different set, so confirm the binary's registered drivers
Expand Down Expand Up @@ -453,8 +454,13 @@ Then inspect sandbox resources in that namespace.

Check the configured sandbox service account when TokenReview bootstrap or
sandbox registration fails. Helm creates a dedicated sandbox service account by
default and writes it to `[openshell.drivers.kubernetes].service_account_name`;
the gateway rejects projected tokens from other service accounts.
default. The driver receives it in
`[openshell.drivers.kubernetes].service_account_name`, while the independent
gateway authenticator receives it in
`[openshell.gateway.sandbox_token_bootstrap].service_account_name`; the gateway
rejects projected tokens from other service accounts. Confirm the bootstrap
table also contains exactly one of `namespace`, `namespace_prefix`,
`namespace_label`, or `namespace_file`.

```bash
helm -n openshell get values openshell | grep -A3 sandboxServiceAccount
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ jobs:
run: |
set -euo pipefail
mise x -- rustup target add ${{ matrix.target }}
mise x -- cargo zigbuild --release --target ${{ matrix.zig_target }} -p openshell-server --bin openshell-gateway --features bundled-z3
mise x -- cargo zigbuild --release --target ${{ matrix.zig_target }} -p openshell-gateway --bin openshell-gateway --features bundled-z3
mkdir -p artifacts/bin
install -m 0755 target/${{ matrix.target }}/release/openshell-gateway artifacts/bin/openshell-gateway

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ jobs:
run: |
set -euo pipefail
mise x -- rustup target add ${{ matrix.target }}
mise x -- cargo zigbuild --release --target ${{ matrix.zig_target }} -p openshell-server --bin openshell-gateway --features bundled-z3
mise x -- cargo zigbuild --release --target ${{ matrix.zig_target }} -p openshell-gateway --bin openshell-gateway --features bundled-z3
mkdir -p artifacts/bin
install -m 0755 target/${{ matrix.target }}/release/openshell-gateway artifacts/bin/openshell-gateway

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust-native-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ jobs:

case "$COMPONENT" in
gateway)
crate=openshell-server
crate=openshell-gateway
binary=openshell-gateway
zig_target=
;;
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ These pipelines connect skills into end-to-end workflows. Individual skill files
| `crates/openshell-otel/` | OpenTelemetry support | Shared OTLP trace provider, resource, and tracing-layer construction |
| `crates/openshell-core/` | Shared core | Common types, configuration, error handling |
| `crates/openshell-extension-core/` | Extension core | Shared extension identity, JWT claims, bearer-token rotation, and TLS transport primitives |
| `crates/openshell-gateway/` | Gateway binary composition | Links selected first-party compute drivers into the backend-agnostic server registry |
| `crates/openshell-sdk/` | Shared client SDK | Async Rust gateway client (gRPC transport, TLS, OIDC refresh, edge tunnel); consumed by CLI, TUI, and `@openshell/sdk` |
| `crates/openshell-providers/` | Provider management | Credential provider backends |
| `crates/openshell-tui/` | Terminal UI | Ratatui-based dashboard for monitoring |
Expand Down
26 changes: 23 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ OpenShell collects anonymous telemetry to help improve the project for developer

Disable telemetry at runtime by setting `OPENSHELL_TELEMETRY_ENABLED=false` on the gateway deployment. For Helm installs, set `server.telemetryEnabled=false`. OpenShell propagates this deployment setting into sandbox supervisor environments so sandbox-side telemetry collection is disabled as well.

You can also compile telemetry out entirely. Telemetry support is a default-on `telemetry` Cargo feature; building with `--no-default-features` produces binaries that contain no telemetry endpoint, no telemetry HTTP client, and no emission code. Build telemetry-free artifacts with, for example, `cargo build --release -p openshell-server --no-default-features` (gateway) and the equivalent for `openshell-sandbox` and `openshell-driver-vm`. With telemetry compiled out, the gateway emits nothing and reports telemetry disabled to the sandboxes it launches.
You can also compile telemetry out entirely. Telemetry support is a default-on `telemetry` Cargo feature; building with `--no-default-features` produces binaries that contain no telemetry endpoint, no telemetry HTTP client, and no emission code. Build a telemetry-free gateway with `cargo build --release -p openshell-gateway --no-default-features --features in-tree-compute-drivers`, and use the equivalent feature selection for `openshell-sandbox` and `openshell-driver-vm`. With telemetry compiled out, the gateway emits nothing and reports telemetry disabled to the sandboxes it launches.

Telemetry events are limited to anonymous operational categories and counts, such as sandbox lifecycle outcomes, provider profile buckets, policy decision counts, and aggregate network activity denial categories. OpenShell telemetry does not collect sandbox names or IDs, hostnames, file paths, binary paths, prompts, credentials, provider names, model names, or user content.

Expand Down
4 changes: 2 additions & 2 deletions architecture/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ OpenShell builds these main artifacts:

| Artifact | Source |
|---|---|
| Gateway binary | `crates/openshell-server` |
| Gateway binary | `crates/openshell-gateway` |
| CLI package and Python SDK | `python/openshell` plus Rust binaries where packaged |
| TypeScript SDK package | `sdk/typescript` |
| Gateway container image | `deploy/docker/Dockerfile.gateway` |
Expand All @@ -26,7 +26,7 @@ Sandbox community images are built outside this repository.
Anonymous telemetry emission is gated behind a default-on `telemetry` Cargo
feature. It is defined in `openshell-core` (where the emission code, HTTP
client, and endpoint live) and forwarded by the binary crates that emit or
collect telemetry: `openshell-server` (gateway), `openshell-sandbox`
collect telemetry: `openshell-gateway`, `openshell-sandbox`
(supervisor), and `openshell-driver-vm`. Every crate depends on
`openshell-core` with `default-features = false`, so the binary crate's feature
is the single switch that enables `openshell-core/telemetry` for its build
Expand Down
53 changes: 30 additions & 23 deletions architecture/compute-runtimes.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,8 @@ of re-querying drivers on each request.
The gateway binary explicitly installs the compute drivers compiled into that
binary before entering server startup. The server selects a configured driver
by normalized registry name. When no driver is configured, it evaluates only
the installed drivers' probes in registered priority order, records every
available registration, and selects the first. Drivers without a probe,
including VM, remain opt-in.
the installed drivers' probes and chooses the lowest registered priority.
Drivers without a probe, including VM, remain opt-in.

Startup computes this selection once after merging configuration. The same
selection drives authentication defaults and runtime construction, so a probe
Expand All @@ -117,17 +116,18 @@ registry. Adding or removing a compiled driver therefore changes registration
rather than the server's selection flow. Alternate gateway binaries can install
their own `ComputeDriverFactory` registrations and hand the completed registry
to `run_cli_with_compute_drivers`; factories receive merged driver config and
finish through the same in-process runtime adapter. A configured UDS endpoint
still takes precedence over a compiled registration with the same name.

The standard server crate groups first-party registrations behind the
`in-tree-compute-drivers` feature. Protocol-only gateway builds disable that
feature and link no compute-driver crates. E2E lanes compose that gateway with
Docker, Podman, Kubernetes, and VM driver executables over the public UDS gRPC
contract so an in-tree driver cannot silently depend on a server-only API.
External Kubernetes drivers support shared and managed workspace modes.
Operator mode requires an in-process dynamic namespace allowlist and is
rejected when Kubernetes is configured through an external endpoint.
return either an in-process driver or a gateway-managed remote endpoint. The
server constructs the common runtime adapter and snapshots `GetCapabilities`
for either result. A configured UDS endpoint still takes precedence over a
compiled registration with the same name.

The `openshell-gateway` composition crate groups first-party registrations
behind the `in-tree-compute-drivers` feature. `openshell-server` has no compute
driver dependencies or backend-name dispatch. Protocol-only gateway builds
disable the composition feature and link no compute-driver crates. E2E lanes
compose that gateway with Docker, Podman, Kubernetes, and VM driver executables
over the public UDS gRPC contract so an in-tree driver cannot silently depend
on a server-only API.

## Stop and Start Lifecycle

Expand Down Expand Up @@ -436,13 +436,13 @@ image-pull Secrets in every operator-managed namespace.

**Operator** uses pre-provisioned namespaces discovered through two optional
sources: a K8s label selector (`operator_namespace_label`) and a drop-in
allowlist file (`operator_namespace_file`). At least one must be configured.
The `OperatorNamespaceAllowlist` (`Arc<RwLock<BTreeSet<String>>>`) is populated
at runtime by background watchers and read by the namespace resolver. Sandbox
creation fails closed if the workspace is not in the current allowlist. Platform
teams manage namespace lifecycle externally. RBAC uses the same ClusterRole as
managed mode but without namespace `create`/`delete` or ServiceAccount
permissions.
allowlist file (`operator_namespace_file`). Exactly one must be configured.
The compute driver and the gateway's ServiceAccount authenticator independently
watch that public config source; no in-process driver state crosses into the
server. Sandbox creation and token bootstrap fail closed if the workspace is
not in the current allowlist. Platform teams manage namespace lifecycle
externally. RBAC uses the same ClusterRole as managed mode but without namespace
`create`/`delete` or ServiceAccount permissions.

### Watching and Querying

Expand All @@ -455,15 +455,22 @@ watcher emits only sandbox CR changes, not platform events.

### SA Token Authentication

The gateway's `K8sServiceAccountAuthenticator` adapts its `NamespaceValidator`
per mode (`crates/openshell-server/src/auth/k8s_sa.rs`):
The gateway owns ServiceAccount bootstrap under
`[openshell.gateway.sandbox_token_bootstrap]`, independently of compute-driver
selection. The Helm chart maps its workspace mode into the corresponding
`NamespaceValidator` (`crates/openshell-server/src/auth/k8s_sa.rs`):

- **Shared:** `Exact` — accepts only the single configured namespace.
- **Managed:** `Prefix` — accepts any namespace starting with `openshell-{gateway_id}-`.
- **Operator:** `Allowlist` — accepts namespaces present in the dynamic
`BTreeSet` populated by the label/file watchers. Starts empty (fail-closed)
until the first watcher update.

The compiled Kubernetes registration derives the same policy from legacy
driver configuration for compatibility. Operator-managed external drivers use
the gateway-owned table directly; unrelated external drivers do not acquire a
Kubernetes bootstrap requirement merely because the gateway runs in-cluster.

These checks rely on an ownership invariant. In shared and managed modes, the
gateway and its trusted Agent Sandbox controller exclusively administer the
sandbox namespace, Sandbox CRs, sandbox pods, and configured sandbox
Expand Down
Loading
Loading