feat(deployments): OpenShell sandboxed deployment backend (AIRCORE-872)#662
Draft
maxdubrinsky wants to merge 14 commits into
Draft
feat(deployments): OpenShell sandboxed deployment backend (AIRCORE-872)#662maxdubrinsky wants to merge 14 commits into
maxdubrinsky wants to merge 14 commits into
Conversation
Contributor
|
maxdubrinsky
force-pushed
the
aircore-872-openshell-deployment-target/md
branch
from
July 15, 2026 17:17
5b25cc0 to
3c9f550
Compare
maxdubrinsky
force-pushed
the
aircore-872-openshell-deployment-target/md
branch
from
July 22, 2026 18:57
a3e43ad to
04b9b31
Compare
Add the `openshell` Python SDK as the nemo-deployments plugin's optional `[openshell]` extra and dev dependency-group, alongside grpcio/protobuf. The SDK is on PyPI and resolves like any other dependency; no vendored gRPC stubs and no local wheel pin. Pin as `openshell>=0.0.83` and let `uv.lock` hold the exact resolved version so the lockfile carries the pin without churning pyproject on every SDK bump. AIRCORE-872 (892) Signed-off-by: Max Dubrinsky <[email protected]>
Build the OpenShell SandboxPolicy for a deployment: a default-deny filesystem/process allowlist plus a mandatory, always-injected platform-egress rule so the sandbox's only outbound path is back to the Inference Gateway. A static-YAML policy override is supported for callers that need to hand-tune the allowlist. AIRCORE-872 (891) Signed-off-by: Max Dubrinsky <[email protected]>
Implement OpenShellDeploymentBackend against the DeploymentBackend ABC (create / read_status / delete / expose) over the OpenShell gRPC gateway, and register it in BACKEND_CLASSES. The backend applies the generated SandboxPolicy and serve workdir when it stands a deployment up, so an agent deployed through the standard deployments API runs inside a policy-governed sandbox. Covered by mocked unit tests, an executor-config test, and a live-gateway integration test. AIRCORE-872 (887) Signed-off-by: Max Dubrinsky <[email protected]>
Add a provider-neutral `--sandbox-runtime` image profile to `nemo agents package` so an agent can be packaged for a sandbox runtime (openshell) without hand-editing the container build. The nemo-deployments plugin contributes the `openshell` profile via the `nemo.sandbox_profiles` entry point; the agents container builder/template consume the selected profile. build-agent skill docs updated to mention the flag. AIRCORE-872 (888) Signed-off-by: Max Dubrinsky <[email protected]>
Register an `openshell-local` executor in the local platform config so the OpenShell backend is reachable end-to-end through the deployments API on a developer machine. AIRCORE-872 (889) Signed-off-by: Max Dubrinsky <[email protected]>
Add the `deploy-sandbox` skill (with its test manifest) that walks the create -> package -> deploy -> invoke flow for a policy-governed OpenShell sandbox, and a self-contained getting-started notebook under examples/openshell. The demo routes the agent's model traffic through gateway-managed `inference.local`, so egress governance holds with zero sandbox egress rules and no docker-specific host/proxy hacks. AIRCORE-872 Signed-off-by: Max Dubrinsky <[email protected]>
maxdubrinsky
force-pushed
the
aircore-872-openshell-deployment-target/md
branch
from
July 23, 2026 22:36
04b9b31 to
0f88d5f
Compare
openshell is a platform-restricted wheel present only in the plugin dev group and its [openshell] extra, so CI's root-level uv run never installs it (unlike docker/kubernetes, which are main deps of core packages). Five CI checks failed on its absence. Handle it gracefully instead of requiring it: - add MissingBackendDependencyError; the executor registry skips a missing-dep executor with a warning rather than crashing the whole deployments service at startup (the default local.yaml now registers an opt-in openshell executor, which broke e2e service boot). - importorskip / skipif the openshell backend tests so they skip where the extra is not installed and still run where it is. - mark the optional openshell imports with ty: ignore[unresolved-import]. - reformat the demo notebook (ruff). Add registry tests for the skip path and for a missing-dep default_executor still failing fast. Signed-off-by: Max Dubrinsky <[email protected]>
The graceful-degradation change means the shared unit-test job skips the OpenShell backend tests (the platform-restricted openshell extra is not in the default sync). Add an isolated, path-filtered job that installs the extra and runs the backend tests for real, so the backend is not left to local-only testing. Kept separate so a wheel-install failure fails only this small job, not the whole unit suite (mirrors the nemo-guardrails extra job). Signed-off-by: Max Dubrinsky <[email protected]>
The PR added a second top-level deployments: key, so YAML last-wins dropped the local-docker executor and default_executor from the deployments registry while models.controller still referenced local-docker. Merge into one block: both executors plus default_executor: local-docker, sandbox stays opt-in per deployment. Signed-off-by: Max Dubrinsky <[email protected]>
openshell is a platform-restricted manylinux_2_39 wheel with no sdist; keeping it in the dev group made uv sync --all-packages (bootstrap) hard-fail on glibc < 2.39 / older macOS, since the lock marker gates arch/OS but not glibc. Rely on the [openshell] extra; the dedicated CI job installs it to cover the backend. Signed-off-by: Max Dubrinsky <[email protected]>
… read_status create_deployment now resolves DeploymentConfig secrets (matching docker/k8s) and fails with named vars on unresolved secretRef/valueFrom instead of silently dropping them. Provisioning (wait for READY, launch the serve command, expose ports) moves out of the blocking create path into a read_status state machine, so a slow sandbox no longer stalls the serial reconcile loop. The serve launcher writes a marker file so read_status (stateless across polls) does not relaunch it. A non-zero launcher exit fails the deployment, and any provisioning failure best-effort deletes the sandbox so it does not leak behind a terminal FAILED deployment. Also drops house-style em-dashes from the module docstring/comments. Signed-off-by: Max Dubrinsky <[email protected]>
A loaded/override policy YAML that omitted enforcement ran egress rules in audit (observe-but-allow) mode, and one omitting process/landlock ran as the image-default user with no filesystem confinement. Default network enforcement to enforce and normalize loaded policies to inject the sandbox process block and a landlock block, matching the generated path. Add a validated landlock_compatibility knob (default best_effort to keep the local-dev docker path working; opt into hard_requirement to fail closed on kernels without Landlock). Nits: fix the tls-passthrough comment, align the gateway_endpoint default to the documented :17670, drop em-dashes. Signed-off-by: Max Dubrinsky <[email protected]>
…cal design The skill documented the old direct-egress model (platform_egress present, agent base_url at host.docker.internal:8080), but the repo ships gateway-managed inference.local with platform_egress: null, so following the skill literally produced a blocked-egress 502. Rewrite onto the shipped design: add the one-time provider create / inference set wiring and the mandatory generate-certs and telemetry-trim preflight steps, keep direct-egress as an explicit alternate branch, and fix the version-pin and unicode nits. Signed-off-by: Max Dubrinsky <[email protected]>
An unrelated edit renumbered the 'Verify the wire' step from 5. to 1., restarting the ordered list mid-sequence. Restore 5. in both skill copies. Signed-off-by: Max Dubrinsky <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an OpenShell deployment backend to the
nemo-deploymentsplugin, so an agent deployed through the standard deployments API runs inside an OpenShell sandbox. The backend generates a Landlock filesystem/process policy and a default-deny egress rule that only permits traffic back to the platform Inference Gateway, so the agent's model calls go through the platform and other egress is blocked at the sandbox boundary.The create/package/deploy/invoke flow works end to end. The demo routes model traffic through gateway-managed
inference.local, which drops the docker-specific host and proxy workarounds the earlier version needed. Getting-started notebook:plugins/nemo-deployments/examples/openshell/DEMO.ipynb.What's here (AIRCORE-872)
Six commits, ordered so each builds on the last:
openshellPyPI package as the plugin's optional[openshell]extra and dev group. No vendored gRPC stubs and no wheel pin. Pinned>=0.0.83, with the exact version inuv.lock.OpenShellDeploymentBackendimplements theDeploymentBackendABC (create, read_status, delete, expose) over the OpenShell gRPC gateway and applies the policy and serve workdir. Covered by mocked unit tests, an executor-config test, and a live-gateway integration test.--sandbox-runtime openshellprofile fornemo agents package, registered through thenemo.sandbox_profilesentry point.openshell-localexecutor tolocal.yamlfor the local end-to-end path.deploy-sandboxskill plus the getting-started notebook.Status
Still a draft, pending review.
openshellis a normal PyPI dependency (>=0.0.83, resolved to0.0.90in the lock), so CI can resolve it anduv syncpicks it up like any other dependency. Local checks pass: openshell unit tests (35), agents container tests (102), ruff check and format.Linear: AIRCORE-872