Repository navigation
Description
User Story
I run workloads in OpenShell sandboxes. I need each sandbox to use the policy the gateway approved, clearly show what its runtime supports, and explain startup or forwarding failures.
This issue covers shared behavior across compute drivers and isolation backends, including Docker, Podman, Kubernetes, VM, and external backends. Native macOS tools are one motivating example.
Problem Statement
OpenShell does not consistently carry the approved policy and backend capabilities through sandbox creation, startup, policy updates and restart.
For example, after I stop a sandbox and narrow its policy, a restart can pass the new policy to the supervisor while the retained compute resource still starts with the original policy. The backend can then refuse to attach, and configuration and status can identify different effective policies.
This parent issue tracks the coordinated fixes for that workflow and related gaps:
- Backend filesystem requirements can be added after the gateway has already approved and hashed the policy.
- Callers cannot reliably check allowed service ports or distinguish hard CPU/memory limits, scheduler reservations and periodically checked resource budgets before starting an operation.
- Valid integer driver settings can fail decoding after protobuf conversion.
- Backend startup and workload entrypoint failures can appear as generic supervisor exits.
- A TCP forward can appear ready before its target is rejected.
- Late runtime updates can move a stopped sandbox back to provisioning, and a live filesystem policy change can be reported as loaded before it is enforced.
- A source archive built inside another Git checkout can report that unrelated checkout's version.
Impact / Why This Matters
Users need the policy OpenShell approves to match the policy that governs the next launch. They should be able to stop a sandbox, update its policy and restart it without recreating the sandbox or falling back to older permissions. Frozen sandboxes must keep their original policy and reject changes.
Unsupported requests should fail before provisioning or opening a listener. Startup failures should explain the stage and failure category safely, and status should describe the policy and state actually in effect.
Backend authors also need shared lifecycle and validation behavior they can reuse. Operators need accurate resource guarantees and build versions to compare backends and diagnose deployments.
Proposed Design
Use the gateway-approved policy throughout the sandbox lifecycle. Each backend reports the guarantees it provides. OpenShell checks requests before creating resources or opening listeners, then uses the approved policy for each launch. The CLI, SDKs, gateway, and supervisor must agree on the accepted configuration and the reported outcome.
Expected user workflow
- Inspect the selected backend's network and resource guarantees. OpenShell identifies shared host networking, hard limits and sampled budgets explicitly.
- Create a sandbox with supported configuration. The gateway includes the backend's filesystem prerequisites in the effective policy and rejects unsupported ports or guarantees before provisioning.
- Start the workload with the approved policy saved for that launch generation. Retries and recovery reuse the same input. Supervisor attachment and confirmation must succeed before workload execution.
- Inspect a useful startup failure category if construction, attachment or confirmation fails. A policy refusal remains distinguishable from configuration or infrastructure failure.
- Forward an approved service target. Invalid target syntax fails before a local listener appears ready; the gateway also checks the live route.
- Stop a sandbox with a mutable policy, narrow its static permissions, and start again with the newly approved revision when the driver supports this workflow. For a frozen sandbox, the update is rejected and restart retains the frozen snapshot.
For example, if a backend admits service port 8080, a request for 9090 fails before provisioning or listener creation. If it offers only sampled RSS enforcement, a hard-memory-limit request fails; a caller may explicitly choose the advertised sampled budget. Neither workflow silently weakens the original request.
Coordination with existing OpenShell work
- Build resource enforcement on the typed CPU/memory model in feat(api)!: model CPU and memory as typed compute resource requirements #3012. Typed requests and limits alone do not establish enforcement scope or sampled-budget support.
- Preserve frozen-policy precedence from feat(policy): freeze a sandbox's effective policy for its lifetime #4735 when adding launch-policy input. Backend prerequisites and endpoint-status identity must describe the same admitted snapshot.
- Build bounded startup diagnostics on the Attach-refusal behavior in fix(supervisor): report isolation backend Attach refusals to the gateway #4791, keeping the scopes independently reviewable.
- Coordinate service admission with Sandbox Service Exposure #4310 and RFC 0017. The RFC PR #4267 supplies the design; service exposure and CLI TCP forwarding retain their distinct authentication and routing boundaries.
- Coordinate the retained Stop/watch workflow with bug(kubernetes): stopped sandbox regresses to Provisioning after stop completes #5195 and PR fix(kubernetes): keep a late stop snapshot from reviving a stopped sandbox #5196. The Kubernetes observation correction and shared gateway lifecycle guard address different layers; verify the combined result before treating the dependency as resolved.
- Keep live-policy status truthful under UpdateConfig that adds filesystem paths on a live sandbox is reported LOADED but is not enforced #5041. Backend prerequisites in Include backend filesystem requirements before approving sandbox policy #5108 and next-generation policy input in Use the approved policy for each sandbox start, retry, and recovery #5109 do not by themselves prove a filesystem change is active in a running workload. Reject unsupported live changes or report their actual applied state.
- Include workload entrypoint startup reporting from bug: surface supervisor startup failures to sandbox commands #3519. This complements backend Build/Attach/Confirm categories in Report which backend startup stage failed without exposing private logs #5107 and must preserve ordinary workload exit semantics.
- Verify the combined protocol and client behavior after the scoped changes are integrated. Component PRs resolve their child issues; this parent tracks the complete OpenShell behavior and its integration checks.
Implementation links
Linked PRs track implementation. A linked PR does not mark its requirement complete; the acceptance criteria below still apply. #5237 remains a draft while its overlap with #4983 is coordinated.
| Work | Issue | PR |
|---|---|---|
| Proxy sockets and per-connection executable checks | #4804 | #4806 |
| Attach refusal reporting | #4739 | #4791 |
| Integer driver settings | #5106 | #5117 |
| Backend startup diagnostics | #5107 | #5118 |
| Backend filesystem requirements | #5108 | #5120 |
| Policy for each start, retry, and recovery | #5109 | #5121 |
| Allowed service ports | #5110 | #5116 |
| Hard limits and sampled resource budgets | #5111 | #5119 |
| TCP target validation | #5112 | #5115 |
| Build version accuracy | #4186 | #3844 |
| Stopped state and late driver updates | #5195 | #5196, #5204 |
| Truthful live filesystem policy status | #5041 | #5234 |
| Runtime and workload startup errors | #3519 | #5235 |
| Workload platform and fixed restrictions | #5201 | #5236 |
| Shared restart and background-check race | #4932 | #5237 (draft; overlaps #4983) |
| Docker restart and background-check race | #4981 | #4983 |
Acceptance Criteria
- Prebound proxy listeners work with executable-specific policy decisions made for each connection.
- Actual Attach refusals reach gateway status. Build, Attach and Confirm failures have bounded, authenticated, generation-fenced categories; public status excludes raw privileged diagnostics and reporting failure preserves the original startup error.
- Exactly represented integer driver options survive protobuf conversion, including nested objects and lists. Non-finite input and fractional values for integer fields are rejected rather than silently changed.
- Backend filesystem prerequisites participate in admission before effective-policy hashing. Explicit empty baselines and read-only grants are respected, and delivered configuration and endpoint status agree on policy identity before and after Loaded acknowledgement.
- Live stop/update/start uses the updated admitted policy. Same-generation retries and gateway recovery reuse the committed launch input, a narrowing never falls back to older grants, and frozen-policy starts retain the original snapshot while mutation is rejected.
- Create-time and live service routes enforce admitted target ports and expose their network scope. Unadmitted targets fail before provisioning or listener creation, including through SDK and direct gateway requests.
- Resource inspection distinguishes hard limits, reservations and sampled enforcement with their scope. A sampled watchdog never satisfies a hard-limit request; unsupported or changed guarantees and missing gateway acknowledgement prevent the corresponding mutation.
- CLI and SDK TCP forwarding reject invalid hosts and ports before lookup or binding, normalize supported loopback forms consistently, and retain authoritative gateway checks.
- Source archives report the package version even when nested in another checkout. Regular and linked worktree checkouts retain correct source-owned Git metadata and relevant rebuild invalidation.
- Each work item is linked to its scoped OpenShell issue and implementation or reviewed resolution. Combined lifecycle, protocol and affected-client checks pass, with regression coverage for existing compute backends including the VM backend. Documented capabilities match the behavior observed by users.
- A completed Stop remains
Stoppeduntil a new Start or delete is accepted. Late bootstrap/watch observations cannot revive it, and a genuine accepted Start still recovers a stale stopped view. Verify the shared gateway behavior together with the affected driver's observation correction (bug(kubernetes): stopped sandbox regresses to Provisioning after stop completes #5195). - A live filesystem policy change is either applied and reported accurately or rejected with a clear explanation. A
LOADEDrevision never claims filesystem permissions the running workload has not received; stop/update/start and frozen-policy behavior remain consistent (UpdateConfig that adds filesystem paths on a live sandbox is reported LOADED but is not enforced #5041). - If the workload entrypoint cannot start before readiness, create/run reports a concise, sanitized launch-stage failure. Ordinary workload exits retain their existing meaning, and backend startup classification remains intact (bug: surface supervisor startup failures to sandbox commands #3519).
Alternatives Considered
Recreate a sandbox whenever static policy changes. This avoids reusing stale launch inputs but discards the retained-resource workflow and does not define stable policy identity for retries or recovery.
Put backend-specific options in untyped driver configuration. Such options remain useful for implementation details, but cannot tell every OpenShell caller which policy, ingress or resource guarantees the gateway actually admitted. A client-only check also leaves direct gateway callers and existing service connections unchecked.
Reuse applicable compute-driver, isolation-backend, middleware, interceptor and provider extension points. Those remain the preferred integration mechanisms. Request-processing extensions do not by themselves supply backend-owned filesystem prerequisites, atomically bind policy to a launch generation or describe runtime enforcement guarantees; the shared OpenShell lifecycle must carry and validate that information.
Checklist
- I've reviewed existing issues and the published docs
- This is a design proposal, not a "please build this" request
Activity
[-]feat: make compute backend admission and lifecycle guarantees consistent[/-][+]Make compute backend admission and lifecycle guarantees consistent[/+]fix(compute): preserve policy CAS and complete SDK checks
[-]Make compute backend admission and lifecycle guarantees consistent[/-][+]Make sandbox policies, restarts, and backend limits consistent[/+][-]Make sandbox policies, restarts, and backend limits consistent[/-][+]Keep sandbox policies, restarts, and limits consistent across backends[/+]