Add workspace network policy and published ports

Replace the workspace-level boolean network toggle with explicit network policies and attach localhost TCP publication to workspace services.

Persist network_policy in workspace records, validate --publish requests, and run host-side proxy helpers that follow the service lifecycle so published ports are cleaned up on failure, stop, reset, and delete.

Update the CLI, SDK, MCP contract, docs, roadmap, and examples for the new policy model, add coverage for the proxy and manager edge cases, and validate with uv lock, UV_CACHE_DIR=.uv-cache make check, UV_CACHE_DIR=.uv-cache make dist-check, and a real guest-backed published-port probe smoke.
This commit is contained in:
Thales Maciel 2026-03-12 18:12:57 -03:00
parent fc72fcd3a1
commit c82f4629b2
21 changed files with 1944 additions and 49 deletions

View file

@ -83,7 +83,7 @@ uvx --from pyro-mcp pyro env list
Expected output:
```bash
Catalog version: 2.9.0
Catalog version: 2.10.0
debian:12 [installed|not installed] Debian 12 environment with Git preinstalled for common agent workflows.
debian:12-base [installed|not installed] Minimal Debian 12 environment for shell and core Unix tooling.
debian:12-build [installed|not installed] Debian 12 environment with Git and common build tools preinstalled.
@ -176,12 +176,14 @@ After the CLI path works, you can move on to:
- persistent workspaces: `pyro workspace create debian:12 --seed-path ./repo`
- live workspace updates: `pyro workspace sync push WORKSPACE_ID ./changes`
- guest networking policy: `pyro workspace create debian:12 --network-policy egress`
- workspace secrets: `pyro workspace create debian:12 --secret API_TOKEN=expected --secret-file PIP_TOKEN=./token.txt`
- baseline diff: `pyro workspace diff WORKSPACE_ID`
- snapshots and reset: `pyro workspace snapshot create WORKSPACE_ID checkpoint` and `pyro workspace reset WORKSPACE_ID --snapshot checkpoint`
- host export: `pyro workspace export WORKSPACE_ID note.txt --output ./note.txt`
- interactive shells: `pyro workspace shell open WORKSPACE_ID`
- long-running services: `pyro workspace service start WORKSPACE_ID app --ready-file .ready -- sh -lc 'touch .ready && while true; do sleep 60; done'`
- localhost-published ports: `pyro workspace create debian:12 --network-policy egress+published-ports` and `pyro workspace service start WORKSPACE_ID app --ready-http http://127.0.0.1:8080/ --publish 18080:8080 -- ./start-app`
- MCP: `pyro mcp serve`
- Python SDK: `from pyro_mcp import Pyro`
- Demos: `pyro demo` or `pyro demo --network`
@ -192,7 +194,9 @@ Use `pyro workspace ...` when you need repeated commands in one sandbox instead
```bash
pyro workspace create debian:12 --seed-path ./repo
pyro workspace create debian:12 --network-policy egress
pyro workspace create debian:12 --seed-path ./repo --secret API_TOKEN=expected
pyro workspace create debian:12 --network-policy egress+published-ports
pyro workspace sync push WORKSPACE_ID ./changes --dest src
pyro workspace exec WORKSPACE_ID -- cat src/note.txt
pyro workspace exec WORKSPACE_ID --secret-env API_TOKEN -- sh -lc 'test "$API_TOKEN" = "expected"'
@ -207,6 +211,7 @@ pyro workspace shell read WORKSPACE_ID SHELL_ID
pyro workspace shell close WORKSPACE_ID SHELL_ID
pyro workspace service start WORKSPACE_ID web --secret-env API_TOKEN --ready-file .web-ready -- sh -lc 'touch .web-ready && while true; do sleep 60; done'
pyro workspace service start WORKSPACE_ID worker --ready-file .worker-ready -- sh -lc 'touch .worker-ready && while true; do sleep 60; done'
pyro workspace service start WORKSPACE_ID app --ready-http http://127.0.0.1:8080/ --publish 18080:8080 -- ./start-app
pyro workspace service list WORKSPACE_ID
pyro workspace service status WORKSPACE_ID web
pyro workspace service logs WORKSPACE_ID web --tail-lines 50
@ -220,7 +225,7 @@ Workspace commands default to the persistent `/workspace` directory inside the g
the identifier programmatically, use `--json` and read the `workspace_id` field. Use `--seed-path`
when the workspace should start from a host directory or a local `.tar` / `.tar.gz` / `.tgz`
archive. Use `pyro workspace sync push` for later host-side changes to a started workspace. Sync
is non-atomic in `2.9.0`; if it fails partway through, prefer `pyro workspace reset` to recover
is non-atomic in `2.10.0`; if it fails partway through, prefer `pyro workspace reset` to recover
from `baseline` or one named snapshot. Use `pyro workspace diff` to compare the current workspace
tree to its immutable create-time baseline, `pyro workspace snapshot *` to capture named
checkpoints, and `pyro workspace export` to copy one changed file or directory back to the host. Use
@ -228,10 +233,13 @@ checkpoints, and `pyro workspace export` to copy one changed file or directory b
interactive PTY that survives across separate calls. Use `pyro workspace service *` when the
workspace needs long-running background processes with typed readiness probes. Service metadata and
logs stay outside `/workspace`, so the service runtime itself does not show up in workspace diff or
export results. Use `--secret` and `--secret-file` at workspace creation when the sandbox needs
private tokens or config, and `--secret-env SECRET_NAME[=ENV_VAR]` when one exec, shell, or
service call needs that secret as an environment variable. Persisted secret files are available in
the guest at `/run/pyro-secrets/<name>`.
export results. Use `--network-policy egress` when the workspace needs outbound guest networking,
and `--network-policy egress+published-ports` plus `workspace service start --publish` when one
service must be reachable from the host on `127.0.0.1`. Use `--secret` and `--secret-file` at
workspace creation when the sandbox needs private tokens or config, and
`--secret-env SECRET_NAME[=ENV_VAR]` when one exec, shell, or service call needs that secret as an
environment variable. Persisted secret files are available in the guest at
`/run/pyro-secrets/<name>`.
## Contributor Clone