diff --git a/crates/right-openshell/proto/UPSTREAM.md b/crates/right-openshell/proto/UPSTREAM.md index 7cb43f68..5f1571f5 100644 --- a/crates/right-openshell/proto/UPSTREAM.md +++ b/crates/right-openshell/proto/UPSTREAM.md @@ -1,3 +1,3 @@ -tag: v0.0.62 -fetched: 2026-06-13T07:00:33Z +tag: v0.0.85 +fetched: 2026-07-17T07:34:34Z upstream: https://github.com/NVIDIA/OpenShell diff --git a/crates/right-openshell/proto/openshell/datamodel.proto b/crates/right-openshell/proto/openshell/datamodel.proto index f92d7b7a..ada4716b 100644 --- a/crates/right-openshell/proto/openshell/datamodel.proto +++ b/crates/right-openshell/proto/openshell/datamodel.proto @@ -5,10 +5,13 @@ syntax = "proto3"; package openshell.datamodel.v1; +import "options.proto"; + // Kubernetes-style metadata shared by all top-level OpenShell domain objects. // -// This structure provides consistent metadata (identity, labels, timestamps, -// resource versioning) across Sandbox, Provider, SshSession, and other resources. +// This structure provides consistent metadata (identity, labels, annotations, +// timestamps, resource versioning) across Sandbox, Provider, SshSession, and +// other resources. message ObjectMeta { // Stable object ID generated by the gateway. string id = 1; @@ -26,6 +29,10 @@ message ObjectMeta { // Optimistic concurrency control version. // Incremented by the gateway on each update. Clients can use this for compare-and-swap operations. uint64 resource_version = 5; + + // Opaque key-value metadata that is not used for selectors. + // Annotation keys use the same qualified-key shape as labels, but values may be longer. + map annotations = 6; } // Provider model stored by OpenShell. @@ -35,7 +42,7 @@ message Provider { // Canonical provider type slug (for example: "claude", "gitlab"). string type = 2; // Secret values used for authentication. - map credentials = 3; + map credentials = 3 [(openshell.options.v1.secret) = true]; // Non-secret provider configuration. map config = 4; // Expiration timestamps for credential values, keyed by credential/env var diff --git a/crates/right-openshell/proto/openshell/openshell.proto b/crates/right-openshell/proto/openshell/openshell.proto index d701956d..b437613b 100644 --- a/crates/right-openshell/proto/openshell/openshell.proto +++ b/crates/right-openshell/proto/openshell/openshell.proto @@ -7,6 +7,7 @@ package openshell.v1; import "datamodel.proto"; import "google/protobuf/struct.proto"; +import "options.proto"; import "sandbox.proto"; // OpenShell service provides sandbox, provider, and runtime management capabilities. @@ -21,6 +22,9 @@ service OpenShell { // Check the health of the service. rpc Health(HealthRequest) returns (HealthResponse); + // Fetch elevated live gateway runtime metadata. + rpc GetGatewayInfo(GetGatewayInfoRequest) returns (GetGatewayInfoResponse); + // Create a new sandbox. rpc CreateSandbox(CreateSandboxRequest) returns (SandboxResponse); @@ -95,6 +99,10 @@ service OpenShell { rpc ImportProviderProfiles(ImportProviderProfilesRequest) returns (ImportProviderProfilesResponse); + // Update an existing custom provider type profile. + rpc UpdateProviderProfiles(UpdateProviderProfilesRequest) + returns (UpdateProviderProfilesResponse); + // Validate provider type profiles without registering them. rpc LintProviderProfiles(LintProviderProfilesRequest) returns (LintProviderProfilesResponse); @@ -252,7 +260,7 @@ message IssueSandboxTokenRequest {} // gateway RPC. message IssueSandboxTokenResponse { // Gateway-minted JWT bound to the calling sandbox's UUID. - string token = 1; + string token = 1 [(openshell.options.v1.secret) = true]; // Absolute expiry of the issued token, milliseconds since the epoch. 0 means // the token is non-expiring. int64 expires_at_ms = 2; @@ -267,7 +275,7 @@ message RefreshSandboxTokenRequest {} // in-memory bearer credential. message RefreshSandboxTokenResponse { // Fresh gateway-minted JWT bound to the same sandbox UUID. - string token = 1; + string token = 1 [(openshell.options.v1.secret) = true]; // Absolute expiry of the new token, milliseconds since the epoch. 0 means // the token is non-expiring. int64 expires_at_ms = 2; @@ -285,6 +293,40 @@ message HealthResponse { string version = 2; } +// Gateway info request. +message GetGatewayInfoRequest {} + +// Gateway info response. +message GetGatewayInfoResponse { + // Service status. + ServiceStatus status = 1; + + // OpenShell gateway binary version. + string gateway_version = 2; + + // Compute driver runtimes initialized by this gateway. Current gateways + // return exactly one entry. + repeated ComputeDriverInfo compute_drivers = 3; +} + +// Info for one initialized compute driver runtime. +message ComputeDriverInfo { + // Gateway-selected driver name used for routing and driver_config keys. + string name = 1; + + // Capabilities reported by the driver during gateway runtime initialization. + ComputeDriverCapabilities capabilities = 2; +} + +// Public compute driver capability snapshot. +message ComputeDriverCapabilities { + // Driver-reported human-readable name from the startup capability snapshot. + string driver_name = 1; + + // Driver-reported implementation version from the startup capability snapshot. + string driver_version = 2; +} + // Public sandbox resource exposed by the OpenShell API. // // This is the canonical gateway-owned view of a sandbox. It merges user intent @@ -317,8 +359,9 @@ message SandboxSpec { openshell.sandbox.v1.SandboxPolicy policy = 7; // Provider names to attach to this sandbox. repeated string providers = 8; - // Request NVIDIA GPU resources for this sandbox. - bool gpu = 9; + // Portable resource requirements used by the gateway for driver selection + // and by drivers for provisioning. + ResourceRequirements resource_requirements = 9; reserved 10; reserved "gpu_device"; // Field 11 was `proposal_approval_mode`. The approval mode is now a @@ -329,6 +372,18 @@ message SandboxSpec { reserved "proposal_approval_mode"; } +message ResourceRequirements { + // GPU requirements for the sandbox. Presence indicates a GPU request. + GpuResourceRequirements gpu = 1; +} + +// Public GPU resource requirements. +message GpuResourceRequirements { + // Optional number of GPUs requested. When omitted, the request is for one + // GPU using the selected driver's default assignment behavior. + optional uint32 count = 1; +} + // Public sandbox template mapped onto compute-driver template inputs. message SandboxTemplate { // Fully-qualified OCI image reference used to boot the sandbox. @@ -345,8 +400,8 @@ message SandboxTemplate { map environment = 6; // Platform-specific compute resource requirements and limits. google.protobuf.Struct resources = 7; - // Optional platform-specific volume claim templates. - google.protobuf.Struct volume_claim_templates = 9; + reserved 9; + reserved "volume_claim_templates"; // Enable Kubernetes user namespace isolation (hostUsers: false). // When true, container UID 0 maps to a non-root host UID and capabilities // become namespaced. Requires Kubernetes 1.33+ with user namespace support @@ -430,6 +485,8 @@ message CreateSandboxRequest { string name = 2; // Optional labels for the sandbox (key-value metadata). map labels = 3; + // Optional annotations for the sandbox (non-selector metadata). + map annotations = 4; } // Get sandbox request. @@ -538,7 +595,7 @@ message CreateSshSessionResponse { // Session token for the gateway tunnel. URL-safe ASCII // ([A-Za-z0-9._~+/=-]) up to 4096 bytes. No shell metacharacters or // whitespace. - string token = 2; + string token = 2 [(openshell.options.v1.secret) = true]; // Gateway host for SSH proxy connection. IPv4 address, bracketed IPv6 // address, or DNS hostname (Punycode-encoded for IDN). Alphanumeric plus @@ -632,7 +689,7 @@ message ServiceEndpointResponse { // Revoke SSH session request. message RevokeSshSessionRequest { // Session token to revoke. - string token = 1; + string token = 1 [(openshell.options.v1.secret) = true]; } // Revoke SSH session response. @@ -708,7 +765,7 @@ message TcpForwardInit { } // Optional target-specific authorization token. SSH targets use this as the // short-lived SSH session token issued by CreateSshSession. - string authorization_token = 7; + string authorization_token = 7 [(openshell.options.v1.secret) = true]; } // A single frame on the CLI-to-gateway TCP forward stream. @@ -747,7 +804,7 @@ message SshSession { string sandbox_id = 2; // Session token. - string token = 3; + string token = 3 [(openshell.options.v1.secret) = true]; // Expiry timestamp in milliseconds since epoch. 0 means no expiry // (backward-compatible default for sessions created before this field existed). @@ -999,7 +1056,7 @@ message StoredProviderCredentialRefreshState { string provider_name = 3; string credential_key = 4; ProviderCredentialRefreshStrategy strategy = 5; - map material = 6; + map material = 6 [(openshell.options.v1.secret) = true]; repeated string secret_material_keys = 7; int64 expires_at_ms = 8; int64 next_refresh_at_ms = 9; @@ -1025,7 +1082,7 @@ message ConfigureProviderRefreshRequest { string provider = 1; string credential_key = 2; ProviderCredentialRefreshStrategy strategy = 3; - map material = 4; + map material = 4 [(openshell.options.v1.secret) = true]; repeated string secret_material_keys = 5; optional int64 expires_at_ms = 6; } @@ -1075,6 +1132,12 @@ message ProviderProfile { repeated openshell.sandbox.v1.NetworkBinary binaries = 7; bool inference_capable = 8; ProviderProfileDiscovery discovery = 9; + // Storage resource version for custom profiles. Built-in profiles and new + // profile files use 0. Gateway responses set this for stored custom profiles. + // Update calls use this for optimistic concurrency. + uint64 resource_version = 10; + // Optional non-secret annotations attached by profile sources or importers. + map annotations = 11; } // Stored custom provider profile object. @@ -1105,6 +1168,25 @@ message ImportProviderProfilesResponse { bool imported = 3; } +// Update one custom provider profile request. +message UpdateProviderProfilesRequest { + ProviderProfileImportItem profile = 1; + // Expected storage resource version for optimistic concurrency control. + // If 0, the server uses the resource_version embedded in profile.profile. + // Updates without a non-zero version are rejected to prevent stale files from + // silently overwriting newer profile definitions. + uint64 expected_resource_version = 2; + // Existing custom provider profile ID to update. The payload ID must match. + string id = 3; +} + +// Update one custom provider profile response. +message UpdateProviderProfilesResponse { + repeated ProviderProfileDiagnostic diagnostics = 1; + ProviderProfile profile = 2; + bool updated = 3; +} + // Lint provider profiles request. message LintProviderProfilesRequest { repeated ProviderProfileImportItem profiles = 1; @@ -1140,7 +1222,7 @@ message GetSandboxProviderEnvironmentRequest { // Get sandbox provider environment response. message GetSandboxProviderEnvironmentResponse { // Provider credential environment variables. - map environment = 1; + map environment = 1 [(openshell.options.v1.secret) = true]; // Fingerprint for the provider credential inputs that produced environment. uint64 provider_env_revision = 2; // Expiration timestamps for returned environment variables. @@ -1186,6 +1268,13 @@ message UpdateConfigRequest { // matches this value before applying the mutation, returning ABORTED on mismatch. // Ignored for global-scoped updates. uint64 expected_resource_version = 8; + // Caller-provided annotations associated with a sandbox-scoped update. Values + // must not contain secrets; the gateway treats them as opaque metadata and does + // not interpret or verify their semantics. For policy updates, the gateway + // stores the annotations immutably with the revision and merges them into + // sandbox metadata as a convenience projection. For setting-only updates, it + // only merges them into sandbox metadata. + map annotations = 9; } message PolicyMergeOperation { @@ -1241,6 +1330,8 @@ message UpdateConfigResponse { uint64 settings_revision = 3; // True when a setting delete operation removed an existing key. bool deleted = 4; + // Sandbox metadata annotations after the update. Empty for global updates. + map annotations = 5; } // Get sandbox policy status request. @@ -1307,6 +1398,8 @@ message SandboxPolicyRevision { int64 loaded_at_ms = 6; // The full policy (only populated when explicitly requested). openshell.sandbox.v1.SandboxPolicy policy = 7; + // Immutable provenance supplied with this policy revision. + map provenance = 8; } // Policy load status. @@ -1788,6 +1881,8 @@ message PolicyRevisionPayload { string load_error = 3; // When the policy version was reported as loaded (ms since epoch). 0 if unset. int64 loaded_at_ms = 4; + // Immutable provenance supplied when this revision was created. + map provenance = 5; } // Stored payload for a draft policy chunk row in the generic objects table. @@ -1831,6 +1926,7 @@ message StoredPolicyRevision { optional string load_error = 7; int64 created_at_ms = 8; optional int64 loaded_at_ms = 9; + map provenance = 10; } // Internal stored draft chunk row materialized from the generic objects table. diff --git a/crates/right-openshell/proto/openshell/sandbox.proto b/crates/right-openshell/proto/openshell/sandbox.proto index ef0b0540..8a5a5933 100644 --- a/crates/right-openshell/proto/openshell/sandbox.proto +++ b/crates/right-openshell/proto/openshell/sandbox.proto @@ -128,6 +128,53 @@ message NetworkEndpoint { // Advisor-proposed endpoints must not satisfy exact-host SSRF trust unless // they are converted through an explicit user-authored policy path. bool advisor_proposed = 18; + // Proxy-side credential signing mode: "sigv4" for AWS SigV4 re-signing. + // When set, the proxy strips the client's Authorization header and computes + // a fresh SigV4 signature using real credentials from the provider. + string credential_signing = 19; + // AWS signing service name override. Required when credential_signing is + // "sigv4" — e.g. "bedrock" for bedrock-runtime endpoints. + string signing_service = 20; + // AWS region override for SigV4 signing. When set, takes precedence over + // hostname-based region extraction. Required for non-standard endpoints. + string signing_region = 21; + // Maximum JSON-RPC-over-HTTP request body bytes to buffer for inspection. + // Defaults to 65536 when unset. + uint32 json_rpc_max_body_bytes = 22; + // MCP-only policy and inspection options. Only used when protocol is "mcp". + McpOptions mcp = 23; +} + +// MCP options are grouped so MCP-specific policy can grow without adding more +// top-level NetworkEndpoint fields. Current enforcement targets the active +// 2025-11-25 Streamable HTTP/tools behavior, while preserving space for +// version-profile policy if OpenShell adopts 2026-07-28 draft behavior later. +// +// Planned policy extensions should use OpenShell-owned static definitions for +// MCP method/version profiles rather than treating dependency enums as the +// policy contract. Candidate profile checks include request metadata/header +// validation, response/SSE introspection, trusted annotation handling, +// resultType/cache metadata validation, x-mcp-header tool-definition checks, +// and subscriptions/listen handling. +// +// Sources: +// - https://modelcontextprotocol.io/specification/2025-11-25/server/tools +// - https://modelcontextprotocol.io/specification/draft/changelog +// - https://modelcontextprotocol.io/specification/draft/basic/transports/streamable-http +// - https://modelcontextprotocol.io/specification/draft/server/tools +message McpOptions { + // Hardening boundary for tools/call params.name. When unset or true, the + // supervisor enforces the MCP recommended tool-name syntax + // ^[A-Za-z0-9_.-]{1,128}$ before policy evaluation. Set false only for + // compatibility with servers that intentionally use non-recommended names. + // + // Source: + // - https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool-names + optional bool strict_tool_names = 1; + // Method-layer default for MCP endpoints. When true, OpenShell allows parsed + // MCP-family methods at the method layer unless a tool-name policy narrows + // tools/call. When unset or false, explicit method rules are required. + optional bool allow_all_known_mcp_methods = 2; } // Trusted GraphQL operation classification. @@ -144,7 +191,8 @@ message GraphqlOperation { // Mirrors L7Allow — same fields, same matching semantics, inverted effect. // Deny rules are evaluated after allow rules and take precedence. message L7DenyRule { - // HTTP method (REST): GET, POST, etc. or "*" for any. + // Protocol method: HTTP method (REST/WebSocket), JSON-RPC method name, or + // "*" for any when supported by the protocol. string method = 1; // URL path glob pattern (REST): "/repos/*/pulls/*/reviews", "**" for any. string path = 2; @@ -160,6 +208,10 @@ message L7DenyRule { // GraphQL root field globs. Deny rules match when any selected root field // matches any configured glob. repeated string fields = 7; + reserved 8; + // MCP params matcher map. Currently only params.name is supported for + // tools/call filtering. Generic protocol "json-rpc" rejects params matchers. + map params = 9; } // An L7 policy rule (allow-only). @@ -169,7 +221,8 @@ message L7Rule { // Allowed action definition for L7 rules. message L7Allow { - // HTTP method (REST): GET, POST, etc. or "*" for any. + // Protocol method: HTTP method (REST/WebSocket), JSON-RPC method name, or + // "*" for any when supported by the protocol. string method = 1; // URL path glob pattern (REST): "/repos/**", "**" for any. string path = 2; @@ -186,6 +239,10 @@ message L7Allow { // GraphQL root field globs. Allow rules match only when every selected root // field matches one of the configured globs. Omit to match all fields. repeated string fields = 7; + reserved 8; + // MCP params matcher map. Currently only params.name is supported for + // tools/call filtering. Generic protocol "json-rpc" rejects params matchers. + map params = 9; } // Query value matcher for one query parameter key.