Repository navigation
Description
User Story
I use OpenShell to run native macOS tools through a compute driver and an isolation backend. I need each sandbox to use the policy the gateway approved. I also need to understand what the selected backend supports and get a useful error before a workload or service forward appears ready.
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
Make the gateway's admitted decision authoritative throughout the sandbox lifecycle. A backend advertises the guarantees it actually provides; OpenShell validates the requested behavior before side effects and carries the admitted policy into each launch. CLI, SDK, gateway and supervisor must agree on the accepted configuration and failure 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 admitted policy for that launch generation. Retry and recovery retain 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 admitted service target. Invalid target syntax fails before a local listener appears ready; the gateway also checks the live route.
- Stop a live sandbox, narrow its static policy and start again with the new admitted revision. 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.
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[/+]