Skip to content

fix(sandbox): acknowledge initial policy load and expose SDK labels #2159

Description

@KyleZheng1284

Summary

Two OpenShell lifecycle/API gaps block the policy-bound per-job sandbox integration in NVIDIA-AI-Blueprints/aiq#298 for AI-Q 2.2:

  1. A newly created sandbox can reach Ready and expose an effective policy while the same revision remains Pending indefinitely.
  2. The public Python SDK cannot send gateway-object labels or list sandboxes by label selector, although the protobuf supports both.

AI-Q intentionally fails closed instead of exposing execution without authoritative policy attestation.

Confirmed policy-state behavior

Reproduced on macOS/Apple Silicon with Docker Desktop:

OpenShell Creation path Result
0.0.72 clean gateway diagnostic Ready; effective policy present; matching revision remains Pending; current_policy_version=0
0.0.77 CLI directly, without AI-Q Ready; revision 2 is Effective via policy get; revision 2 remains Pending via policy list; revision 1 is Superseded

The state remained stable rather than transitioning to LOADED. The policy itself was successfully constructed and applied. landlock.compatibility: best_effort is therefore not an attestation bypass or explanation; it controls filesystem-enforcement compatibility.

Linux has not yet been reproduced. The observed behavior is confirmed on the macOS/Docker Desktop path; source inspection suggests shared lifecycle logic, but a Linux run is required to establish platform scope.

Minimal reproduction

  1. Create a sandbox with an explicit policy.
  2. Wait until the sandbox reaches Ready.
  3. Compare policy get <sandbox> -o json, policy list <sandbox>, and the sandbox's current_policy_version.
  4. Observe an effective positive revision while that same revision remains Pending.
  5. Delete the sandbox and verify it is absent.

Expected contract

After initial policy construction:

  • report the exact sandbox-scoped revision as LOADED;
  • report FAILED with a load error when construction fails;
  • never leave a successfully applied initial revision permanently Pending;
  • continue reporting later hot-reload revisions normally.

Suspected source path

Inspection of v0.0.72 and v0.0.74 found:

  • load_policy() constructs the initial OpaEngine;
  • the first run_policy_poll_loop() iteration records config_revision and policy_hash;
  • ReportPolicyStatus(LOADED) is sent only from the later policy_changed branch;
  • an unchanged initial hash never enters that branch.

The same runtime symptom is present in 0.0.77; its exact source path should be confirmed against that tag.

Python SDK label/selector gap

CreateSandboxRequest supports request-level labels and ListSandboxes supports label_selector, but the public Python lifecycle API does not expose them:

  • SandboxClient.create(), create_session(), and Sandbox(...) cannot forward gateway labels;
  • SandboxClient.list() cannot forward a selector;
  • SandboxRef does not retain gateway metadata labels.

Template labels reach Docker/runtime resources, but gateway selectors inspect gateway-object metadata. Consequently, a Python-created AI-Q sandbox is not returned by:

openshell sandbox list --selector aiq=deep-research

Proposed fix

Initial policy acknowledgement

  • Preserve the fetched sandbox policy version/source through initial construction.
  • Report initial success or failure exactly once.
  • Track the acknowledged version so later polling does not duplicate it.
  • Preserve existing hot-reload behavior.

Python SDK

Add optional, source-compatible parameters:

  • name and labels for creation/session/Sandbox;
  • label_selector for listing;
  • immutable gateway labels on SandboxRef.

The lifecycle and SDK fixes may land separately, but AI-Q requires both in a tagged release.

Acceptance criteria

  • Initial success and failure acknowledgement tests.
  • Later policy-revision/hot-reload regression tests.
  • Python request-label and selector-forwarding tests.
  • Docker E2E: create → Ready → LOADED → selector membership → execute → delete.
  • Direct lookup and selector both confirm deletion.
  • Tagged release with compatible CLI, Python SDK, and gateway versions.
  • AI-Q macOS demo validation with explicit best_effort.
  • AI-Q Linux production validation with hard_requirement.

Downstream impact

This issue blocks AI-Q #298. It blocks only the OpenShell-specific live acceptance for stacked artifact-lifecycle PR AI-Q #305; #305's provider-independent artifact-storage implementation can be restacked onto develop and proceed separately. AI-Q will not treat Pending as success, weaken attestation, or pin an unreleased fork.

A focused implementation PR can be prepared after maintainer triage and the repository's human state:agent-ready gate.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions