Skip to content

Needs a live run: OpenShell v0.1.2 → v0.1.5, interceptor stubs regenerated - #8

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
openshell/v0.1.5
Open

github-actions[bot] wants to merge 1 commit into
mainfrom
openshell/v0.1.5

Conversation

@github-actions

Copy link
Copy Markdown

Needs a live run before merging. Merging means upgrading the gateway to v0.1.5 first.

Proposed by the openshell-release workflow. It regenerated interceptor/proto, interceptor/_gen and the hash locks from OpenShell v0.1.5. The main suite FAILS, and the interceptor suite passes. Neither suite runs OpenShell.

Review the new proto fields on the mount path (CreateSandboxRequest, SandboxSpec, SandboxTemplate, and the Docker driver's mount schema): the rule's allowlists (R2, R3, R6) refuse a field they do not know until it is reviewed.

Changes under interceptor/

 interceptor/_gen/datamodel_pb2.py                |   10 +-
 interceptor/_gen/datamodel_pb2_grpc.py           |   10 +-
 interceptor/_gen/extension_pb2.py                |   10 +-
 interceptor/_gen/extension_pb2_grpc.py           |   10 +-
 interceptor/_gen/gateway_interceptor_pb2.py      |   10 +-
 interceptor/_gen/gateway_interceptor_pb2_grpc.py |   10 +-
 interceptor/_gen/openshell_pb2.py                | 1098 ++++++++++++----------
 interceptor/_gen/openshell_pb2_grpc.py           |  116 ++-
 interceptor/_gen/options_pb2.py                  |   10 +-
 interceptor/_gen/options_pb2_grpc.py             |   10 +-
 interceptor/_gen/sandbox_pb2.py                  |  124 +--
 interceptor/_gen/sandbox_pb2_grpc.py             |   10 +-
 interceptor/proto/SOURCE                         |   12 +-
 interceptor/proto/gateway_interceptor.proto      |    2 +
 interceptor/proto/openshell.proto                |  414 +++++++-
 interceptor/proto/options.proto                  |    3 +-
 interceptor/proto/sandbox.proto                  |   36 +-
 17 files changed, 1238 insertions(+), 657 deletions(-)

The protos' diff

diff --git a/interceptor/proto/gateway_interceptor.proto b/interceptor/proto/gateway_interceptor.proto
index 1bd12d9..cf55619 100644
--- a/interceptor/proto/gateway_interceptor.proto
+++ b/interceptor/proto/gateway_interceptor.proto
@@ -111,6 +111,8 @@ message InterceptorManifest {
   // post-authentication consistency check.
   string expected_audience = 5;
   // Gateway-interceptor protocol metadata. Required for negotiation.
+  // Declare protocol 1.0 and list "openshell.gateway-interceptor.contract" in
+  // supported_capabilities.
   openshell.extension.v1.PeerMetadata extension = 6;
 }
 
diff --git a/interceptor/proto/openshell.proto b/interceptor/proto/openshell.proto
index a836e16..44d5ed8 100644
--- a/interceptor/proto/openshell.proto
+++ b/interceptor/proto/openshell.proto
@@ -296,6 +296,13 @@ service OpenShell {
     };
   }
 
+  // Export selected usable runtime credentials. Only directly authenticated
+  // mTLS operators may call this method; refresh material is never returned.
+  rpc GetProviderCredentials(GetProviderCredentialsRequest)
+      returns (GetProviderCredentialsResponse) {
+    option (openshell.options.v1.authorization) = { auth_mode: "operator" };
+  }
+
   // List providers.
   rpc ListProviders(ListProvidersRequest) returns (ListProvidersResponse) {
     option (openshell.options.v1.authorization) = {
@@ -423,7 +430,9 @@ service OpenShell {
     };
   }
 
-  // Get sandbox settings by id (called by sandbox entrypoint and poll loop).
+  // Get sandbox settings by id (called by users, and by supervisors at startup
+  // and in their poll loop). A supervisor whose session pushes configuration
+  // receives later updates over ConnectSupervisor and stops polling.
   rpc GetSandboxConfig(openshell.sandbox.v1.GetSandboxConfigRequest)
       returns (openshell.sandbox.v1.GetSandboxConfigResponse) {
     option (openshell.options.v1.authorization) = {
@@ -509,7 +518,9 @@ service OpenShell {
     option (openshell.options.v1.authorization) = { auth_mode: "sandbox" };
   }
 
-  // Get provider environment for a sandbox (called by sandbox supervisor at startup).
+  // Get provider environment for a sandbox (called by the sandbox supervisor at
+  // startup and by its poll loop). Polling projection of the provider
+  // environment delivered over ConnectSupervisor; removed with the polling RPCs.
   rpc GetSandboxProviderEnvironment(GetSandboxProviderEnvironmentRequest)
       returns (GetSandboxProviderEnvironmentResponse) {
     option (openshell.options.v1.authorization) = {
@@ -546,9 +557,11 @@ service OpenShell {
   //
   // The supervisor opens this stream at startup and keeps it alive for the
   // sandbox lifetime. The gateway uses it to coordinate relay channels for
-  // SSH connect, ExecSandbox, and targetable sandbox services. Raw service
-  // bytes flow over RelayStream calls (separate HTTP/2 streams on the same
-  // connection), not over this stream.
+  // SSH connect, ExecSandbox, targetable sandbox services, and configuration
+  // delivery. Supervisors advertise optional stream features in
+  // SupervisorHello, and the gateway sends only payloads the supervisor
+  // advertises. Raw service bytes flow over RelayStream calls (separate HTTP/2
+  // streams on the same connection), not over this stream.
   rpc ConnectSupervisor(stream SupervisorMessage) returns (stream GatewayMessage) {
     option (openshell.options.v1.authorization) = {
       auth_mode: "sandbox"
@@ -622,6 +635,15 @@ service OpenShell {
     };
   }
 
+  // Best-effort notification to the replica that owns a supervisor session.
+  // The receiver rebuilds snapshots from authoritative state.
+  rpc PeerNotifyConfigUpdate(PeerNotifyConfigUpdateRequest)
+      returns (PeerNotifyConfigUpdateResponse) {
+    option (openshell.options.v1.authorization) = {
+      auth_mode: "peer"
+    };
+  }
+
   // Watch a sandbox and stream updates.
   //
   // This stream can include:
@@ -1006,6 +1028,10 @@ message Sandbox {
   SandboxSpec spec = 2;
   // Latest user-facing observed status derived by the gateway.
   SandboxStatus status = 3;
+  // Read-only SSH host identity in OpenSSH SHA256:<base64> form. Stable for
+  // this sandbox's lifetime, including runtime restarts. Empty on legacy
+  // runtimes that do not provide a gateway-managed SSH identity.
+  string host_key_fingerprint = 6;
   // Read-only provenance for sandboxes created from a reusable workload template.
   SandboxWorkloadTemplateProvenance created_from_workload_template = 20;
 
@@ -1045,6 +1071,9 @@ message SandboxSpec {
   // Gateway-owned attachment identity, changed atomically with the provider set.
   // Equality only: detach and reattach must not revive an older receipt.
   string provider_attachment_epoch = 14;
+  // Gateway-owned policy for replacing the sandbox runtime after the canonical
+  // main process exits. Unspecified is normalized to Never before persistence.
+  SandboxRestartPolicy restart_policy = 15;
 }
 
 message ResourceRequirements {
@@ -1170,9 +1199,8 @@ message SandboxStatus {
   // Supervisor instance currently associated with the canonical main process.
   // The gateway uses this to reject stale exit reports after a restart.
   string main_process_instance_id = 8;
-  // Normalized main process result. Signal exits use 128 + signal number.
-  // Presence indicates that the canonical main process exited. Exit code 0
-  // produces Completed; nonzero and signal-normalized exits produce Error.
+  // Most recent normalized main process result. Signal exits use 128 + signal number.
+  // Cleared when a replacement main process becomes ready.
   optional int32 exit_code = 9;
   // Last accepted network result for each configured tool server endpoint.
   // Currently populated for MCP-over-HTTP endpoints. These passive results
@@ -1182,8 +1210,18 @@ message SandboxStatus {
   SandboxConfigurationAdmission configuration_admission = 11;
   // Durable first-acceptance marker. Absent on legacy records; never reset by restart.
   optional bool configuration_activated = 12;
-  // Gateway-owned repair window. Retained after timeout for inspection and retry.
+  // Gateway-owned provisioning deadlines, retained after timeout for inspection and retry.
   SandboxProvisioning provisioning = 13;
+  // Consecutive policy-driven restart number in the current crash loop.
+  uint32 restart_count = 14;
+  // Deadline for the next restart attempt or recovery check.
+  google.protobuf.Timestamp next_restart_time = 15;
+  // Time when the current main process became ready.
+  google.protobuf.Timestamp main_process_started_time = 16;
+  // Latest refused token grant across all outbound HTTP protocols, including
+  // failures before a configured endpoint or credential could be selected.
+  // Matching grant success or a policy, provider, or supervisor reset clears it.
+  TokenGrantFailureObservation last_token_grant_failure = 17;
 }
 
 // User-facing sandbox condition derived from platform or gateway observations.
@@ -1218,6 +1256,8 @@ enum SandboxPhase {
   SANDBOX_PHASE_STARTING = 8;
   // The canonical main process exited successfully and its result is final.
   SANDBOX_PHASE_COMPLETED = 9;
+  reserved 10;
+  reserved "SANDBOX_PHASE_RESTARTING";
 }
 
 // Public platform event exposed on the sandbox watch stream.
@@ -1247,7 +1287,8 @@ message CreateSandboxRequest {
   string name = 2;
   // Optional labels for the sandbox (key-value metadata).
   map<string, string> labels = 3;
-  // Optional annotations for the sandbox (non-selector metadata).
+  // Optional annotations for the sandbox (non-selector metadata). Keys under
+  // the `internal.openshell.ai/` prefix are reserved for the gateway.
   map<string, string> annotations = 4;
   // One-shot launch hint indicating that the creating client will attach to
   // the canonical main process. The supervisor keeps the terminal transport
@@ -1743,7 +1784,8 @@ message CreateSshSessionResponse {
   // Gateway scheme. Must be exactly "http" or "https".
   string gateway_scheme = 5;
 
-  // Optional host key fingerprint. If non-empty, [A-Za-z0-9:+/=-] only.
+  // Expected sandbox SSH host identity in OpenSSH SHA256:<base64> form.
+  // Stable for the sandbox's lifetime. Empty only for legacy runtimes.
   string host_key_fingerprint = 7;
 
   // Absolute expiry. Absence means no expiry.
@@ -1764,6 +1806,8 @@ message ExposeServiceRequest {
   // Optional nonzero UUID for durable at-most-once admission. Successful results
   // can be replayed for 24 hours; see the API errors and retries reference.
   string request_id = 6;
+  // Application authorization behavior. Omission resolves to STRIP.
+  ServiceAuthorizationMode authorization_mode = 7;
 }
 
 // Request to fetch an exposed sandbox service endpoint.
@@ -1830,6 +1874,8 @@ message ServiceEndpoint {
   uint32 target_port = 5;
   // Whether browser-facing service routing is enabled for this endpoint.
   bool domain = 6;
+  // Effective application authorization behavior for ingress requests.
+  ServiceAuthorizationMode authorization_mode = 7;
 }
 
 // Response containing a service endpoint and, when available, its local URL.
@@ -2117,6 +2163,31 @@ message GetProviderRequest {
   string name = 1;
 }
 
+// Retrieve selected runtime credentials from one provider in one workspace.
+// Refresh side effects can persist even when the complete request fails.
+message GetProviderCredentialsRequest {
+  // Required named workspace selection; all_workspaces is not accepted.
+  openshell.datamodel.v1.WorkspaceSelector workspace_scope = 1;
+  // Provider canonical name.
+  string name = 2;
+  // Nonempty selection of runtime environment keys (maximum 32).
+  repeated string credential_keys = 3;
+  // Omitted/zero uses a five-minute safety margin. Maximum is 24 hours.
+  google.protobuf.Duration minimum_remaining_lifetime = 4;
+}

The main suite

E           }

tests/test_repin.py:122: AssertionError
_________________ test_openshell_check_reads_the_vendored_tag __________________

    def test_openshell_check_reads_the_vendored_tag():
        seen = []
        repin.openshell_check(tags=lambda url: seen.append(url) or [])
        assert seen == [repin.OPENSHELL_URL]
>       assert repin.locks.read_source(str(repin.OPENSHELL_SOURCE))[0] == "v0.1.2"
E       AssertionError: assert 'v0.1.5' == 'v0.1.2'
E         
E         - v0.1.2
E         ?      ^
E         + v0.1.5
E         ?      ^

tests/test_repin.py:135: AssertionError
=========================== short test summary info ============================
FAILED tests/test_repin.py::test_openshell_check_reports_the_newest_release_after_the_vendored_tag - AssertionError: assert {'current': '...ag': 'v0.2.0'} == {'current': '...ag': 'v0.2.0'}
  
  Omitting 1 identical items, use -vv to show
  Differing items:
  {'current': 'v0.1.5'} != {'current': 'v0.1.2'}
  
  Full diff:
    {
  -     'current': 'v0.1.2',
  ?                      ^
  +     'current': 'v0.1.5',
  ?                      ^
        'tag': 'v0.2.0',
    }
FAILED tests/test_repin.py::test_openshell_check_reads_the_vendored_tag - AssertionError: assert 'v0.1.5' == 'v0.1.2'
  
  - v0.1.2
  ?      ^
  + v0.1.5
  ?      ^
2 failed, 1108 passed, 7 deselected in 224.01s (0:03:44)

The interceptor suite

........                                                                 [100%]
8 passed in 1.11s

@github-actions
github-actions Bot requested a review from rappdw as a code owner October 25, 2026 07:00

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants