From 6646a31dab50ee78a1863d1cb8229471d5f5461c Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Wed, 9 Sep 2026 12:37:57 -0700 Subject: [PATCH 1/5] feat(supervisor): stage gateway configuration snapshot delivery Signed-off-by: Piotr Mlocek --- architecture/gateway.md | 18 + architecture/sandbox.md | 38 + crates/openshell-core/src/proto/mod.rs | 7 + crates/openshell-server/src/compute/mod.rs | 55 + .../openshell-server/src/config_delivery.rs | 661 ++++ crates/openshell-server/src/grpc/policy.rs | 666 +++- crates/openshell-server/src/grpc/provider.rs | 51 +- crates/openshell-server/src/grpc/sandbox.rs | 16 + crates/openshell-server/src/lib.rs | 21 + .../src/persistence/postgres.rs | 44 + .../src/persistence/sqlite.rs | 30 + .../openshell-server/src/persistence/tests.rs | 81 +- crates/openshell-server/src/policy_store.rs | 19 + .../openshell-server/src/provider_refresh.rs | 24 +- .../src/supervisor_session.rs | 434 ++- .../src/supervisor_session.rs | 42 + docs/reference/gateway-config.mdx | 3 +- proto/openshell.proto | 132 +- proto/sandbox.proto | 18 +- sdk/go/proto/openshellv1/openshell.pb.go | 2951 +++++++++++------ sdk/go/proto/openshellv1/openshell_grpc.pb.go | 14 +- sdk/go/proto/sandboxv1/sandbox.pb.go | 256 +- sdk/typescript/src/raw.ts | 2 +- skills/debug-openshell-cluster/SKILL.md | 2 + 24 files changed, 4416 insertions(+), 1169 deletions(-) create mode 100644 crates/openshell-server/src/config_delivery.rs diff --git a/architecture/gateway.md b/architecture/gateway.md index 4b0e70c730..23216798c6 100644 --- a/architecture/gateway.md +++ b/architecture/gateway.md @@ -543,6 +543,24 @@ successful create therefore yields an immediately usable provider; failures roll back the provider record. Service-account JSON and private keys remain gateway-side refresh bootstrap material; sandboxes receive minted access tokens instead. +## Supervisor configuration routing + +Committed configuration mutations publish component and scope identifiers, +never configuration payloads, to a bounded coalescing scheduler. The scheduler +builds the latest full snapshot for each affected active sandbox. An async +router owns session lookup, message sizing, sequence allocation, and enqueue. +Its local implementation uses the process-local supervisor registry. A future +HA implementation can resolve the gateway that owns a session and forward the +same typed message without changing mutation handlers. + +Polling remains authoritative during the first rollout stage. Snapshot build, +fanout, or enqueue failure cannot fail a mutation that already committed. +Provider snapshots may contain credentials and must not be +persisted or included in logs. + +See [sandbox configuration delivery](sandbox.md#supervisor-configuration-delivery) +for bootstrap, revision, and supervisor application semantics. + ## Supervisor Relay Sandbox workloads maintain an outbound supervisor session to the gateway. This diff --git a/architecture/sandbox.md b/architecture/sandbox.md index 8676ac9a56..5447c1c93c 100644 --- a/architecture/sandbox.md +++ b/architecture/sandbox.md @@ -471,6 +471,44 @@ the structured 403 and authors the narrowest rule. Mechanistically mapping L7 would either over-broaden rules or require path-templating logic that rots quickly. +## Supervisor Configuration Delivery + +The gateway and supervisor must implement the same internal supervisor protocol +revision. The gateway includes a configuration bootstrap when it accepts a +`ConnectSupervisor` session and can send complete component replacements on the +same stream after policy, settings, or provider state changes. +Bootstrap construction does not gate the session while polling remains +authoritative. These payloads describe the latest effective state rather than +the mutation that produced it. The gateway assigns ordering sequences within +each session and component, while each snapshot retains its own content +revision. + +Bootstrap components are independent read projections, not one atomic database +snapshot. The sandbox configuration carries the provider-environment revision +it was built against. The gateway retries bootstrap construction when that +revision does not match the provider snapshot. Later component updates and +polling repair changes committed while the other projections were being built. + +Configuration delivery goes through a gateway-owned routing boundary rather +than exposing local supervisor channels to mutation handlers. The current +implementation routes only to a supervisor connected to the same gateway +process. The asynchronous router contract can resolve a remote owner later +without changing publishers. Provider payloads can contain +credentials, so the gateway does not persist or render complete stream +messages in logs. + +The supervisor currently parses and ignores stream-delivered configuration. +Polling remains the only path that changes runtime state and repairs dropped or +unavailable delivery. The gateway serializes construction per sandbox and +component, and coalesces repeated mutations into the latest full snapshot. An +enqueue result means only that the local stream queue accepted the message. A +bounded scope fanout scheduler coalesces repeated workspace and global changes. +Snapshot construction has a deadline, and the gateway rejects encoded stream +messages that approach the transport decoder limit. A +later migration will apply these payloads directly and acknowledge their exact +revisions before removing supervisor polling. At that point, the gateway will +require a valid bootstrap before marking a session ready. + ## Policy Revision Acknowledgement When the supervisor loads a sandbox-scoped policy from the gateway, it retains diff --git a/crates/openshell-core/src/proto/mod.rs b/crates/openshell-core/src/proto/mod.rs index cd4b24afe9..c458294f9b 100644 --- a/crates/openshell-core/src/proto/mod.rs +++ b/crates/openshell-core/src/proto/mod.rs @@ -73,3 +73,10 @@ pub use middleware::v1::*; pub use openshell::*; pub use sandbox::v1::*; pub use test::ObjectForTest; + +/// Exact protocol revision required between a gateway and its supervisor. +/// +/// The supervisor stream is an internal, version-locked deployment contract. +/// Bump this when either peer can no longer honor the previous stream +/// semantics. +pub const SUPERVISOR_PROTOCOL_REVISION: u32 = 1; diff --git a/crates/openshell-server/src/compute/mod.rs b/crates/openshell-server/src/compute/mod.rs index 70356e1add..7be655de02 100644 --- a/crates/openshell-server/src/compute/mod.rs +++ b/crates/openshell-server/src/compute/mod.rs @@ -989,6 +989,18 @@ impl ComputeRuntime { } })?; + if let Err(status) = Box::pin(crate::grpc::policy::initialize_policy_history( + self.store.as_ref(), + &sandbox, + crate::grpc::policy::InitialPolicyHistoryStatus::Pending, + )) + .await + { + let _ = self.store.delete(Sandbox::object_type(), &sandbox_id).await; + self.sandbox_index.remove_sandbox(&sandbox_id); + return Err(status); + } + if let Some(token) = sandbox_token && let Some(spec) = driver_sandbox.spec.as_mut() { @@ -1026,6 +1038,10 @@ impl ComputeRuntime { Ok(sandbox) } Err(status) if status.code() == Code::AlreadyExists => { + let _ = self + .store + .delete_by_scope(POLICY_OBJECT_TYPE, sandbox.object_id()) + .await; let _ = self .store .delete(Sandbox::object_type(), sandbox.object_id()) @@ -1034,6 +1050,10 @@ impl ComputeRuntime { Err(Status::already_exists("sandbox already exists")) } Err(status) if status.code() == Code::FailedPrecondition => { + let _ = self + .store + .delete_by_scope(POLICY_OBJECT_TYPE, sandbox.object_id()) + .await; let _ = self .store .delete(Sandbox::object_type(), sandbox.object_id()) @@ -1042,6 +1062,10 @@ impl ComputeRuntime { Err(Status::failed_precondition(status.message().to_string())) } Err(err) => { + let _ = self + .store + .delete_by_scope(POLICY_OBJECT_TYPE, sandbox.object_id()) + .await; let _ = self .store .delete(Sandbox::object_type(), sandbox.object_id()) @@ -4953,6 +4977,7 @@ pub async fn new_test_runtime_with_driver( #[cfg(test)] mod tests { use super::*; + use crate::policy_store::PolicyStoreExt; use futures::stream; use openshell_core::proto::compute::v1::{ CreateSandboxResponse, DeleteSandboxResponse, GetCapabilitiesResponse, GetSandboxRequest, @@ -11255,6 +11280,36 @@ mod tests { ); } + #[tokio::test] + async fn create_sandbox_persists_initial_policy_revision() { + let runtime = test_runtime(Arc::new(TestDriver::default())).await; + let mut sandbox = sandbox_record( + "sb-initial-policy", + "initial-policy", + SandboxPhase::Provisioning, + ); + let policy = openshell_core::proto::SandboxPolicy::default(); + sandbox.spec = Some(SandboxSpec { + policy: Some(policy.clone()), + ..Default::default() + }); + + runtime.create_sandbox(sandbox, None, false).await.unwrap(); + + let revision = runtime + .store + .get_latest_policy("sb-initial-policy") + .await + .unwrap() + .expect("initial policy revision"); + assert_eq!(revision.version, 1); + assert_eq!( + revision.policy_hash, + crate::grpc::policy::deterministic_policy_hash(&policy) + ); + assert_eq!(revision.status, "pending"); + } + #[tokio::test] async fn created_sandbox_is_immediately_visible_to_label_selectors() { let runtime = test_runtime(Arc::new(TestDriver::default())).await; diff --git a/crates/openshell-server/src/config_delivery.rs b/crates/openshell-server/src/config_delivery.rs new file mode 100644 index 0000000000..99470ef7bc --- /dev/null +++ b/crates/openshell-server/src/config_delivery.rs @@ -0,0 +1,661 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Build and route complete supervisor configuration snapshots. + +use std::collections::HashMap; +use std::collections::hash_map::Entry; +use std::fmt; +use std::sync::{Arc, Mutex}; +use std::time::Duration; + +use metrics::counter; +use openshell_core::proto::{ + ConfigBootstrap, ProviderEnvironmentSnapshot, Sandbox, SandboxConfigSnapshot, +}; +use tonic::{Code, Status}; +use tracing::warn; + +use crate::ServerState; +use crate::grpc::policy::{build_provider_environment_snapshot, build_sandbox_config_snapshot}; +use crate::persistence::ObjectWorkspace; +use crate::supervisor_session::SupervisorSessionRegistry; + +/// Leaves headroom below tonic's default 4 MiB decode limit for framing and +/// future envelope fields. +pub const MAX_SUPERVISOR_CONFIG_MESSAGE_BYTES: usize = 3 * 1024 * 1024; +const CONFIG_SNAPSHOT_BUILD_TIMEOUT: Duration = Duration::from_secs(45); +const MAX_ACTIVE_FANOUT_WORKERS: usize = 64; + +/// One complete configuration component awaiting delivery to a supervisor. +#[derive(Clone)] +pub enum SupervisorConfigMessage { + SandboxConfig(Box), + ProviderEnvironment(ProviderEnvironmentSnapshot), +} + +impl SupervisorConfigMessage { + pub(crate) fn component_name(&self) -> &'static str { + match self { + Self::SandboxConfig(_) => "sandbox_config", + Self::ProviderEnvironment(_) => "provider_environment", + } + } +} + +impl fmt::Debug for SupervisorConfigMessage { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str(match self { + Self::SandboxConfig(_) => "SandboxConfig()", + Self::ProviderEnvironment(_) => "ProviderEnvironment()", + }) + } +} + +/// Result of routing one configuration snapshot toward a supervisor session. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DeliveryDisposition { + Enqueued, + NoActiveSession, + QueueFull, + SessionClosed, + PayloadTooLarge, +} + +/// Transport boundary for configuration delivery. +#[tonic::async_trait] +pub trait SupervisorConfigRouter: fmt::Debug + Send + Sync { + async fn deliver( + &self, + sandbox_id: &str, + message: SupervisorConfigMessage, + ) -> DeliveryDisposition; + + async fn routable_sandbox_ids(&self) -> Vec; +} + +#[derive(Debug)] +pub struct LocalSupervisorConfigRouter { + sessions: Arc, +} + +impl LocalSupervisorConfigRouter { + #[must_use] + pub fn new(sessions: Arc) -> Self { + Self { sessions } + } +} + +#[tonic::async_trait] +impl SupervisorConfigRouter for LocalSupervisorConfigRouter { + async fn deliver( + &self, + sandbox_id: &str, + message: SupervisorConfigMessage, + ) -> DeliveryDisposition { + self.sessions.deliver_config(sandbox_id, message) + } + + async fn routable_sandbox_ids(&self) -> Vec { + self.sessions.connected_sandbox_ids() + } +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] +pub struct ConfigComponents { + pub sandbox_config: bool, + pub provider_environment: bool, +} + +impl ConfigComponents { + pub const ALL: Self = Self { + sandbox_config: true, + provider_environment: true, + }; + + pub const SANDBOX_AND_PROVIDER: Self = Self { + sandbox_config: true, + provider_environment: true, + }; + + pub const SANDBOX_CONFIG: Self = Self { + sandbox_config: true, + provider_environment: false, + }; + + fn selected(self) -> impl Iterator { + [ + (self.sandbox_config, ConfigComponentKind::SandboxConfig), + ( + self.provider_environment, + ConfigComponentKind::ProviderEnvironment, + ), + ] + .into_iter() + .filter_map(|(selected, component)| selected.then_some(component)) + } + + fn only(component: ConfigComponentKind) -> Self { + Self { + sandbox_config: component == ConfigComponentKind::SandboxConfig, + provider_environment: component == ConfigComponentKind::ProviderEnvironment, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum ConfigComponentKind { + SandboxConfig, + ProviderEnvironment, +} + +impl ConfigComponentKind { + fn name(self) -> &'static str { + match self { + Self::SandboxConfig => "sandbox_config", + Self::ProviderEnvironment => "provider_environment", + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +struct DeliveryKey { + sandbox_id: String, + component: ConfigComponentKind, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +enum FanoutScope { + Workspace(String), + AllConnected, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +struct FanoutKey { + scope: FanoutScope, + component: ConfigComponentKind, +} + +/// Coalesces publications and runs one worker per sandbox and component. +/// +/// The map entry is also the worker lease. Its boolean is set when another +/// mutation arrives during a build or route operation. The worker then rebuilds +/// the current full snapshot once, regardless of how many mutations arrived. +#[derive(Debug, Default)] +pub struct ConfigDeliveryQueue { + pending: Mutex>, + fanout_pending: Mutex>, +} + +impl ConfigDeliveryQueue { + fn enqueue(&self, key: DeliveryKey) -> bool { + let mut pending = self.pending.lock().unwrap(); + match pending.entry(key) { + Entry::Occupied(mut entry) => { + *entry.get_mut() = true; + false + } + Entry::Vacant(entry) => { + entry.insert(true); + true + } + } + } + + fn take(&self, key: &DeliveryKey) { + let mut pending = self.pending.lock().unwrap(); + if let Some(changed) = pending.get_mut(key) { + *changed = false; + } + } + + fn finish_pass(&self, key: &DeliveryKey) -> bool { + let mut pending = self.pending.lock().unwrap(); + if pending.get(key).is_some_and(|changed| !changed) { + pending.remove(key); + false + } else { + pending.contains_key(key) + } + } + + fn enqueue_fanout(&self, key: FanoutKey) -> FanoutEnqueue { + let mut pending = self.fanout_pending.lock().unwrap(); + if let Some(changed) = pending.get_mut(&key) { + *changed = true; + return FanoutEnqueue::Coalesced; + } + if pending.len() >= MAX_ACTIVE_FANOUT_WORKERS { + FanoutEnqueue::Full + } else { + pending.insert(key, true); + FanoutEnqueue::StartWorker + } + } + + fn take_fanout(&self, key: &FanoutKey) { + let mut pending = self.fanout_pending.lock().unwrap(); + if let Some(changed) = pending.get_mut(key) { + *changed = false; + } + } + + fn finish_fanout_pass(&self, key: &FanoutKey) -> bool { + let mut pending = self.fanout_pending.lock().unwrap(); + if pending.get(key).is_some_and(|changed| !changed) { + pending.remove(key); + false + } else { + pending.contains_key(key) + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum FanoutEnqueue { + StartWorker, + Coalesced, + Full, +} + +pub async fn build_config_bootstrap( + state: &Arc, + sandbox: &Sandbox, +) -> Result { + tokio::time::timeout( + CONFIG_SNAPSHOT_BUILD_TIMEOUT, + build_consistent_config_bootstrap(state, sandbox), + ) + .await + .map_err(|_| Status::deadline_exceeded("supervisor configuration bootstrap timed out"))? +} + +async fn build_consistent_config_bootstrap( + state: &Arc, + sandbox: &Sandbox, +) -> Result { + const MAX_BUILD_ATTEMPTS: usize = 3; + for _ in 0..MAX_BUILD_ATTEMPTS { + // Components are independent projections. The provider revision is a + // fence for the only overlapping input between sandbox configuration + // and provider environment state. + let (sandbox_config, provider_environment) = tokio::join!( + build_sandbox_config_snapshot(state, sandbox), + build_provider_environment_snapshot(state, sandbox, true), + ); + let bootstrap = ConfigBootstrap { + sandbox_config: Some(sandbox_config?), + provider_environment: Some(provider_environment?), + }; + if bootstrap_revisions_match(&bootstrap) { + return Ok(bootstrap); + } + counter!("openshell_supervisor_config_bootstrap_revision_mismatches_total").increment(1); + } + Err(Status::aborted( + "configuration changed while building supervisor bootstrap", + )) +} + +fn bootstrap_revisions_match(bootstrap: &ConfigBootstrap) -> bool { + bootstrap + .sandbox_config + .as_ref() + .zip(bootstrap.provider_environment.as_ref()) + .is_some_and(|(sandbox, provider)| { + sandbox.provider_env_revision == provider.provider_env_revision + }) +} + +pub fn publish_sandbox_components( + state: &Arc, + sandbox_id: &str, + components: ConfigComponents, +) { + enqueue_sandbox(state, sandbox_id, components); +} + +fn enqueue_sandbox(state: &Arc, sandbox_id: &str, components: ConfigComponents) { + for component in components.selected() { + let key = DeliveryKey { + sandbox_id: sandbox_id.to_string(), + component, + }; + if state.config_delivery_queue.enqueue(key.clone()) { + let state = Arc::clone(state); + tokio::spawn(async move { + loop { + state.config_delivery_queue.take(&key); + publish_sandbox_component_now(&state, &key).await; + if !state.config_delivery_queue.finish_pass(&key) { + break; + } + } + }); + } + } +} + +async fn publish_sandbox_component_now(state: &Arc, key: &DeliveryKey) { + let sandbox = match state.store.get_message::(&key.sandbox_id).await { + Ok(Some(sandbox)) => sandbox, + Ok(None) => return, + Err(_) => { + record_build_failure(&key.sandbox_id, "sandbox", Code::Internal); + return; + } + }; + let component = key.component.name(); + let build = async { + match key.component { + ConfigComponentKind::SandboxConfig => build_sandbox_config_snapshot(state, &sandbox) + .await + .map(|snapshot| SupervisorConfigMessage::SandboxConfig(Box::new(snapshot))), + ConfigComponentKind::ProviderEnvironment => { + build_provider_environment_snapshot(state, &sandbox, true) + .await + .map(SupervisorConfigMessage::ProviderEnvironment) + } + } + }; + match tokio::time::timeout(CONFIG_SNAPSHOT_BUILD_TIMEOUT, build).await { + Ok(Ok(message)) => { + let disposition = state + .supervisor_config_router() + .deliver(&key.sandbox_id, message) + .await; + record_delivery(component, disposition); + } + Ok(Err(error)) => { + record_build_failure(&key.sandbox_id, component, error.code()); + } + Err(_) => { + record_build_failure(&key.sandbox_id, component, Code::DeadlineExceeded); + } + } +} + +pub fn publish_workspace_components( + state: &Arc, + workspace: &str, + components: ConfigComponents, +) { + enqueue_fanout( + state, + FanoutScope::Workspace(workspace.to_string()), + components, + ); +} + +pub fn publish_all_connected(state: &Arc, components: ConfigComponents) { + enqueue_fanout(state, FanoutScope::AllConnected, components); +} + +fn enqueue_fanout(state: &Arc, scope: FanoutScope, components: ConfigComponents) { + for component in components.selected() { + let key = FanoutKey { + scope: scope.clone(), + component, + }; + match state.config_delivery_queue.enqueue_fanout(key.clone()) { + FanoutEnqueue::StartWorker => { + let state = Arc::clone(state); + tokio::spawn(async move { + loop { + state.config_delivery_queue.take_fanout(&key); + publish_fanout_now(&state, &key).await; + if !state.config_delivery_queue.finish_fanout_pass(&key) { + break; + } + } + }); + } + FanoutEnqueue::Coalesced => {} + FanoutEnqueue::Full => { + counter!("openshell_supervisor_config_fanout_total", "outcome" => "queue_full") + .increment(1); + warn!( + component = component.name(), + "supervisor configuration fanout queue is full" + ); + } + } + } +} + +async fn publish_fanout_now(state: &Arc, key: &FanoutKey) { + let sandbox_ids = state + .supervisor_config_router() + .routable_sandbox_ids() + .await; + for sandbox_id in sandbox_ids { + if let FanoutScope::Workspace(workspace) = &key.scope { + let sandbox = match state.store.get_message::(&sandbox_id).await { + Ok(Some(sandbox)) => sandbox, + Ok(None) => continue, + Err(_) => { + record_build_failure(&sandbox_id, "sandbox", Code::Internal); + continue; + } + }; + if sandbox.object_workspace() != workspace { + continue; + } + } + enqueue_sandbox(state, &sandbox_id, ConfigComponents::only(key.component)); + } +} + +fn record_delivery(component: &'static str, disposition: DeliveryDisposition) { + let outcome = match disposition { + DeliveryDisposition::Enqueued => "enqueued", + DeliveryDisposition::NoActiveSession => "no_active_session", + DeliveryDisposition::QueueFull => "queue_full", + DeliveryDisposition::SessionClosed => "session_closed", + DeliveryDisposition::PayloadTooLarge => "payload_too_large", + }; + counter!( + "openshell_supervisor_config_deliveries_total", + "component" => component, + "outcome" => outcome, + ) + .increment(1); +} + +fn record_build_failure(sandbox_id: &str, component: &'static str, error_code: Code) { + counter!( + "openshell_supervisor_config_snapshot_failures_total", + "component" => component, + ) + .increment(1); + warn!( + sandbox_id = %sandbox_id, + component, + ?error_code, + "failed to build supervisor configuration snapshot" + ); +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::grpc::{OpenShellService, test_support::test_server_state}; + use openshell_core::proto::{ + GatewayMessage, ObjectMeta, SandboxSpec, SupervisorHello, SupervisorMessage, + gateway_message, open_shell_client::OpenShellClient, open_shell_server::OpenShellServer, + supervisor_message, + }; + use tokio::sync::mpsc; + use tokio_stream::wrappers::{ReceiverStream, TcpListenerStream}; + + fn key(sandbox_id: &str, component: ConfigComponentKind) -> DeliveryKey { + DeliveryKey { + sandbox_id: sandbox_id.to_string(), + component, + } + } + + #[test] + fn queue_coalesces_repeated_component_changes_while_worker_is_active() { + let queue = ConfigDeliveryQueue::default(); + let key = key("sb-1", ConfigComponentKind::SandboxConfig); + assert!(queue.enqueue(key.clone())); + queue.take(&key); + assert!(!queue.enqueue(key.clone())); + assert!(!queue.enqueue(key.clone())); + assert!(queue.finish_pass(&key)); + queue.take(&key); + assert!(!queue.finish_pass(&key)); + } + + #[test] + fn queue_runs_components_and_sandboxes_independently() { + let queue = ConfigDeliveryQueue::default(); + assert!(queue.enqueue(key("sb-1", ConfigComponentKind::SandboxConfig))); + assert!(queue.enqueue(key("sb-1", ConfigComponentKind::ProviderEnvironment))); + assert!(queue.enqueue(key("sb-2", ConfigComponentKind::SandboxConfig))); + } + + #[test] + fn fanout_queue_coalesces_and_bounds_distinct_scopes() { + let queue = ConfigDeliveryQueue::default(); + let first = FanoutKey { + scope: FanoutScope::Workspace("workspace-0".into()), + component: ConfigComponentKind::SandboxConfig, + }; + assert_eq!( + queue.enqueue_fanout(first.clone()), + FanoutEnqueue::StartWorker + ); + queue.take_fanout(&first); + assert_eq!( + queue.enqueue_fanout(first.clone()), + FanoutEnqueue::Coalesced + ); + assert!(queue.finish_fanout_pass(&first)); + + for index in 1..MAX_ACTIVE_FANOUT_WORKERS { + assert_eq!( + queue.enqueue_fanout(FanoutKey { + scope: FanoutScope::Workspace(format!("workspace-{index}")), + component: ConfigComponentKind::SandboxConfig, + }), + FanoutEnqueue::StartWorker + ); + } + assert_eq!( + queue.enqueue_fanout(FanoutKey { + scope: FanoutScope::Workspace("overflow".into()), + component: ConfigComponentKind::SandboxConfig, + }), + FanoutEnqueue::Full + ); + } + + #[test] + fn configuration_message_debug_output_redacts_payloads() { + let message = SupervisorConfigMessage::ProviderEnvironment(ProviderEnvironmentSnapshot { + values: vec![openshell_core::proto::ProviderEnvironmentValue { + name: "TOKEN".into(), + value: "secret-marker".into(), + ..Default::default() + }], + ..Default::default() + }); + assert!(!format!("{message:?}").contains("secret-marker")); + } + + #[tokio::test] + async fn session_acceptance_precedes_live_configuration_updates() { + let state = test_server_state().await; + state + .store + .put_message(&Sandbox { + metadata: Some(ObjectMeta { + id: "sandbox".into(), + name: "sandbox".into(), + workspace: "default".into(), + ..Default::default() + }), + spec: Some(SandboxSpec::default()), + ..Default::default() + }) + .await + .unwrap(); + + let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); + let address = listener.local_addr().unwrap(); + let server = tokio::spawn( + tonic::transport::Server::builder() + .add_service(OpenShellServer::new(OpenShellService::new(Arc::clone( + &state, + )))) + .serve_with_incoming(TcpListenerStream::new(listener)), + ); + let mut client = OpenShellClient::connect(format!("http://{address}")) + .await + .unwrap(); + let (tx, rx) = mpsc::channel(4); + tx.send(SupervisorMessage { + payload: Some(supervisor_message::Payload::Hello(SupervisorHello { + sandbox_id: "sandbox".into(), + instance_id: "instance".into(), + protocol_revision: openshell_core::proto::SUPERVISOR_PROTOCOL_REVISION, + })), + }) + .await + .unwrap(); + let mut stream = client + .connect_supervisor(ReceiverStream::new(rx)) + .await + .unwrap() + .into_inner(); + + let first = tokio::time::timeout(Duration::from_secs(5), stream.message()) + .await + .unwrap() + .unwrap() + .unwrap(); + assert!(matches!( + first.payload, + Some(gateway_message::Payload::SessionAccepted(_)) + )); + + publish_sandbox_components(&state, "sandbox", ConfigComponents::SANDBOX_CONFIG); + let update = tokio::time::timeout(Duration::from_secs(5), stream.message()) + .await + .unwrap() + .unwrap() + .unwrap(); + assert!(matches!( + update, + GatewayMessage { + payload: Some(gateway_message::Payload::ConfigUpdate(_)) + } + )); + + drop(tx); + server.abort(); + } + + #[test] + fn bootstrap_requires_matching_provider_revision_fence() { + let mut bootstrap = ConfigBootstrap { + sandbox_config: Some(SandboxConfigSnapshot { + provider_env_revision: 7, + ..Default::default() + }), + provider_environment: Some(ProviderEnvironmentSnapshot { + provider_env_revision: 8, + ..Default::default() + }), + }; + assert!(!bootstrap_revisions_match(&bootstrap)); + bootstrap + .provider_environment + .as_mut() + .unwrap() + .provider_env_revision = 7; + assert!(bootstrap_revisions_match(&bootstrap)); + } +} diff --git a/crates/openshell-server/src/grpc/policy.rs b/crates/openshell-server/src/grpc/policy.rs index 054a3c34c6..1fbbfd369f 100644 --- a/crates/openshell-server/src/grpc/policy.rs +++ b/crates/openshell-server/src/grpc/policy.rs @@ -23,6 +23,8 @@ use crate::provider_profile_sources::EffectiveProviderProfileCatalog; #[cfg(test)] use crate::provider_profile_sources::ProviderProfileSources; use openshell_core::net::{is_always_blocked_ip, is_internal_ip}; +#[cfg(test)] +use openshell_core::proto::StaticCredentialBinding; use openshell_core::proto::policy_merge_operation; use openshell_core::proto::setting_value; use openshell_core::proto::{ @@ -36,11 +38,12 @@ use openshell_core::proto::{ GetSandboxPolicyStatusRequest, GetSandboxPolicyStatusResponse, GetSandboxProviderEnvironmentRequest, GetSandboxProviderEnvironmentResponse, ListSandboxPoliciesRequest, ListSandboxPoliciesResponse, PolicyChunk, PolicyMergeOperation, - PolicySource, PolicyStatus, PushSandboxLogsRequest, PushSandboxLogsResponse, + PolicySource, PolicyStatus, ProviderEnvironmentSnapshot, ProviderEnvironmentValue, + ProviderEnvironmentValueClassification, PushSandboxLogsRequest, PushSandboxLogsResponse, RejectDraftChunkRequest, RejectDraftChunkResponse, ReportPolicyStatusRequest, - ReportPolicyStatusResponse, SandboxLogLine, SandboxPolicyRevision, SettingScope, SettingValue, - SubmitPolicyAnalysisRequest, SubmitPolicyAnalysisResponse, UndoDraftChunkRequest, - UndoDraftChunkResponse, UpdateConfigRequest, UpdateConfigResponse, + ReportPolicyStatusResponse, SandboxConfigSnapshot, SandboxLogLine, SandboxPolicyRevision, + SettingScope, SettingValue, SubmitPolicyAnalysisRequest, SubmitPolicyAnalysisResponse, + UndoDraftChunkRequest, UndoDraftChunkResponse, UpdateConfigRequest, UpdateConfigResponse, }; use openshell_core::proto::{ L7DenyRule, L7Rule, NetworkBinary, NetworkEndpoint, NetworkPolicyRule, Provider, Sandbox, @@ -1531,6 +1534,11 @@ async fn auto_approve_chunk( return Err(status); } }; + crate::config_delivery::publish_sandbox_components( + state, + sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); let chunk_summary = summarize_draft_chunk_rule(&chunk)?; let now_ms = current_time_ms(); @@ -2367,6 +2375,18 @@ pub(super) async fn handle_get_sandbox_config( let sandbox = super::sandbox::fetch_and_authorize_sandbox(state, &principal, &sandbox_id).await?; + let snapshot = build_sandbox_config_snapshot(state, &sandbox).await?; + Ok(Response::new(sandbox_config_response(snapshot))) +} + +/// Build the complete effective configuration for one persisted sandbox. +/// +/// This is a read-only projection shared by polling and stream delivery. +pub async fn build_sandbox_config_snapshot( + state: &Arc, + sandbox: &Sandbox, +) -> Result { + let sandbox_id = sandbox.object_id().to_string(); let workspace = sandbox.object_workspace().to_string(); let sandbox_provider_names = sandbox .spec @@ -2391,87 +2411,49 @@ pub(super) async fn handle_get_sandbox_config( .await .map_err(|e| Status::internal(format!("fetch policy history failed: {e}")))?; - let (mut policy, version, mut policy_hash, policy_source) = if let Some(global_policy) = - global_policy - { - let version = latest - .as_ref() - .map(|record| u32::try_from(record.version).unwrap_or(0)) - .filter(|version| *version > 0) - .unwrap_or(1); - let hash = deterministic_policy_hash(&global_policy); - (Some(global_policy), version, hash, PolicySource::Global) - } else if let Some(record) = latest { - let (policy, hash) = canonical_policy_record_identity(&record)?; - debug!( - sandbox_id = %sandbox_id, - version = record.version, - "GetSandboxConfig served from policy history" - ); - ( - Some(policy), - u32::try_from(record.version).unwrap_or(0), - hash, - PolicySource::Sandbox, - ) - } else { - // Lazy backfill: no policy history exists yet. - let spec = sandbox - .spec - .as_ref() - .ok_or_else(|| Status::internal("sandbox has no spec"))?; - - match spec.policy.clone() { - None => { - debug!( - sandbox_id = %sandbox_id, - "GetSandboxConfig: no policy configured, returning empty response" - ); - (None, 0, String::new(), PolicySource::Sandbox) - } - Some(spec_policy) => { - // Stored specs may predate the current schema. Validate before - // creating policy history so malformed state is never copied or - // marked loaded, and hash the canonical representation. - let spec_policy = validate_and_canonicalize_stored_policy( - spec_policy, - STORED_POLICY_SOURCE_SPEC, - )?; - let hash = deterministic_policy_hash(&spec_policy); - let payload = spec_policy.encode_to_vec(); - let policy_id = uuid::Uuid::new_v4().to_string(); - - if let Err(e) = state - .store - .put_policy_revision(&policy_id, &sandbox_id, &workspace, 1, &payload, &hash) - .await - { - warn!( - sandbox_id = %sandbox_id, - error = %e, - "Failed to backfill policy version 1" - ); - } else if let Err(e) = state - .store - .update_policy_status(&sandbox_id, 1, "loaded", None, None) - .await - { - warn!( - sandbox_id = %sandbox_id, - error = %e, - "Failed to mark backfilled policy as loaded" - ); + let (mut policy, version, mut policy_hash, policy_source) = + if let Some(global_policy) = global_policy { + let version = latest + .as_ref() + .map(|record| u32::try_from(record.version).unwrap_or(0)) + .filter(|version| *version > 0) + .unwrap_or(1); + let hash = deterministic_policy_hash(&global_policy); + (Some(global_policy), version, hash, PolicySource::Global) + } else if let Some(record) = latest { + let (policy, hash) = canonical_policy_record_identity(&record)?; + debug!( + sandbox_id = %sandbox_id, + version = record.version, + "GetSandboxConfig served from policy history" + ); + ( + Some(policy), + u32::try_from(record.version).unwrap_or(0), + hash, + PolicySource::Sandbox, + ) + } else { + // Older sandboxes may have policy only in the sandbox spec. Reading a + // snapshot must not create policy history, so project that baseline as + // version 1 until the startup repair persists it. + let spec = sandbox + .spec + .as_ref() + .ok_or_else(|| Status::internal("sandbox has no spec"))?; + + match spec.policy.clone() { + None => (None, 0, String::new(), PolicySource::Sandbox), + Some(spec_policy) => { + let spec_policy = validate_and_canonicalize_stored_policy( + spec_policy, + STORED_POLICY_SOURCE_SPEC, + )?; + let hash = deterministic_policy_hash(&spec_policy); + (Some(spec_policy), 1, hash, PolicySource::Sandbox) } - - info!( - sandbox_id = %sandbox_id, - "GetSandboxConfig served from spec (backfilled version 1)" - ); - - (Some(spec_policy), 1, hash, PolicySource::Sandbox) } - } - }; + }; let global_settings = load_global_settings(state.store.as_ref()).await?; let sandbox_settings = @@ -2578,7 +2560,7 @@ pub(super) async fn handle_get_sandbox_config( ) .await?; - Ok(Response::new(GetSandboxConfigResponse { + Ok(SandboxConfigSnapshot { policy, version, policy_hash, @@ -2595,7 +2577,112 @@ pub(super) async fn handle_get_sandbox_config( .as_str() .to_string(), extension_authentication_enabled: state.sandbox_jwt_issuer.is_some(), - })) + }) +} + +fn sandbox_config_response(snapshot: SandboxConfigSnapshot) -> GetSandboxConfigResponse { + GetSandboxConfigResponse { + policy: snapshot.policy, + version: snapshot.version, + policy_hash: snapshot.policy_hash, + settings: snapshot.settings, + config_revision: snapshot.config_revision, + policy_source: snapshot.policy_source, + global_policy_version: snapshot.global_policy_version, + provider_env_revision: snapshot.provider_env_revision, + supervisor_middleware_services: snapshot.supervisor_middleware_services, + workspace: snapshot.workspace, + policy_validation_failure_mode: snapshot.policy_validation_failure_mode, + extension_authentication_enabled: snapshot.extension_authentication_enabled, + } +} + +#[derive(Clone, Copy)] +pub enum InitialPolicyHistoryStatus { + Pending, + Loaded, +} + +impl InitialPolicyHistoryStatus { + fn as_str(self) -> &'static str { + match self { + Self::Pending => "pending", + Self::Loaded => "loaded", + } + } +} + +/// Insert the version-one policy baseline if this sandbox still has no policy +/// history. This never modifies an existing revision or apply result. +pub async fn initialize_policy_history( + store: &Store, + sandbox: &Sandbox, + status: InitialPolicyHistoryStatus, +) -> Result<(), Status> { + let Some(policy) = sandbox.spec.as_ref().and_then(|spec| spec.policy.as_ref()) else { + return Ok(()); + }; + if store + .get_latest_policy(sandbox.object_id()) + .await + .map_err(|error| Status::internal(format!("read policy history failed: {error}")))? + .is_some() + { + return Ok(()); + } + let policy = + validate_and_canonicalize_stored_policy(policy.clone(), STORED_POLICY_SOURCE_SPEC)?; + store + .put_initial_policy_revision( + &PolicyRecord { + id: uuid::Uuid::new_v4().to_string(), + sandbox_id: sandbox.object_id().to_string(), + version: 1, + policy_payload: policy.encode_to_vec(), + policy_hash: deterministic_policy_hash(&policy), + status: status.as_str().to_string(), + load_error: None, + created_at_ms: current_time_ms(), + loaded_at_ms: None, + provenance: HashMap::new(), + }, + sandbox.object_workspace(), + ) + .await + .map_err(|error| Status::internal(format!("initialize policy history failed: {error}"))) +} + +/// Create policy-history baselines for sandboxes written by older gateways. +/// +/// Snapshot reads stay pure once this startup repair has completed. +pub async fn backfill_legacy_policy_history(state: &Arc) -> Result<(), Status> { + const PAGE_SIZE: u32 = 1000; + let mut offset = 0; + loop { + let sandboxes = state + .store + .list_all_messages::(PAGE_SIZE, offset) + .await + .map_err(|error| { + Status::internal(format!("list sandboxes for policy repair failed: {error}")) + })?; + if sandboxes.is_empty() { + return Ok(()); + } + let count = u32::try_from(sandboxes.len()).unwrap_or(PAGE_SIZE); + for sandbox in sandboxes { + initialize_policy_history( + state.store.as_ref(), + &sandbox, + InitialPolicyHistoryStatus::Loaded, + ) + .await?; + } + if count < PAGE_SIZE { + return Ok(()); + } + offset = offset.saturating_add(count); + } } #[cfg(test)] @@ -3098,6 +3185,19 @@ pub(super) async fn handle_get_sandbox_provider_environment( .await .map_err(|e| Status::internal(format!("fetch sandbox failed: {e}")))? .ok_or_else(|| Status::not_found("sandbox not found"))?; + let snapshot = + build_provider_environment_snapshot(state, &sandbox, supports_static_credential_bindings) + .await?; + Ok(Response::new(provider_environment_response(snapshot))) +} + +/// Build the complete provider environment for one persisted sandbox. +pub async fn build_provider_environment_snapshot( + state: &Arc, + sandbox: &Sandbox, + supports_static_credential_bindings: bool, +) -> Result { + let sandbox_id = sandbox.object_id().to_string(); let workspace = sandbox.object_workspace().to_string(); let spec = sandbox @@ -3120,7 +3220,7 @@ pub(super) async fn handle_get_sandbox_provider_environment( state.as_ref(), &provider_profile_catalog, &workspace, - &sandbox, + sandbox, &sandbox_id, ) .await?; @@ -3185,21 +3285,81 @@ pub(super) async fn handle_get_sandbox_provider_environment( "GetSandboxProviderEnvironment request completed successfully" ); - let non_secret_environment_keys = provider_environment + let mut keys = provider_environment .environment .keys() - .filter(|key| !provider_environment.static_credential_keys.contains(*key)) .cloned() - .collect(); + .collect::>(); + keys.sort(); + let mut values = Vec::with_capacity(keys.len()); + for name in keys { + let value = provider_environment + .environment + .remove(&name) + .expect("provider environment key came from the same map"); + let is_static_credential = provider_environment.static_credential_keys.contains(&name); + let static_credential_binding = provider_environment + .static_credential_bindings + .remove(&name); + if is_static_credential && static_credential_binding.is_none() { + return Err(Status::failed_precondition(format!( + "static provider credential '{name}' has no endpoint binding" + ))); + } + values.push(ProviderEnvironmentValue { + name: name.clone(), + value, + expires_at_ms: provider_environment.credential_expires_at_ms.remove(&name), + classification: if is_static_credential { + ProviderEnvironmentValueClassification::StaticCredential.into() + } else { + ProviderEnvironmentValueClassification::NonSecret.into() + }, + static_credential_binding, + }); + } - Ok(Response::new(GetSandboxProviderEnvironmentResponse { - environment: provider_environment.environment, + Ok(ProviderEnvironmentSnapshot { provider_env_revision, - credential_expires_at_ms: provider_environment.credential_expires_at_ms, + values, dynamic_credentials: provider_environment.dynamic_credentials, - static_credential_bindings: provider_environment.static_credential_bindings, + }) +} + +fn provider_environment_response( + snapshot: ProviderEnvironmentSnapshot, +) -> GetSandboxProviderEnvironmentResponse { + let mut environment = HashMap::with_capacity(snapshot.values.len()); + let mut credential_expires_at_ms = HashMap::new(); + let mut static_credential_bindings = HashMap::new(); + let mut non_secret_environment_keys = Vec::new(); + for value in snapshot.values { + environment.insert(value.name.clone(), value.value); + if let Some(expires_at_ms) = value.expires_at_ms { + credential_expires_at_ms.insert(value.name.clone(), expires_at_ms); + } + match ProviderEnvironmentValueClassification::try_from(value.classification) + .unwrap_or_default() + { + ProviderEnvironmentValueClassification::NonSecret => { + non_secret_environment_keys.push(value.name); + } + ProviderEnvironmentValueClassification::StaticCredential => { + if let Some(binding) = value.static_credential_binding { + static_credential_bindings.insert(value.name, binding); + } + } + ProviderEnvironmentValueClassification::Unspecified => {} + } + } + GetSandboxProviderEnvironmentResponse { + environment, + provider_env_revision: snapshot.provider_env_revision, + credential_expires_at_ms, + dynamic_credentials: snapshot.dynamic_credentials, + static_credential_bindings, non_secret_environment_keys, - })) + } } // --------------------------------------------------------------------------- @@ -3345,6 +3505,10 @@ async fn handle_update_config_inner( if changed { global_settings.revision = global_settings.revision.wrapping_add(1); save_global_settings(state.store.as_ref(), &global_settings).await?; + crate::config_delivery::publish_all_connected( + state, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); } return Ok(update_config_response( u32::try_from(current.version).unwrap_or(0), @@ -3401,6 +3565,10 @@ async fn handle_update_config_inner( if changed { global_settings.revision = global_settings.revision.wrapping_add(1); save_global_settings(state.store.as_ref(), &global_settings).await?; + crate::config_delivery::publish_all_connected( + state, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); } return Ok(update_config_response( @@ -3445,6 +3613,10 @@ async fn handle_update_config_inner( global_settings.revision = global_settings.revision.wrapping_add(1); save_global_settings(state.store.as_ref(), &global_settings).await?; + crate::config_delivery::publish_all_connected( + state, + crate::config_delivery::ConfigComponents::SANDBOX_CONFIG, + ); if req.delete_setting && key == POLICY_SETTING_KEY @@ -3517,6 +3689,11 @@ async fn handle_update_config_inner( &sandbox_settings, ) .await?; + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_CONFIG, + ); } response_annotations = persist_update_config_annotations( @@ -3561,6 +3738,11 @@ async fn handle_update_config_inner( &sandbox_settings, ) .await?; + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_CONFIG, + ); } response_annotations = persist_update_config_annotations( @@ -3619,6 +3801,11 @@ async fn handle_update_config_inner( Some(&atomic_context), ) .await?; + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); response_annotations = if let Some(updated_sandbox) = updated_sandbox { sandbox_metadata_annotations(&updated_sandbox) } else { @@ -3838,6 +4025,11 @@ async fn handle_update_config_inner( })? }; response_annotations = committed_annotations; + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); state.sandbox_watch_bus.notify(&sandbox_id); if backfill_policy.is_some() { @@ -3884,6 +4076,12 @@ async fn handle_update_config_inner( .await .map_err(|e| Status::internal(format!("persist policy revision failed: {e}")))?; + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); + let _ = state .store .supersede_older_policies(&sandbox_id, next_version) @@ -4828,6 +5026,11 @@ async fn handle_approve_draft_chunk_inner( return Err(status); } }; + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); let chunk_summary = summarize_draft_chunk_rule(&chunk)?; let now_ms = current_time_ms(); @@ -4952,6 +5155,11 @@ async fn handle_reject_draft_chunk_inner( require_no_global_policy(state).await?; let (version, hash) = remove_chunk_from_policy(state, &sandbox_id, &workspace, &chunk).await?; + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); emit_gateway_policy_audit_log( &sandbox_id, sandbox.object_name(), @@ -5243,6 +5451,14 @@ async fn handle_approve_all_draft_chunks_inner( } }; + if !accepted.is_empty() { + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); + } + for (chunk, _, chunk_summary) in &accepted { let now_ms = current_time_ms(); clear_pending_application_error(state, &chunk.id).await; @@ -5444,6 +5660,11 @@ async fn handle_undo_draft_chunk_inner( ); let (version, hash) = remove_chunk_from_policy(state, &sandbox_id, &workspace, &chunk).await?; + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); // Clear any prior rejection_reason on the way back to "pending" so an // agent reading the chunk via policy.local cannot see a stale guidance @@ -5799,7 +6020,7 @@ fn canonical_policy_bytes(policy: &ProtoSandboxPolicy) -> Vec { /// Compute a deterministic SHA-256 hash of a `SandboxPolicy`, recursively /// sorting every protobuf map while preserving repeated-field order. -fn deterministic_policy_hash(policy: &ProtoSandboxPolicy) -> String { +pub fn deterministic_policy_hash(policy: &ProtoSandboxPolicy) -> String { hex::encode(Sha256::digest(canonical_policy_bytes(policy))) } @@ -7280,7 +7501,7 @@ mod tests { } #[tokio::test] - async fn get_sandbox_config_backfills_canonical_spec_policy_bytes_and_hash() { + async fn startup_repair_backfills_canonical_spec_policy_bytes_and_hash() { let state = test_server_state().await; let sandbox_id = "stored-canonical-backfill"; let raw = mcp_policy_with_versions(&["2025-11-25", "2025-03-26", "2025-06-18"]); @@ -7315,6 +7536,15 @@ mod tests { assert_eq!(response.policy_hash, canonical_hash); assert_eq!(response.version, 1); + assert!( + state + .store + .get_latest_policy(sandbox_id) + .await + .unwrap() + .is_none() + ); + backfill_legacy_policy_history(&state).await.unwrap(); let persisted = state .store .get_latest_policy(sandbox_id) @@ -7327,7 +7557,7 @@ mod tests { } #[tokio::test] - async fn get_sandbox_config_backfills_defaulted_mcp_policy_as_canonical_bytes_and_hash() { + async fn startup_repair_backfills_defaulted_mcp_policy_as_canonical_bytes_and_hash() { let state = test_server_state().await; let canonical = validate_and_canonicalize_policy(mcp_policy_with_versions(&["2025-11-25"])) .expect("explicit default MCP policy must canonicalize"); @@ -7373,6 +7603,15 @@ mod tests { "{case}" ); + assert!( + state + .store + .get_latest_policy(&sandbox_id) + .await + .unwrap() + .is_none() + ); + backfill_legacy_policy_history(&state).await.unwrap(); let persisted = state .store .get_latest_policy(&sandbox_id) @@ -10364,6 +10603,114 @@ mod tests { ); } + #[tokio::test] + async fn rejected_policy_update_does_not_publish_configuration() { + let state = test_server_state().await; + let mut sandbox = test_sandbox( + "sb-rejected-policy", + "rejected-policy", + ProtoSandboxPolicy::default(), + Vec::new(), + ); + sandbox.spec.as_mut().unwrap().policy = None; + state.store.put_message(&sandbox).await.unwrap(); + + let (tx, mut rx) = tokio::sync::mpsc::channel(1); + let (shutdown_tx, _shutdown_rx) = tokio::sync::oneshot::channel(); + state.supervisor_sessions.register( + "sb-rejected-policy".to_string(), + "session-1".to_string(), + tx, + shutdown_tx, + ); + + let error = handle_update_config( + &state, + with_user(Request::new(UpdateConfigRequest { + name: "rejected-policy".to_string(), + workspace: "default".to_string(), + policy: Some(test_policy_with_rule("rejected", "api.example.com")), + expected_resource_version: u64::MAX, + ..Default::default() + })), + ) + .await + .expect_err("stale resource version must reject the update"); + + assert_eq!(error.code(), Code::Aborted); + assert!(rx.try_recv().is_err()); + assert!( + state + .store + .get_latest_policy("sb-rejected-policy") + .await + .unwrap() + .is_none() + ); + } + + #[tokio::test] + async fn committed_policy_update_publishes_complete_snapshot() { + let state = test_server_state().await; + let mut sandbox = test_sandbox( + "sb-published-policy", + "published-policy", + ProtoSandboxPolicy::default(), + Vec::new(), + ); + sandbox.spec.as_mut().unwrap().policy = None; + state.store.put_message(&sandbox).await.unwrap(); + + let (tx, mut rx) = tokio::sync::mpsc::channel(4); + let (shutdown_tx, _shutdown_rx) = tokio::sync::oneshot::channel(); + state.supervisor_sessions.register( + "sb-published-policy".to_string(), + "session-1".to_string(), + tx, + shutdown_tx, + ); + + handle_update_config( + &state, + with_user(Request::new(UpdateConfigRequest { + name: "published-policy".to_string(), + workspace: "default".to_string(), + policy: Some(test_policy_with_rule("published", "api.example.com")), + ..Default::default() + })), + ) + .await + .unwrap(); + + let persisted = state + .store + .get_latest_policy("sb-published-policy") + .await + .unwrap() + .expect("committed policy"); + let snapshot = tokio::time::timeout(std::time::Duration::from_secs(2), async { + loop { + let message = rx.recv().await.expect("configuration channel closed"); + let Some(openshell_core::proto::gateway_message::Payload::ConfigUpdate(update)) = + message.payload + else { + panic!("expected ConfigUpdate"); + }; + if let Some(openshell_core::proto::config_update::Component::SandboxConfig( + snapshot, + )) = update.component + { + break snapshot; + } + } + }) + .await + .expect("configuration publication timed out"); + assert_eq!(snapshot.version, u32::try_from(persisted.version).unwrap()); + assert_eq!(snapshot.policy_hash, persisted.policy_hash); + assert!(snapshot.policy.is_some()); + } + #[tokio::test] async fn update_config_accepts_sigv4_covered_by_endpointful_aws_profile() { let state = test_server_state().await; @@ -10687,23 +11034,68 @@ mod tests { .contains_key("_provider_work_github") ); - let persisted = state + assert!( + state + .store + .get_latest_policy("sb-jit") + .await + .unwrap() + .is_none(), + "snapshot reads must not create policy history" + ); + } + + #[tokio::test] + async fn legacy_policy_history_repair_is_idempotent() { + let state = test_server_state().await; + let policy = test_policy_with_rule("legacy", "legacy.example.com"); + state + .store + .put_message(&test_sandbox( + "sb-legacy-policy", + "legacy-policy", + policy.clone(), + Vec::new(), + )) + .await + .unwrap(); + + backfill_legacy_policy_history(&state).await.unwrap(); + let initial = state .store - .get_latest_policy("sb-jit") + .get_latest_policy("sb-legacy-policy") .await .unwrap() - .expect("sandbox policy should be lazily backfilled"); - let persisted_policy = ProtoSandboxPolicy::decode(persisted.policy_payload.as_slice()) - .expect("persisted sandbox policy should decode"); - assert!( - persisted_policy - .network_policies - .contains_key("sandbox_only") + .expect("legacy policy baseline"); + assert_eq!(initial.status, "loaded"); + state + .store + .update_policy_status("sb-legacy-policy", 1, "failed", Some("apply failed"), None) + .await + .unwrap(); + + backfill_legacy_policy_history(&state).await.unwrap(); + let repaired_again = state + .store + .get_latest_policy("sb-legacy-policy") + .await + .unwrap() + .expect("legacy policy baseline"); + assert_eq!(repaired_again.version, 1); + assert_eq!( + repaired_again.policy_hash, + deterministic_policy_hash(&policy) ); - assert!( - !persisted_policy - .network_policies - .contains_key("_provider_work_github") + assert_eq!(repaired_again.status, "failed"); + assert_eq!(repaired_again.load_error.as_deref(), Some("apply failed")); + assert_eq!( + state + .store + .list_policies("sb-legacy-policy", 10, 0) + .await + .unwrap() + .len(), + 1 ); } @@ -10828,24 +11220,14 @@ mod tests { assert_eq!(persisted_provider.r#type, provider.r#type); assert_eq!(persisted_provider.credentials, provider.credentials); - let persisted_policy = state - .store - .get_latest_policy("sb-custom-policy-update") - .await - .unwrap() - .expect("sandbox policy should be lazily backfilled"); - let persisted_policy = - ProtoSandboxPolicy::decode(persisted_policy.policy_payload.as_slice()) - .expect("persisted sandbox policy should decode"); - assert!( - persisted_policy - .network_policies - .contains_key("sandbox_only") - ); assert!( - !persisted_policy - .network_policies - .contains_key("_provider_work_custom") + state + .store + .get_latest_policy("sb-custom-policy-update") + .await + .unwrap() + .is_none(), + "config and profile reads must not create policy history" ); } @@ -20487,4 +20869,34 @@ mod tests { response.unwrap_err() ); } + + #[test] + fn provider_stream_values_expand_to_legacy_polling_response() { + let response = provider_environment_response(ProviderEnvironmentSnapshot { + provider_env_revision: 9, + values: vec![ + ProviderEnvironmentValue { + name: "REGION".into(), + value: "west".into(), + classification: ProviderEnvironmentValueClassification::NonSecret.into(), + ..Default::default() + }, + ProviderEnvironmentValue { + name: "TOKEN".into(), + value: "secret".into(), + expires_at_ms: Some(123), + classification: ProviderEnvironmentValueClassification::StaticCredential.into(), + static_credential_binding: Some(StaticCredentialBinding::default()), + }, + ], + dynamic_credentials: HashMap::new(), + }); + + assert_eq!(response.provider_env_revision, 9); + assert_eq!(response.environment["REGION"], "west"); + assert_eq!(response.environment["TOKEN"], "secret"); + assert_eq!(response.credential_expires_at_ms["TOKEN"], 123); + assert_eq!(response.non_secret_environment_keys, ["REGION"]); + assert!(response.static_credential_bindings.contains_key("TOKEN")); + } } diff --git a/crates/openshell-server/src/grpc/provider.rs b/crates/openshell-server/src/grpc/provider.rs index 06ed7aa4ff..7e0bb396cd 100644 --- a/crates/openshell-server/src/grpc/provider.rs +++ b/crates/openshell-server/src/grpc/provider.rs @@ -2462,6 +2462,21 @@ async fn authorize_and_resolve_profile_workspace( } } +fn publish_provider_change(state: &Arc, workspace: &str) { + if workspace.is_empty() { + crate::config_delivery::publish_all_connected( + state, + crate::config_delivery::ConfigComponents::ALL, + ); + } else { + crate::config_delivery::publish_workspace_components( + state, + workspace, + crate::config_delivery::ConfigComponents::ALL, + ); + } +} + pub(super) async fn handle_create_provider( state: &Arc, request: Request, @@ -2521,6 +2536,7 @@ pub(super) async fn handle_create_provider( LifecycleOperation::Create, TelemetryOutcome::Success, ); + publish_provider_change(state, &workspace); Ok(Response::new(ProviderResponse { provider: Some(provider), })) @@ -2743,6 +2759,7 @@ pub(super) async fn handle_import_provider_profiles( stored.profile.unwrap_or_default(), resource_version, )); + publish_provider_change(state, &workspace); } Ok(Response::new(ImportProviderProfilesResponse { @@ -2873,6 +2890,7 @@ pub(super) async fn handle_update_provider_profiles( } let resource_version = stored_profile_resource_version(&stored); let profile = profile_response_payload(stored.profile.unwrap_or_default(), resource_version); + publish_provider_change(state, &workspace); Ok(Response::new(UpdateProviderProfilesResponse { diagnostics: Vec::new(), @@ -2962,6 +2980,9 @@ pub(super) async fn handle_delete_provider_profile( .delete_by_name(StoredProviderProfile::object_type(), &workspace, &id) .await .map_err(|e| Status::internal(format!("delete provider profile failed: {e}")))?; + if deleted { + publish_provider_change(state, &workspace); + } Ok(Response::new(DeleteProviderProfileResponse { deleted })) } @@ -3742,6 +3763,7 @@ pub(super) async fn handle_update_provider( LifecycleOperation::Update, TelemetryOutcome::Success, ); + publish_provider_change(state, &workspace); Ok(Response::new(ProviderResponse { provider: Some(provider), })) @@ -4661,8 +4683,17 @@ pub(super) async fn handle_configure_provider_refresh( profile_workspace: String::new(), credential_handles: HashMap::new(), }; - update_provider_record_with_catalog(state.store.as_ref(), &catalog, &workspace, updated) - .await?; + let result = update_provider_record_with_catalog( + state.store.as_ref(), + &catalog, + &workspace, + updated, + ) + .await; + publish_provider_change(state, &workspace); + result?; + } else { + publish_provider_change(state, &workspace); } Ok(Response::new(ConfigureProviderRefreshResponse { @@ -4706,6 +4737,7 @@ pub(super) async fn handle_rotate_provider_credential( credential_key, ) .await?; + publish_provider_change(state, &workspace); Ok(Response::new(RotateProviderCredentialResponse { status: Some(crate::provider_refresh::refresh_status_from_state( @@ -4788,14 +4820,13 @@ pub(super) async fn handle_delete_provider_refresh( credential_key, ) .await?; - // A refresh co-manages the expiry of its primary credential and every pinned // additional output. Clear each expiry this refresh still owns, leaving // independently updated ones in place. The equality check and removal run // inside the CAS closure so they see the current stored provider — deciding // from the snapshot read above would let a concurrent rotation or provider // update land between the read and the write and then be clobbered (CWE-362). - if let Some(refresh_state) = existing_refresh_state + let expiry_cleanup = if let Some(refresh_state) = existing_refresh_state && refresh_state.expires_at_ms > 0 { let refresh_expires_at_ms = refresh_state.expires_at_ms; @@ -4812,8 +4843,15 @@ pub(super) async fn handle_delete_provider_refresh( Status::internal(format!( "clear refresh-owned credential expiries failed: {e}" )) - })?; + }) + .map(|_| ()) + } else { + Ok(()) + }; + if deleted_refresh_state { + publish_provider_change(state, &workspace); } + expiry_cleanup?; Ok(Response::new(DeleteProviderRefreshResponse { deleted: deleted_refresh_state, @@ -4854,6 +4892,9 @@ pub(super) async fn handle_delete_provider( LifecycleOperation::Delete, outcome, ); + if deleted { + publish_provider_change(state, &workspace); + } Ok(Response::new(DeleteProviderResponse { deleted })) } Err(err) => { diff --git a/crates/openshell-server/src/grpc/sandbox.rs b/crates/openshell-server/src/grpc/sandbox.rs index e0ff130ebc..c805e64e4f 100644 --- a/crates/openshell-server/src/grpc/sandbox.rs +++ b/crates/openshell-server/src/grpc/sandbox.rs @@ -1193,6 +1193,14 @@ pub(super) async fn handle_attach_sandbox_provider( .map_err(|e| super::persistence_error_to_status(e, "attach sandbox provider"))?; let attached = attached.load(Ordering::Relaxed); + if attached { + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); + state.sandbox_watch_bus.notify(&sandbox_id); + } info!( sandbox_name = %request.sandbox_name, @@ -1292,6 +1300,14 @@ pub(super) async fn handle_detach_sandbox_provider( .map_err(|e| super::persistence_error_to_status(e, "detach sandbox provider"))?; let detached = detached.load(Ordering::Relaxed); + if detached { + crate::config_delivery::publish_sandbox_components( + state, + &sandbox_id, + crate::config_delivery::ConfigComponents::SANDBOX_AND_PROVIDER, + ); + state.sandbox_watch_bus.notify(&sandbox_id); + } info!( sandbox_name = %request.sandbox_name, diff --git a/crates/openshell-server/src/lib.rs b/crates/openshell-server/src/lib.rs index 09bf280c9b..c22457e732 100644 --- a/crates/openshell-server/src/lib.rs +++ b/crates/openshell-server/src/lib.rs @@ -17,6 +17,7 @@ mod auth; pub mod certgen; pub mod cli; mod compute; +mod config_delivery; pub mod config_file; mod credentials; mod defaults; @@ -299,6 +300,11 @@ pub struct ServerState { /// Set once graceful gateway shutdown begins so stream handlers can /// distinguish expected transport closes from runtime failures. pub(crate) gateway_shutting_down: AtomicBool, + /// Per-sandbox scheduler for coalesced supervisor configuration delivery. + pub(crate) config_delivery_queue: config_delivery::ConfigDeliveryQueue, + + /// Routing boundary for local or remote supervisor configuration delivery. + pub(crate) supervisor_config_router: Arc, /// Validated built-in and operator-registered supervisor middleware. pub middleware_registry: Arc, @@ -354,6 +360,12 @@ fn is_benign_connection_close(error: &(dyn std::error::Error + 'static)) -> bool } impl ServerState { + /// Return the configuration delivery boundary for supervisor sessions. + #[must_use] + pub fn supervisor_config_router(&self) -> Arc { + Arc::clone(&self.supervisor_config_router) + } + /// Create new server state. #[must_use] #[allow(clippy::too_many_arguments)] @@ -402,6 +414,9 @@ impl ServerState { .oidc .as_ref() .map_or_else(String::new, |oidc| oidc.admin_role.clone()); + let supervisor_config_router: Arc = Arc::new( + config_delivery::LocalSupervisorConfigRouter::new(Arc::clone(&supervisor_sessions)), + ); Self { config, store, @@ -416,6 +431,8 @@ impl ServerState { settings_mutex: tokio::sync::Mutex::new(()), supervisor_sessions, gateway_shutting_down: AtomicBool::new(false), + config_delivery_queue: config_delivery::ConfigDeliveryQueue::default(), + supervisor_config_router, extension_mint_limiter: auth::extension_mint_limit::ExtensionMintLimiter::default(), middleware_registry: Arc::new(MiddlewareRegistry::default()), oidc_cache, @@ -678,6 +695,10 @@ pub(crate) async fn run_server( let state = Arc::new(state); + grpc::policy::backfill_legacy_policy_history(&state) + .await + .map_err(|error| Error::execution(error.to_string()))?; + // Reconcile local-driver running intent before watchers spawn so their // first snapshots observe the post-start backend state. Explicitly stopped // sandboxes remain stopped. diff --git a/crates/openshell-server/src/persistence/postgres.rs b/crates/openshell-server/src/persistence/postgres.rs index 449f8f6df3..209a5a8eff 100644 --- a/crates/openshell-server/src/persistence/postgres.rs +++ b/crates/openshell-server/src/persistence/postgres.rs @@ -847,6 +847,50 @@ VALUES ($1, $2, $3, $4, $5, $6, $7, $7, $8) Ok(()) } + pub async fn put_initial_policy_revision( + &self, + record: &PolicyRecord, + workspace: &str, + ) -> PersistenceResult<()> { + let wrapped_payload = policy_payload_from_record(record)?; + let mut tx = self.pool.begin().await.map_err(|e| map_db_error(&e))?; + + let sandbox_exists = sqlx::query( + "SELECT id FROM objects WHERE object_type = 'sandbox' AND id = $1 FOR UPDATE", + ) + .bind(&record.sandbox_id) + .fetch_optional(&mut *tx) + .await + .map_err(|e| map_db_error(&e))? + .is_some(); + + if sandbox_exists { + sqlx::query( + r" +INSERT INTO objects ( + object_type, id, scope, version, status, payload, created_at_ms, updated_at_ms, workspace +) +SELECT $1, $2, $3, 1, $4, $5, $6, $6, $7 +WHERE NOT EXISTS (SELECT 1 FROM objects WHERE object_type = $1 AND scope = $3) +ON CONFLICT DO NOTHING +", + ) + .bind(POLICY_OBJECT_TYPE) + .bind(&record.id) + .bind(&record.sandbox_id) + .bind(&record.status) + .bind(wrapped_payload) + .bind(record.created_at_ms) + .bind(workspace) + .execute(&mut *tx) + .await + .map_err(|e| map_db_error(&e))?; + } + + tx.commit().await.map_err(|e| map_db_error(&e))?; + Ok(()) + } + pub async fn put_policy_revision_atomic( &self, write: &AtomicPolicyRevisionWrite, diff --git a/crates/openshell-server/src/persistence/sqlite.rs b/crates/openshell-server/src/persistence/sqlite.rs index 5497b96c22..806e4a18fb 100644 --- a/crates/openshell-server/src/persistence/sqlite.rs +++ b/crates/openshell-server/src/persistence/sqlite.rs @@ -982,6 +982,36 @@ VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?7, ?8) Ok(()) } + pub async fn put_initial_policy_revision( + &self, + record: &PolicyRecord, + workspace: &str, + ) -> PersistenceResult<()> { + let wrapped_payload = policy_payload_from_record(record)?; + sqlx::query( + r#" +INSERT INTO "objects" ( + "object_type", "id", "scope", "version", "status", "payload", "created_at_ms", "updated_at_ms", "workspace" +) +SELECT ?1, ?2, ?3, 1, ?4, ?5, ?6, ?6, ?7 +WHERE EXISTS (SELECT 1 FROM "objects" WHERE "object_type" = 'sandbox' AND "id" = ?3) + AND NOT EXISTS (SELECT 1 FROM "objects" WHERE "object_type" = ?1 AND "scope" = ?3) +ON CONFLICT DO NOTHING +"#, + ) + .bind(POLICY_OBJECT_TYPE) + .bind(&record.id) + .bind(&record.sandbox_id) + .bind(&record.status) + .bind(wrapped_payload) + .bind(record.created_at_ms) + .bind(workspace) + .execute(&self.pool) + .await + .map_err(|e| map_db_error(&e))?; + Ok(()) + } + pub async fn put_policy_revision_atomic( &self, write: &AtomicPolicyRevisionWrite, diff --git a/crates/openshell-server/src/persistence/tests.rs b/crates/openshell-server/src/persistence/tests.rs index 169fa81538..31a824e800 100644 --- a/crates/openshell-server/src/persistence/tests.rs +++ b/crates/openshell-server/src/persistence/tests.rs @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -use super::{ObjectType, PersistenceError, Store, generate_name, test_store}; +use super::{ObjectType, PersistenceError, PolicyRecord, Store, generate_name, test_store}; use crate::policy_store::{AtomicPolicyRevisionWrite, PolicyStoreExt}; use openshell_core::proto::datamodel::v1::ObjectMeta as ProtoObjectMeta; use openshell_core::proto::{ObjectForTest, Sandbox, SandboxPolicy, SandboxSpec}; @@ -1049,6 +1049,85 @@ fn policy_test_sandbox(id: &str, name: &str) -> Sandbox { } } +#[tokio::test] +async fn initial_policy_history_is_insert_only() { + assert_initial_policy_history_is_insert_only(&test_store().await).await; +} + +#[tokio::test] +#[ignore = "requires OPENSHELL_TEST_POSTGRES_URL pointing to a test database"] +async fn postgres_initial_policy_history_is_insert_only() { + let url = std::env::var("OPENSHELL_TEST_POSTGRES_URL").expect("test database URL"); + let store = Store::connect(&url).await.unwrap(); + assert_initial_policy_history_is_insert_only(&store).await; +} + +async fn assert_initial_policy_history_is_insert_only(store: &Store) { + let id = uuid::Uuid::new_v4().to_string(); + let sandbox = policy_test_sandbox(&id, &id); + let record = PolicyRecord { + id: uuid::Uuid::new_v4().to_string(), + sandbox_id: id.clone(), + version: 1, + policy_payload: SandboxPolicy::default().encode_to_vec(), + policy_hash: "initial-hash".into(), + status: "loaded".into(), + load_error: None, + created_at_ms: 1, + loaded_at_ms: None, + provenance: StdHashMap::new(), + }; + + store + .put_initial_policy_revision(&record, "default") + .await + .unwrap(); + assert!(store.get_latest_policy(&id).await.unwrap().is_none()); + + store.put_message(&sandbox).await.unwrap(); + let (first, second) = tokio::join!( + store.put_initial_policy_revision(&record, "default"), + store.put_initial_policy_revision(&record, "default"), + ); + first.unwrap(); + second.unwrap(); + let initial = store.get_latest_policy(&id).await.unwrap().unwrap(); + assert_eq!(initial.status, "loaded"); + assert_eq!(initial.policy_hash, record.policy_hash); + assert_eq!(store.list_policies(&id, 10, 0).await.unwrap().len(), 1); + + store + .update_policy_status(&id, 1, "failed", Some("apply failed"), None) + .await + .unwrap(); + store + .put_initial_policy_revision(&record, "default") + .await + .unwrap(); + let failed = store.get_latest_policy(&id).await.unwrap().unwrap(); + assert_eq!(failed.status, "failed"); + assert_eq!(failed.load_error.as_deref(), Some("apply failed")); + + store + .put_policy_revision( + &uuid::Uuid::new_v4().to_string(), + &id, + "default", + 2, + &record.policy_payload, + "new-hash", + ) + .await + .unwrap(); + store + .put_initial_policy_revision(&record, "default") + .await + .unwrap(); + let latest = store.get_latest_policy(&id).await.unwrap().unwrap(); + assert_eq!(latest.version, 2); + assert_eq!(store.list_policies(&id, 10, 0).await.unwrap().len(), 2); +} + #[tokio::test] async fn policy_atomic_write_commits_revision_provenance_and_sandbox_projection() { let store = test_store().await; diff --git a/crates/openshell-server/src/policy_store.rs b/crates/openshell-server/src/policy_store.rs index bd044c8712..4eb78b25fa 100644 --- a/crates/openshell-server/src/policy_store.rs +++ b/crates/openshell-server/src/policy_store.rs @@ -96,6 +96,14 @@ pub fn project_policy_revision_onto_sandbox( } pub trait PolicyStoreExt { + /// Insert version-one policy history when the sandbox still has no policy + /// revisions. Existing history and apply status are left untouched. + async fn put_initial_policy_revision( + &self, + record: &PolicyRecord, + workspace: &str, + ) -> PersistenceResult<()>; + async fn put_policy_revision( &self, id: &str, @@ -211,6 +219,17 @@ pub trait PolicyStoreExt { } impl PolicyStoreExt for Store { + async fn put_initial_policy_revision( + &self, + record: &PolicyRecord, + workspace: &str, + ) -> PersistenceResult<()> { + match self { + Self::Postgres(store) => store.put_initial_policy_revision(record, workspace).await, + Self::Sqlite(store) => store.put_initial_policy_revision(record, workspace).await, + } + } + async fn put_policy_revision( &self, id: &str, diff --git a/crates/openshell-server/src/provider_refresh.rs b/crates/openshell-server/src/provider_refresh.rs index 11f46daafb..b5892ad32e 100644 --- a/crates/openshell-server/src/provider_refresh.rs +++ b/crates/openshell-server/src/provider_refresh.rs @@ -1839,14 +1839,25 @@ pub fn spawn_refresh_worker(state: std::sync::Arc, interval: ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); loop { ticker.tick().await; - if let Err(err) = run_refresh_worker_tick( + match run_refresh_worker_tick( state.store.as_ref(), Some(&state.credentials), Some(&state.compute), ) .await { - warn!(error = %err, "provider credential refresh worker tick failed"); + Ok(workspaces) => { + for workspace in workspaces { + crate::config_delivery::publish_workspace_components( + &state, + &workspace, + crate::config_delivery::ConfigComponents::ALL, + ); + } + } + Err(err) => { + warn!(error = %err, "provider credential refresh worker tick failed"); + } } } }); @@ -1865,7 +1876,8 @@ async fn run_refresh_worker_tick( store: &Store, credentials: Option<&crate::credentials::CredentialRuntime>, compute: Option<&crate::compute::ComputeRuntime>, -) -> Result<(), Status> { +) -> Result, Status> { + let mut changed_workspaces = std::collections::HashSet::new(); let now_ms = current_time_ms(); let states = list_all_refresh_states(store).await.inspect_err(|_| { crate::otel_tracing::mark_error(&tracing::Span::current()); @@ -1915,6 +1927,8 @@ async fn run_refresh_worker_tick( error = %err, "failed to finalize tombstoned provider refresh; retrying on the next sweep" ); + } else { + changed_workspaces.insert(state.object_workspace().to_string()); } continue; } @@ -1998,9 +2012,11 @@ async fn run_refresh_worker_tick( error = %err, "provider credential refresh failed" ); + } else { + changed_workspaces.insert(state.object_workspace().to_string()); } } - Ok(()) + Ok(changed_workspaces) } #[cfg(test)] diff --git a/crates/openshell-server/src/supervisor_session.rs b/crates/openshell-server/src/supervisor_session.rs index 24413f0f1b..c5668cc41e 100644 --- a/crates/openshell-server/src/supervisor_session.rs +++ b/crates/openshell-server/src/supervisor_session.rs @@ -7,21 +7,29 @@ use std::sync::atomic::Ordering; use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; +use metrics::counter; +use prost::Message; use tokio::sync::{mpsc, oneshot}; use tokio_stream::wrappers::ReceiverStream; use tonic::{Request, Response, Status}; use tracing::{debug, info, warn}; use uuid::Uuid; +use openshell_core::proto::SUPERVISOR_PROTOCOL_REVISION; use openshell_core::proto::{ - GatewayMessage, RelayFrame, RelayInit, RelayOpen, ReportMainProcessExitRequest, + ConfigUpdate, GatewayMessage, RelayFrame, RelayInit, RelayOpen, ReportMainProcessExitRequest, ReportMainProcessExitResponse, Sandbox, SandboxPhase, SessionAccepted, SshRelayTarget, - SupervisorMessage, gateway_message, relay_open, supervisor_message, + SupervisorMessage, config_update, gateway_message, relay_open, supervisor_message, }; use openshell_core::transport_errors::is_expected_transport_close_status; use crate::ServerState; use crate::auth::principal::Principal; +use crate::config_delivery::{ + DeliveryDisposition, MAX_SUPERVISOR_CONFIG_MESSAGE_BYTES, SupervisorConfigMessage, +}; +#[cfg(test)] +use crate::config_delivery::{LocalSupervisorConfigRouter, SupervisorConfigRouter}; const HEARTBEAT_INTERVAL_SECS: u32 = 15; const RELAY_PENDING_TIMEOUT: Duration = Duration::from_secs(10); @@ -52,6 +60,7 @@ struct LiveSession { /// removing a session that has since been superseded by a reconnect. session_id: String, tx: mpsc::Sender, + config_sequences: ConfigSequences, /// Fires when this session is superseded by a reconnect so the old session /// task can exit promptly — dropping its own `tx` clone and closing the /// outbound stream. Without this, a concurrent `open_relay` that grabbed @@ -65,6 +74,12 @@ struct LiveSession { connected_at: Instant, } +#[derive(Debug, Default)] +struct ConfigSequences { + sandbox_config: u64, + provider_environment: u64, +} + /// Holds a oneshot sender that will deliver the upgraded relay stream or a /// target-open failure reported by the supervisor. type RelayStreamSender = oneshot::Sender>; @@ -127,6 +142,7 @@ impl SupervisorSessionRegistry { sandbox_id, session_id, tx, + config_sequences: ConfigSequences::default(), shutdown, terminal_delivery_finalized: false, connected_at: Instant::now(), @@ -233,6 +249,65 @@ impl SupervisorSessionRegistry { true } + pub(crate) fn connected_sandbox_ids(&self) -> Vec { + self.sessions.lock().unwrap().keys().cloned().collect() + } + + pub(crate) fn deliver_config( + &self, + sandbox_id: &str, + message: SupervisorConfigMessage, + ) -> DeliveryDisposition { + let component_name = message.component_name(); + let mut sessions = self.sessions.lock().unwrap(); + let Some(session) = sessions.get_mut(sandbox_id) else { + return DeliveryDisposition::NoActiveSession; + }; + let sequence = match &message { + SupervisorConfigMessage::SandboxConfig(_) => { + &mut session.config_sequences.sandbox_config + } + SupervisorConfigMessage::ProviderEnvironment(_) => { + &mut session.config_sequences.provider_environment + } + }; + *sequence = sequence.saturating_add(1); + let component_sequence = *sequence; + + let component = match message { + SupervisorConfigMessage::SandboxConfig(snapshot) => { + config_update::Component::SandboxConfig(*snapshot) + } + SupervisorConfigMessage::ProviderEnvironment(snapshot) => { + config_update::Component::ProviderEnvironment(snapshot) + } + }; + let gateway_message = GatewayMessage { + payload: Some(gateway_message::Payload::ConfigUpdate(ConfigUpdate { + update_id: Uuid::new_v4().to_string(), + component_sequence, + component: Some(component), + })), + }; + + if gateway_message.encoded_len() > MAX_SUPERVISOR_CONFIG_MESSAGE_BYTES { + return DeliveryDisposition::PayloadTooLarge; + } + + match session.tx.try_send(gateway_message) { + Ok(()) => DeliveryDisposition::Enqueued, + Err(mpsc::error::TrySendError::Full(_)) => { + warn!( + sandbox_id = %sandbox_id, + component = component_name, + "supervisor configuration queue is full" + ); + DeliveryDisposition::QueueFull + } + Err(mpsc::error::TrySendError::Closed(_)) => DeliveryDisposition::SessionClosed, + } + } + pub fn is_current_session(&self, sandbox_id: &str, session_id: &str) -> bool { self.sessions .lock() @@ -480,17 +555,13 @@ pub fn spawn_relay_reaper(state: Arc, interval: Duration) { async fn require_persisted_sandbox( store: &Arc, sandbox_id: &str, -) -> Result<(), Status> { +) -> Result { let sandbox = store .get_message::(sandbox_id) .await .map_err(|err| Status::internal(format!("failed to load sandbox: {err}")))?; - if sandbox.is_none() { - return Err(Status::not_found("sandbox not found")); - } - - Ok(()) + sandbox.ok_or_else(|| Status::not_found("sandbox not found")) } // --------------------------------------------------------------------------- @@ -739,10 +810,35 @@ pub async fn handle_connect_supervisor( if sandbox_id.is_empty() { return Err(Status::invalid_argument("sandbox_id is required")); } + validate_protocol_revision(hello.protocol_revision)?; if let Some(principal) = principal.as_ref() { crate::auth::guard::ensure_sandbox_principal_scope(principal, &sandbox_id)?; } - require_persisted_sandbox(&state.store, &sandbox_id).await?; + let sandbox = require_persisted_sandbox(&state.store, &sandbox_id).await?; + + let bootstrap = match crate::config_delivery::build_config_bootstrap(state, &sandbox).await { + Ok(bootstrap) => { + counter!( + "openshell_supervisor_config_bootstrap_total", + "outcome" => "built" + ) + .increment(1); + Some(bootstrap) + } + Err(error) => { + counter!( + "openshell_supervisor_config_bootstrap_total", + "outcome" => "build_failed" + ) + .increment(1); + warn!( + sandbox_id = %sandbox_id, + error_code = ?error.code(), + "failed to build supervisor configuration bootstrap" + ); + None + } + }; let session_id = Uuid::new_v4().to_string(); info!( @@ -752,9 +848,35 @@ pub async fn handle_connect_supervisor( "supervisor session: accepted" ); - // Step 2: Create and register the outbound channel. + // Step 2: Queue SessionAccepted before the session becomes routable. This + // keeps a concurrent ConfigUpdate from becoming the first stream message. let (tx, rx) = mpsc::channel::(64); let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>(); + let mut accepted = GatewayMessage { + payload: Some(gateway_message::Payload::SessionAccepted(SessionAccepted { + session_id: session_id.clone(), + heartbeat_interval_secs: HEARTBEAT_INTERVAL_SECS, + bootstrap, + protocol_revision: SUPERVISOR_PROTOCOL_REVISION, + })), + }; + if accepted.encoded_len() > MAX_SUPERVISOR_CONFIG_MESSAGE_BYTES { + counter!( + "openshell_supervisor_config_bootstrap_total", + "outcome" => "payload_too_large" + ) + .increment(1); + let Some(gateway_message::Payload::SessionAccepted(accepted_payload)) = + accepted.payload.as_mut() + else { + unreachable!("constructed SessionAccepted payload") + }; + accepted_payload.bootstrap = None; + } + if tx.send(accepted).await.is_err() { + return Err(Status::internal("failed to send session accepted")); + } + let superseded = state.supervisor_sessions.register( sandbox_id.clone(), session_id.clone(), @@ -769,22 +891,6 @@ pub async fn handle_connect_supervisor( ); } - // Step 3: Send SessionAccepted. - let accepted = GatewayMessage { - payload: Some(gateway_message::Payload::SessionAccepted(SessionAccepted { - session_id: session_id.clone(), - heartbeat_interval_secs: HEARTBEAT_INTERVAL_SECS, - })), - }; - if tx.send(accepted).await.is_err() { - // Only evict ourselves — a faster reconnect may already have - // superseded this registration. - state - .supervisor_sessions - .remove_if_current(&sandbox_id, &session_id); - return Err(Status::internal("failed to send session accepted")); - } - if superseded { state .supervisor_sessions @@ -854,6 +960,16 @@ pub async fn handle_connect_supervisor( Ok(Response::new(stream)) } +fn validate_protocol_revision(supervisor_revision: u32) -> Result<(), Status> { + if supervisor_revision == SUPERVISOR_PROTOCOL_REVISION { + Ok(()) + } else { + Err(Status::failed_precondition(format!( + "supervisor protocol revision mismatch: gateway requires {SUPERVISOR_PROTOCOL_REVISION}, supervisor offered {supervisor_revision}" + ))) + } +} + pub async fn handle_report_main_process_exit( state: &Arc, request: Request, @@ -1016,6 +1132,22 @@ fn handle_supervisor_message( "supervisor session: relay closed by supervisor" ); } + Some(supervisor_message::Payload::ConfigUpdateResult(result)) => { + debug!( + sandbox_id = %sandbox_id, + session_id = %session_id, + component_sequence = result.component_sequence, + "supervisor session: ignoring configuration result while polling remains authoritative" + ); + } + Some(supervisor_message::Payload::ConfigBootstrapResult(result)) => { + debug!( + sandbox_id = %sandbox_id, + session_id = %session_id, + result_count = result.results.len(), + "supervisor session: ignoring bootstrap result while polling remains authoritative" + ); + } _ => { warn!( sandbox_id = %sandbox_id, @@ -1036,6 +1168,256 @@ mod tests { use crate::auth::identity::{Identity, IdentityProvider}; use crate::auth::principal::{SandboxIdentitySource, SandboxPrincipal, UserPrincipal}; use crate::persistence::Store; + use openshell_core::proto::{ + ProviderEnvironmentSnapshot, ProviderEnvironmentValue, SandboxConfigRevision, + SandboxConfigSnapshot, + }; + use prost::Message; + + #[test] + fn configuration_stream_messages_round_trip() { + let bootstrap = GatewayMessage { + payload: Some(gateway_message::Payload::SessionAccepted(SessionAccepted { + session_id: "session-1".into(), + heartbeat_interval_secs: 15, + bootstrap: Some(openshell_core::proto::ConfigBootstrap { + sandbox_config: Some(SandboxConfigSnapshot::default()), + provider_environment: Some(ProviderEnvironmentSnapshot::default()), + }), + protocol_revision: SUPERVISOR_PROTOCOL_REVISION, + })), + }; + let updates = [ + config_update::Component::SandboxConfig(SandboxConfigSnapshot::default()), + config_update::Component::ProviderEnvironment(ProviderEnvironmentSnapshot::default()), + ] + .into_iter() + .enumerate() + .map(|(index, component)| GatewayMessage { + payload: Some(gateway_message::Payload::ConfigUpdate(ConfigUpdate { + update_id: format!("update-{index}"), + component_sequence: u64::try_from(index + 1).unwrap(), + component: Some(component), + })), + }); + + for original in std::iter::once(bootstrap).chain(updates) { + let decoded = GatewayMessage::decode(original.encode_to_vec().as_slice()).unwrap(); + assert_eq!(decoded, original); + } + + let result = SupervisorMessage { + payload: Some(supervisor_message::Payload::ConfigUpdateResult( + openshell_core::proto::ConfigUpdateResult { + update_id: "update-1".into(), + component_sequence: 4, + result: Some(openshell_core::proto::ConfigComponentApplyResult { + component: openshell_core::proto::ConfigComponent::SandboxConfig.into(), + requested_revision: Some(openshell_core::proto::ConfigSnapshotRevision { + component: Some( + openshell_core::proto::config_snapshot_revision::Component::SandboxConfig( + SandboxConfigRevision { + config_revision: 7, + policy_version: 3, + ..Default::default() + }, + ), + ), + }), + applied_revision: Some(openshell_core::proto::ConfigSnapshotRevision { + component: Some( + openshell_core::proto::config_snapshot_revision::Component::SandboxConfig( + SandboxConfigRevision { + config_revision: 7, + policy_version: 3, + ..Default::default() + }, + ), + ), + }), + outcome: openshell_core::proto::ConfigApplyOutcome::Applied.into(), + failure: None, + }), + }, + )), + }; + let decoded = SupervisorMessage::decode(result.encode_to_vec().as_slice()).unwrap(); + assert_eq!(decoded, result); + } + + #[test] + fn supervisor_protocol_revision_must_match_exactly() { + assert!(validate_protocol_revision(SUPERVISOR_PROTOCOL_REVISION).is_ok()); + let error = validate_protocol_revision(SUPERVISOR_PROTOCOL_REVISION + 1).unwrap_err(); + assert_eq!(error.code(), tonic::Code::FailedPrecondition); + assert!(error.message().contains("revision mismatch")); + } + + #[tokio::test] + async fn config_router_reports_missing_session() { + let router = LocalSupervisorConfigRouter::new(Arc::new(SupervisorSessionRegistry::new())); + assert_eq!( + router + .deliver( + "missing", + SupervisorConfigMessage::SandboxConfig(Box::default()), + ) + .await, + DeliveryDisposition::NoActiveSession + ); + } + + #[tokio::test] + async fn config_router_assigns_sequences_per_component() { + let registry = Arc::new(SupervisorSessionRegistry::new()); + let router = LocalSupervisorConfigRouter::new(Arc::clone(®istry)); + let (tx, mut rx) = mpsc::channel(4); + let (shutdown_tx, _shutdown_rx) = oneshot::channel(); + registry.register("sb-1".into(), "session-1".into(), tx, shutdown_tx); + + assert_eq!( + router + .deliver( + "sb-1", + SupervisorConfigMessage::SandboxConfig(Box::default()), + ) + .await, + DeliveryDisposition::Enqueued + ); + assert_eq!( + router + .deliver( + "sb-1", + SupervisorConfigMessage::SandboxConfig(Box::default()), + ) + .await, + DeliveryDisposition::Enqueued + ); + assert_eq!( + router + .deliver( + "sb-1", + SupervisorConfigMessage::ProviderEnvironment( + ProviderEnvironmentSnapshot::default(), + ), + ) + .await, + DeliveryDisposition::Enqueued + ); + + let first = rx.recv().await.expect("first config update"); + let second = rx.recv().await.expect("second config update"); + let third = rx.recv().await.expect("provider config update"); + let sequence = |message: GatewayMessage| match message.payload { + Some(gateway_message::Payload::ConfigUpdate(update)) => update.component_sequence, + other => panic!("expected config update, got {other:?}"), + }; + assert_eq!(sequence(first), 1); + assert_eq!(sequence(second), 2); + assert_eq!(sequence(third), 1); + } + + #[tokio::test] + async fn config_router_uses_replacement_session() { + let registry = Arc::new(SupervisorSessionRegistry::new()); + let router = LocalSupervisorConfigRouter::new(Arc::clone(®istry)); + let (old_tx, mut old_rx) = mpsc::channel(2); + let (old_shutdown_tx, _old_shutdown_rx) = oneshot::channel(); + registry.register("sb-1".into(), "old-session".into(), old_tx, old_shutdown_tx); + + assert_eq!( + router + .deliver( + "sb-1", + SupervisorConfigMessage::SandboxConfig(Box::default()), + ) + .await, + DeliveryDisposition::Enqueued + ); + let old_update = old_rx.recv().await.expect("old-session config update"); + let Some(gateway_message::Payload::ConfigUpdate(old_update)) = old_update.payload else { + panic!("expected config update"); + }; + assert_eq!(old_update.component_sequence, 1); + + let (new_tx, mut new_rx) = mpsc::channel(1); + let (new_shutdown_tx, _new_shutdown_rx) = oneshot::channel(); + assert!(registry.register("sb-1".into(), "new-session".into(), new_tx, new_shutdown_tx,)); + + assert_eq!( + router + .deliver( + "sb-1", + SupervisorConfigMessage::SandboxConfig(Box::default()), + ) + .await, + DeliveryDisposition::Enqueued + ); + assert!(old_rx.try_recv().is_err()); + let new_update = new_rx.try_recv().expect("new-session config update"); + let Some(gateway_message::Payload::ConfigUpdate(new_update)) = new_update.payload else { + panic!("expected config update"); + }; + assert_eq!(new_update.component_sequence, 1); + } + + #[tokio::test] + async fn config_router_reports_full_and_closed_queues() { + let registry = Arc::new(SupervisorSessionRegistry::new()); + let router = LocalSupervisorConfigRouter::new(Arc::clone(®istry)); + let (tx, rx) = mpsc::channel(1); + tx.try_send(GatewayMessage::default()).unwrap(); + let (shutdown_tx, _shutdown_rx) = oneshot::channel(); + registry.register("sb-1".into(), "session-1".into(), tx, shutdown_tx); + assert_eq!( + router + .deliver( + "sb-1", + SupervisorConfigMessage::SandboxConfig(Box::default()), + ) + .await, + DeliveryDisposition::QueueFull + ); + + drop(rx); + assert_eq!( + router + .deliver( + "sb-1", + SupervisorConfigMessage::SandboxConfig(Box::default()), + ) + .await, + DeliveryDisposition::SessionClosed + ); + } + + #[tokio::test] + async fn config_router_rejects_oversized_messages() { + let registry = Arc::new(SupervisorSessionRegistry::new()); + let router = LocalSupervisorConfigRouter::new(Arc::clone(®istry)); + let (tx, mut rx) = mpsc::channel(1); + let (shutdown_tx, _shutdown_rx) = oneshot::channel(); + registry.register("sb-1".into(), "session-1".into(), tx, shutdown_tx); + + let snapshot = ProviderEnvironmentSnapshot { + values: vec![ProviderEnvironmentValue { + name: "TOKEN".into(), + value: "x".repeat(MAX_SUPERVISOR_CONFIG_MESSAGE_BYTES), + ..Default::default() + }], + ..Default::default() + }; + assert_eq!( + router + .deliver( + "sb-1", + SupervisorConfigMessage::ProviderEnvironment(snapshot), + ) + .await, + DeliveryDisposition::PayloadTooLarge + ); + assert!(rx.try_recv().is_err()); + } use tokio::io::{AsyncReadExt, AsyncWriteExt}; async fn test_store() -> Arc { diff --git a/crates/openshell-supervisor-process/src/supervisor_session.rs b/crates/openshell-supervisor-process/src/supervisor_session.rs index 98a3c0497b..2ee7fcfe95 100644 --- a/crates/openshell-supervisor-process/src/supervisor_session.rs +++ b/crates/openshell-supervisor-process/src/supervisor_session.rs @@ -17,6 +17,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; +use openshell_core::proto::SUPERVISOR_PROTOCOL_REVISION; use openshell_core::proto::open_shell_client::OpenShellClient; use openshell_core::proto::{ FinalizeMainProcessExitRequest, GatewayMessage, RelayFrame, RelayInit, RelayOpen, @@ -358,6 +359,7 @@ async fn run_single_session( payload: Some(supervisor_message::Payload::Hello(SupervisorHello { sandbox_id: config.sandbox_id.clone(), instance_id: config.instance_id.clone(), + protocol_revision: SUPERVISOR_PROTOCOL_REVISION, })), }) .await @@ -385,6 +387,7 @@ async fn run_single_session( }; let heartbeat_secs = accepted.heartbeat_interval_secs.max(5); + validate_gateway_protocol_revision(accepted.protocol_revision)?; let event = session_established_event( openshell_ocsf::ctx::ctx(), &config.endpoint, @@ -392,6 +395,15 @@ async fn run_single_session( heartbeat_secs, ); ocsf_emit!(event); + + if accepted.bootstrap.is_some() { + debug!( + sandbox_id = %config.sandbox_id, + session_id = %accepted.session_id, + "supervisor session: ignoring configuration bootstrap while polling remains active" + ); + } + // Main loop: receive gateway messages + send heartbeats. let mut heartbeat_interval = tokio::time::interval(Duration::from_secs(u64::from(heartbeat_secs))); @@ -436,6 +448,19 @@ async fn run_single_session( } } +fn validate_gateway_protocol_revision( + gateway_revision: u32, +) -> Result<(), Box> { + if gateway_revision == SUPERVISOR_PROTOCOL_REVISION { + Ok(()) + } else { + Err(format!( + "supervisor protocol revision mismatch: supervisor requires {SUPERVISOR_PROTOCOL_REVISION}, gateway offered {gateway_revision}" + ) + .into()) + } +} + /// Report the canonical process result and wait for durable handling. pub async fn report_main_process_exit( endpoint: &str, @@ -491,6 +516,15 @@ fn handle_gateway_message(msg: &GatewayMessage, context: &GatewayMessageContext< Some(gateway_message::Payload::Heartbeat(_)) => { // Gateway heartbeat — nothing to do. } + Some(gateway_message::Payload::ConfigUpdate(update)) => { + // Stage 1 accepts pushed configuration but leaves polling as the + // only path that changes runtime state. + debug!( + sandbox_id = %context.sandbox_id, + component_sequence = update.component_sequence, + "supervisor session: ignoring configuration update while polling remains active" + ); + } Some(gateway_message::Payload::RelayOpen(open)) => { let channel_id = open.channel_id.clone(); let relay_open = open.clone(); @@ -832,6 +866,14 @@ fn normalize_tcp_target_host(target: &TcpRelayTarget) -> Result mod target_tests { use super::*; + #[test] + fn gateway_protocol_revision_must_match_exactly() { + assert!(validate_gateway_protocol_revision(SUPERVISOR_PROTOCOL_REVISION).is_ok()); + let error = validate_gateway_protocol_revision(SUPERVISOR_PROTOCOL_REVISION + 1) + .expect_err("version skew must be rejected"); + assert!(error.to_string().contains("revision mismatch")); + } + fn tcp(host: &str, port: u32) -> TcpRelayTarget { TcpRelayTarget { host: host.to_string(), diff --git a/docs/reference/gateway-config.mdx b/docs/reference/gateway-config.mdx index 14cdb05ece..8aeb2281eb 100644 --- a/docs/reference/gateway-config.mdx +++ b/docs/reference/gateway-config.mdx @@ -106,7 +106,8 @@ disable_tls = false # Shared driver defaults. These inherit into [openshell.drivers.] tables # when the driver-specific table does not override them. default_image = "ghcr.io/nvidia/openshell-community/sandboxes/base:latest" -# Defaults to the gateway version; override to pin a specific build. +# Defaults to the gateway version. Custom builds must match the gateway's +# internal supervisor protocol revision; mismatched peers reject the session. # supervisor_image = "ghcr.io/nvidia/openshell/supervisor:" client_tls_secret_name = "openshell-client-tls" service_account_name = "openshell-sandbox" diff --git a/proto/openshell.proto b/proto/openshell.proto index c2051f94b8..000e6023b0 100644 --- a/proto/openshell.proto +++ b/proto/openshell.proto @@ -512,9 +512,10 @@ 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. Peers must report the same exact protocol_revision during the + // handshake. 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" @@ -2168,6 +2169,30 @@ message GetSandboxProviderEnvironmentResponse { repeated string non_secret_environment_keys = 6; } +enum ProviderEnvironmentValueClassification { + PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_UNSPECIFIED = 0; + PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_NON_SECRET = 1; + PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_STATIC_CREDENTIAL = 2; +} + +// One environment value and all metadata that shares its key. +message ProviderEnvironmentValue { + string name = 1; + string value = 2 [(openshell.options.v1.secret) = true]; + optional int64 expires_at_ms = 3; + ProviderEnvironmentValueClassification classification = 4; + StaticCredentialBinding static_credential_binding = 5; +} + +// Complete provider environment state delivered to a supervisor. Dynamic +// credentials are endpoint selectors rather than environment values and stay +// in their own collection. +message ProviderEnvironmentSnapshot { + uint64 provider_env_revision = 1; + repeated ProviderEnvironmentValue values = 2; + map dynamic_credentials = 3; +} + message ExchangeProviderSubjectTokenRequest { // The sandbox ID. Must match the authenticated sandbox principal. string sandbox_id = 1; @@ -2429,6 +2454,9 @@ message GetSandboxLogsResponse { // Supervisor session messages // --------------------------------------------------------------------------- +// These messages form an internal, version-locked deployment protocol between +// the gateway and the supervisor. They are not a public sandbox client API. + // Envelope for supervisor-to-gateway messages on the ConnectSupervisor stream. message SupervisorMessage { oneof payload { @@ -2436,6 +2464,8 @@ message SupervisorMessage { SupervisorHeartbeat heartbeat = 2; RelayOpenResult relay_open_result = 3; RelayClose relay_close = 4; + ConfigUpdateResult config_update_result = 5; + ConfigBootstrapResult config_bootstrap_result = 6; } } @@ -2447,6 +2477,7 @@ message GatewayMessage { GatewayHeartbeat heartbeat = 3; RelayOpen relay_open = 4; RelayClose relay_close = 5; + ConfigUpdate config_update = 6; } } @@ -2456,6 +2487,8 @@ message SupervisorHello { string sandbox_id = 1; // Supervisor instance ID (e.g. boot id or process epoch). string instance_id = 2; + // Exact internal stream protocol revision implemented by this supervisor. + uint32 protocol_revision = 3; } // Gateway accepts the supervisor session. @@ -2464,6 +2497,99 @@ message SessionAccepted { string session_id = 1; // Recommended heartbeat interval in seconds. uint32 heartbeat_interval_secs = 2; + // Complete gateway-owned configuration. During the staged rollout this may + // be omitted only when the gateway cannot build the projection. + ConfigBootstrap bootstrap = 3; + // Exact internal stream protocol revision implemented by this gateway. + uint32 protocol_revision = 4; +} + +// Complete gateway-owned configuration for a supervisor session. +message ConfigBootstrap { + openshell.sandbox.v1.SandboxConfigSnapshot sandbox_config = 1; + ProviderEnvironmentSnapshot provider_environment = 2; +} + +// A complete replacement snapshot for exactly one configuration component. +message ConfigUpdate { + // Opaque non-empty identifier scoped to the active supervisor session. + string update_id = 1; + // Monotonic within one session and component. Snapshot revisions are + // content identities and must only be compared for equality. + uint64 component_sequence = 2; + oneof component { + openshell.sandbox.v1.SandboxConfigSnapshot sandbox_config = 3; + ProviderEnvironmentSnapshot provider_environment = 4; + } +} + +enum ConfigComponent { + CONFIG_COMPONENT_UNSPECIFIED = 0; + CONFIG_COMPONENT_SANDBOX_CONFIG = 1; + CONFIG_COMPONENT_PROVIDER_ENVIRONMENT = 2; +} + +// Identifies one component snapshot revision. Revisions are equality tokens, +// not members of one shared ordering domain. +message ConfigSnapshotRevision { + oneof component { + SandboxConfigRevision sandbox_config = 1; + uint64 provider_environment = 2; + } +} + +// Identity needed to correlate effective sandbox configuration with the +// policy-history row whose apply status the gateway records. +message SandboxConfigRevision { + uint64 config_revision = 1; + uint32 policy_version = 2; + openshell.sandbox.v1.PolicySource policy_source = 3; + uint32 global_policy_version = 4; +} + +enum ConfigApplyOutcome { + CONFIG_APPLY_OUTCOME_UNSPECIFIED = 0; + CONFIG_APPLY_OUTCOME_APPLIED = 1; + CONFIG_APPLY_OUTCOME_IGNORED_DUPLICATE = 2; + CONFIG_APPLY_OUTCOME_IGNORED_STALE = 3; + CONFIG_APPLY_OUTCOME_RETAINED_LOCAL_OVERRIDE = 4; + CONFIG_APPLY_OUTCOME_DEGRADED = 5; + CONFIG_APPLY_OUTCOME_FAILED_RETAINED_LAST_KNOWN_GOOD = 6; + CONFIG_APPLY_OUTCOME_FAILED_CLOSED = 7; + CONFIG_APPLY_OUTCOME_UNSUPPORTED = 8; +} + +// Sanitized application failure. Messages must not contain configuration +// payloads, credentials, or provider values. +message ConfigApplyFailure { + string code = 1; + string message = 2; + bool retryable = 3; +} + +message ConfigComponentApplyResult { + ConfigComponent component = 1; + // Revision extracted from the received snapshot. + ConfigSnapshotRevision requested_revision = 2; + // Revision active after this attempt. Omitted when the received snapshot + // was not installed or a local override has no gateway revision. + ConfigSnapshotRevision applied_revision = 3; + ConfigApplyOutcome outcome = 4; + ConfigApplyFailure failure = 5; +} + +// Application result for one ConfigUpdate. +message ConfigUpdateResult { + // Echoes ConfigUpdate.update_id for session-local correlation. + string update_id = 1; + // Echoes ConfigUpdate.component_sequence. + uint64 component_sequence = 2; + ConfigComponentApplyResult result = 3; +} + +// Aggregate application result for the SessionAccepted bootstrap. +message ConfigBootstrapResult { + repeated ConfigComponentApplyResult results = 1; } // Gateway rejects the supervisor session. diff --git a/proto/sandbox.proto b/proto/sandbox.proto index c2b61d0b3a..620c973798 100644 --- a/proto/sandbox.proto +++ b/proto/sandbox.proto @@ -356,13 +356,29 @@ message EffectiveSetting { SettingScope scope = 2; } -// Source used for the policy payload in GetSandboxConfigResponse. +// Source used for a sandbox configuration payload. enum PolicySource { POLICY_SOURCE_UNSPECIFIED = 0; POLICY_SOURCE_SANDBOX = 1; POLICY_SOURCE_GLOBAL = 2; } +// Complete effective sandbox configuration delivered to a supervisor. +message SandboxConfigSnapshot { + SandboxPolicy policy = 1; + uint32 version = 2; + string policy_hash = 3; + map settings = 4; + uint64 config_revision = 5; + PolicySource policy_source = 6; + uint32 global_policy_version = 7; + uint64 provider_env_revision = 8; + repeated SupervisorMiddlewareService supervisor_middleware_services = 9; + string workspace = 10; + string policy_validation_failure_mode = 11; + bool extension_authentication_enabled = 12; +} + // Response containing effective sandbox settings and policy. message GetSandboxConfigResponse { // The sandbox policy configuration. diff --git a/sdk/go/proto/openshellv1/openshell.pb.go b/sdk/go/proto/openshellv1/openshell.pb.go index 3c977cbb76..97ea45abf7 100644 --- a/sdk/go/proto/openshellv1/openshell.pb.go +++ b/sdk/go/proto/openshellv1/openshell.pb.go @@ -281,6 +281,55 @@ func (ProviderProfileCategory) EnumDescriptor() ([]byte, []int) { return file_openshell_proto_rawDescGZIP(), []int{3} } +type ProviderEnvironmentValueClassification int32 + +const ( + ProviderEnvironmentValueClassification_PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_UNSPECIFIED ProviderEnvironmentValueClassification = 0 + ProviderEnvironmentValueClassification_PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_NON_SECRET ProviderEnvironmentValueClassification = 1 + ProviderEnvironmentValueClassification_PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_STATIC_CREDENTIAL ProviderEnvironmentValueClassification = 2 +) + +// Enum value maps for ProviderEnvironmentValueClassification. +var ( + ProviderEnvironmentValueClassification_name = map[int32]string{ + 0: "PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_UNSPECIFIED", + 1: "PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_NON_SECRET", + 2: "PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_STATIC_CREDENTIAL", + } + ProviderEnvironmentValueClassification_value = map[string]int32{ + "PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_UNSPECIFIED": 0, + "PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_NON_SECRET": 1, + "PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_STATIC_CREDENTIAL": 2, + } +) + +func (x ProviderEnvironmentValueClassification) Enum() *ProviderEnvironmentValueClassification { + p := new(ProviderEnvironmentValueClassification) + *p = x + return p +} + +func (x ProviderEnvironmentValueClassification) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ProviderEnvironmentValueClassification) Descriptor() protoreflect.EnumDescriptor { + return file_openshell_proto_enumTypes[4].Descriptor() +} + +func (ProviderEnvironmentValueClassification) Type() protoreflect.EnumType { + return &file_openshell_proto_enumTypes[4] +} + +func (x ProviderEnvironmentValueClassification) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ProviderEnvironmentValueClassification.Descriptor instead. +func (ProviderEnvironmentValueClassification) EnumDescriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{4} +} + // Policy load status. type PolicyStatus int32 @@ -327,11 +376,11 @@ func (x PolicyStatus) String() string { } func (PolicyStatus) Descriptor() protoreflect.EnumDescriptor { - return file_openshell_proto_enumTypes[4].Descriptor() + return file_openshell_proto_enumTypes[5].Descriptor() } func (PolicyStatus) Type() protoreflect.EnumType { - return &file_openshell_proto_enumTypes[4] + return &file_openshell_proto_enumTypes[5] } func (x PolicyStatus) Number() protoreflect.EnumNumber { @@ -340,7 +389,123 @@ func (x PolicyStatus) Number() protoreflect.EnumNumber { // Deprecated: Use PolicyStatus.Descriptor instead. func (PolicyStatus) EnumDescriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{4} + return file_openshell_proto_rawDescGZIP(), []int{5} +} + +type ConfigComponent int32 + +const ( + ConfigComponent_CONFIG_COMPONENT_UNSPECIFIED ConfigComponent = 0 + ConfigComponent_CONFIG_COMPONENT_SANDBOX_CONFIG ConfigComponent = 1 + ConfigComponent_CONFIG_COMPONENT_PROVIDER_ENVIRONMENT ConfigComponent = 2 +) + +// Enum value maps for ConfigComponent. +var ( + ConfigComponent_name = map[int32]string{ + 0: "CONFIG_COMPONENT_UNSPECIFIED", + 1: "CONFIG_COMPONENT_SANDBOX_CONFIG", + 2: "CONFIG_COMPONENT_PROVIDER_ENVIRONMENT", + } + ConfigComponent_value = map[string]int32{ + "CONFIG_COMPONENT_UNSPECIFIED": 0, + "CONFIG_COMPONENT_SANDBOX_CONFIG": 1, + "CONFIG_COMPONENT_PROVIDER_ENVIRONMENT": 2, + } +) + +func (x ConfigComponent) Enum() *ConfigComponent { + p := new(ConfigComponent) + *p = x + return p +} + +func (x ConfigComponent) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ConfigComponent) Descriptor() protoreflect.EnumDescriptor { + return file_openshell_proto_enumTypes[6].Descriptor() +} + +func (ConfigComponent) Type() protoreflect.EnumType { + return &file_openshell_proto_enumTypes[6] +} + +func (x ConfigComponent) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ConfigComponent.Descriptor instead. +func (ConfigComponent) EnumDescriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{6} +} + +type ConfigApplyOutcome int32 + +const ( + ConfigApplyOutcome_CONFIG_APPLY_OUTCOME_UNSPECIFIED ConfigApplyOutcome = 0 + ConfigApplyOutcome_CONFIG_APPLY_OUTCOME_APPLIED ConfigApplyOutcome = 1 + ConfigApplyOutcome_CONFIG_APPLY_OUTCOME_IGNORED_DUPLICATE ConfigApplyOutcome = 2 + ConfigApplyOutcome_CONFIG_APPLY_OUTCOME_IGNORED_STALE ConfigApplyOutcome = 3 + ConfigApplyOutcome_CONFIG_APPLY_OUTCOME_RETAINED_LOCAL_OVERRIDE ConfigApplyOutcome = 4 + ConfigApplyOutcome_CONFIG_APPLY_OUTCOME_DEGRADED ConfigApplyOutcome = 5 + ConfigApplyOutcome_CONFIG_APPLY_OUTCOME_FAILED_RETAINED_LAST_KNOWN_GOOD ConfigApplyOutcome = 6 + ConfigApplyOutcome_CONFIG_APPLY_OUTCOME_FAILED_CLOSED ConfigApplyOutcome = 7 + ConfigApplyOutcome_CONFIG_APPLY_OUTCOME_UNSUPPORTED ConfigApplyOutcome = 8 +) + +// Enum value maps for ConfigApplyOutcome. +var ( + ConfigApplyOutcome_name = map[int32]string{ + 0: "CONFIG_APPLY_OUTCOME_UNSPECIFIED", + 1: "CONFIG_APPLY_OUTCOME_APPLIED", + 2: "CONFIG_APPLY_OUTCOME_IGNORED_DUPLICATE", + 3: "CONFIG_APPLY_OUTCOME_IGNORED_STALE", + 4: "CONFIG_APPLY_OUTCOME_RETAINED_LOCAL_OVERRIDE", + 5: "CONFIG_APPLY_OUTCOME_DEGRADED", + 6: "CONFIG_APPLY_OUTCOME_FAILED_RETAINED_LAST_KNOWN_GOOD", + 7: "CONFIG_APPLY_OUTCOME_FAILED_CLOSED", + 8: "CONFIG_APPLY_OUTCOME_UNSUPPORTED", + } + ConfigApplyOutcome_value = map[string]int32{ + "CONFIG_APPLY_OUTCOME_UNSPECIFIED": 0, + "CONFIG_APPLY_OUTCOME_APPLIED": 1, + "CONFIG_APPLY_OUTCOME_IGNORED_DUPLICATE": 2, + "CONFIG_APPLY_OUTCOME_IGNORED_STALE": 3, + "CONFIG_APPLY_OUTCOME_RETAINED_LOCAL_OVERRIDE": 4, + "CONFIG_APPLY_OUTCOME_DEGRADED": 5, + "CONFIG_APPLY_OUTCOME_FAILED_RETAINED_LAST_KNOWN_GOOD": 6, + "CONFIG_APPLY_OUTCOME_FAILED_CLOSED": 7, + "CONFIG_APPLY_OUTCOME_UNSUPPORTED": 8, + } +) + +func (x ConfigApplyOutcome) Enum() *ConfigApplyOutcome { + p := new(ConfigApplyOutcome) + *p = x + return p +} + +func (x ConfigApplyOutcome) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ConfigApplyOutcome) Descriptor() protoreflect.EnumDescriptor { + return file_openshell_proto_enumTypes[7].Descriptor() +} + +func (ConfigApplyOutcome) Type() protoreflect.EnumType { + return &file_openshell_proto_enumTypes[7] +} + +func (x ConfigApplyOutcome) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ConfigApplyOutcome.Descriptor instead. +func (ConfigApplyOutcome) EnumDescriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{7} } // Service status enum. @@ -380,11 +545,11 @@ func (x ServiceStatus) String() string { } func (ServiceStatus) Descriptor() protoreflect.EnumDescriptor { - return file_openshell_proto_enumTypes[5].Descriptor() + return file_openshell_proto_enumTypes[8].Descriptor() } func (ServiceStatus) Type() protoreflect.EnumType { - return &file_openshell_proto_enumTypes[5] + return &file_openshell_proto_enumTypes[8] } func (x ServiceStatus) Number() protoreflect.EnumNumber { @@ -393,7 +558,7 @@ func (x ServiceStatus) Number() protoreflect.EnumNumber { // Deprecated: Use ServiceStatus.Descriptor instead. func (ServiceStatus) EnumDescriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{5} + return file_openshell_proto_rawDescGZIP(), []int{8} } // Workspace-scoped role for members. @@ -430,11 +595,11 @@ func (x WorkspaceRole) String() string { } func (WorkspaceRole) Descriptor() protoreflect.EnumDescriptor { - return file_openshell_proto_enumTypes[6].Descriptor() + return file_openshell_proto_enumTypes[9].Descriptor() } func (WorkspaceRole) Type() protoreflect.EnumType { - return &file_openshell_proto_enumTypes[6] + return &file_openshell_proto_enumTypes[9] } func (x WorkspaceRole) Number() protoreflect.EnumNumber { @@ -443,7 +608,7 @@ func (x WorkspaceRole) Number() protoreflect.EnumNumber { // Deprecated: Use WorkspaceRole.Descriptor instead. func (WorkspaceRole) EnumDescriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{6} + return file_openshell_proto_rawDescGZIP(), []int{9} } // Stable recovery action for the most recent provider credential refresh @@ -489,11 +654,11 @@ func (x ProviderCredentialRefreshRecoveryAction) String() string { } func (ProviderCredentialRefreshRecoveryAction) Descriptor() protoreflect.EnumDescriptor { - return file_openshell_proto_enumTypes[7].Descriptor() + return file_openshell_proto_enumTypes[10].Descriptor() } func (ProviderCredentialRefreshRecoveryAction) Type() protoreflect.EnumType { - return &file_openshell_proto_enumTypes[7] + return &file_openshell_proto_enumTypes[10] } func (x ProviderCredentialRefreshRecoveryAction) Number() protoreflect.EnumNumber { @@ -502,7 +667,7 @@ func (x ProviderCredentialRefreshRecoveryAction) Number() protoreflect.EnumNumbe // Deprecated: Use ProviderCredentialRefreshRecoveryAction.Descriptor instead. func (ProviderCredentialRefreshRecoveryAction) EnumDescriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{7} + return file_openshell_proto_rawDescGZIP(), []int{10} } // IssueSandboxToken request. Empty body; identity is established by the @@ -9138,6 +9303,146 @@ func (x *GetSandboxProviderEnvironmentResponse) GetNonSecretEnvironmentKeys() [] return nil } +// One environment value and all metadata that shares its key. +type ProviderEnvironmentValue struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + ExpiresAtMs *int64 `protobuf:"varint,3,opt,name=expires_at_ms,json=expiresAtMs,proto3,oneof" json:"expires_at_ms,omitempty"` + Classification ProviderEnvironmentValueClassification `protobuf:"varint,4,opt,name=classification,proto3,enum=openshell.v1.ProviderEnvironmentValueClassification" json:"classification,omitempty"` + StaticCredentialBinding *StaticCredentialBinding `protobuf:"bytes,5,opt,name=static_credential_binding,json=staticCredentialBinding,proto3" json:"static_credential_binding,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProviderEnvironmentValue) Reset() { + *x = ProviderEnvironmentValue{} + mi := &file_openshell_proto_msgTypes[128] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProviderEnvironmentValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProviderEnvironmentValue) ProtoMessage() {} + +func (x *ProviderEnvironmentValue) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[128] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProviderEnvironmentValue.ProtoReflect.Descriptor instead. +func (*ProviderEnvironmentValue) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{128} +} + +func (x *ProviderEnvironmentValue) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ProviderEnvironmentValue) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *ProviderEnvironmentValue) GetExpiresAtMs() int64 { + if x != nil && x.ExpiresAtMs != nil { + return *x.ExpiresAtMs + } + return 0 +} + +func (x *ProviderEnvironmentValue) GetClassification() ProviderEnvironmentValueClassification { + if x != nil { + return x.Classification + } + return ProviderEnvironmentValueClassification_PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_UNSPECIFIED +} + +func (x *ProviderEnvironmentValue) GetStaticCredentialBinding() *StaticCredentialBinding { + if x != nil { + return x.StaticCredentialBinding + } + return nil +} + +// Complete provider environment state delivered to a supervisor. Dynamic +// credentials are endpoint selectors rather than environment values and stay +// in their own collection. +type ProviderEnvironmentSnapshot struct { + state protoimpl.MessageState `protogen:"open.v1"` + ProviderEnvRevision uint64 `protobuf:"varint,1,opt,name=provider_env_revision,json=providerEnvRevision,proto3" json:"provider_env_revision,omitempty"` + Values []*ProviderEnvironmentValue `protobuf:"bytes,2,rep,name=values,proto3" json:"values,omitempty"` + DynamicCredentials map[string]*ProviderProfileCredential `protobuf:"bytes,3,rep,name=dynamic_credentials,json=dynamicCredentials,proto3" json:"dynamic_credentials,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProviderEnvironmentSnapshot) Reset() { + *x = ProviderEnvironmentSnapshot{} + mi := &file_openshell_proto_msgTypes[129] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProviderEnvironmentSnapshot) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProviderEnvironmentSnapshot) ProtoMessage() {} + +func (x *ProviderEnvironmentSnapshot) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[129] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProviderEnvironmentSnapshot.ProtoReflect.Descriptor instead. +func (*ProviderEnvironmentSnapshot) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{129} +} + +func (x *ProviderEnvironmentSnapshot) GetProviderEnvRevision() uint64 { + if x != nil { + return x.ProviderEnvRevision + } + return 0 +} + +func (x *ProviderEnvironmentSnapshot) GetValues() []*ProviderEnvironmentValue { + if x != nil { + return x.Values + } + return nil +} + +func (x *ProviderEnvironmentSnapshot) GetDynamicCredentials() map[string]*ProviderProfileCredential { + if x != nil { + return x.DynamicCredentials + } + return nil +} + type ExchangeProviderSubjectTokenRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // The sandbox ID. Must match the authenticated sandbox principal. @@ -9155,7 +9460,7 @@ type ExchangeProviderSubjectTokenRequest struct { func (x *ExchangeProviderSubjectTokenRequest) Reset() { *x = ExchangeProviderSubjectTokenRequest{} - mi := &file_openshell_proto_msgTypes[128] + mi := &file_openshell_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9167,7 +9472,7 @@ func (x *ExchangeProviderSubjectTokenRequest) String() string { func (*ExchangeProviderSubjectTokenRequest) ProtoMessage() {} func (x *ExchangeProviderSubjectTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[128] + mi := &file_openshell_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9180,7 +9485,7 @@ func (x *ExchangeProviderSubjectTokenRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use ExchangeProviderSubjectTokenRequest.ProtoReflect.Descriptor instead. func (*ExchangeProviderSubjectTokenRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{128} + return file_openshell_proto_rawDescGZIP(), []int{130} } func (x *ExchangeProviderSubjectTokenRequest) GetSandboxId() string { @@ -9222,7 +9527,7 @@ type ExchangeProviderSubjectTokenResponse struct { func (x *ExchangeProviderSubjectTokenResponse) Reset() { *x = ExchangeProviderSubjectTokenResponse{} - mi := &file_openshell_proto_msgTypes[129] + mi := &file_openshell_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9234,7 +9539,7 @@ func (x *ExchangeProviderSubjectTokenResponse) String() string { func (*ExchangeProviderSubjectTokenResponse) ProtoMessage() {} func (x *ExchangeProviderSubjectTokenResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[129] + mi := &file_openshell_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9247,7 +9552,7 @@ func (x *ExchangeProviderSubjectTokenResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use ExchangeProviderSubjectTokenResponse.ProtoReflect.Descriptor instead. func (*ExchangeProviderSubjectTokenResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{129} + return file_openshell_proto_rawDescGZIP(), []int{131} } func (x *ExchangeProviderSubjectTokenResponse) GetAccessToken() string { @@ -9318,7 +9623,7 @@ type UpdateConfigRequest struct { func (x *UpdateConfigRequest) Reset() { *x = UpdateConfigRequest{} - mi := &file_openshell_proto_msgTypes[130] + mi := &file_openshell_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9330,7 +9635,7 @@ func (x *UpdateConfigRequest) String() string { func (*UpdateConfigRequest) ProtoMessage() {} func (x *UpdateConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[130] + mi := &file_openshell_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9343,7 +9648,7 @@ func (x *UpdateConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateConfigRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{130} + return file_openshell_proto_rawDescGZIP(), []int{132} } func (x *UpdateConfigRequest) GetName() string { @@ -9433,7 +9738,7 @@ type PolicyMergeOperation struct { func (x *PolicyMergeOperation) Reset() { *x = PolicyMergeOperation{} - mi := &file_openshell_proto_msgTypes[131] + mi := &file_openshell_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9445,7 +9750,7 @@ func (x *PolicyMergeOperation) String() string { func (*PolicyMergeOperation) ProtoMessage() {} func (x *PolicyMergeOperation) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[131] + mi := &file_openshell_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9458,7 +9763,7 @@ func (x *PolicyMergeOperation) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicyMergeOperation.ProtoReflect.Descriptor instead. func (*PolicyMergeOperation) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{131} + return file_openshell_proto_rawDescGZIP(), []int{133} } func (x *PolicyMergeOperation) GetOperation() isPolicyMergeOperation_Operation { @@ -9572,7 +9877,7 @@ type AddNetworkRule struct { func (x *AddNetworkRule) Reset() { *x = AddNetworkRule{} - mi := &file_openshell_proto_msgTypes[132] + mi := &file_openshell_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9584,7 +9889,7 @@ func (x *AddNetworkRule) String() string { func (*AddNetworkRule) ProtoMessage() {} func (x *AddNetworkRule) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[132] + mi := &file_openshell_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9597,7 +9902,7 @@ func (x *AddNetworkRule) ProtoReflect() protoreflect.Message { // Deprecated: Use AddNetworkRule.ProtoReflect.Descriptor instead. func (*AddNetworkRule) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{132} + return file_openshell_proto_rawDescGZIP(), []int{134} } func (x *AddNetworkRule) GetRuleName() string { @@ -9625,7 +9930,7 @@ type RemoveNetworkEndpoint struct { func (x *RemoveNetworkEndpoint) Reset() { *x = RemoveNetworkEndpoint{} - mi := &file_openshell_proto_msgTypes[133] + mi := &file_openshell_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9637,7 +9942,7 @@ func (x *RemoveNetworkEndpoint) String() string { func (*RemoveNetworkEndpoint) ProtoMessage() {} func (x *RemoveNetworkEndpoint) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[133] + mi := &file_openshell_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9650,7 +9955,7 @@ func (x *RemoveNetworkEndpoint) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveNetworkEndpoint.ProtoReflect.Descriptor instead. func (*RemoveNetworkEndpoint) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{133} + return file_openshell_proto_rawDescGZIP(), []int{135} } func (x *RemoveNetworkEndpoint) GetRuleName() string { @@ -9683,7 +9988,7 @@ type RemoveNetworkRule struct { func (x *RemoveNetworkRule) Reset() { *x = RemoveNetworkRule{} - mi := &file_openshell_proto_msgTypes[134] + mi := &file_openshell_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9695,7 +10000,7 @@ func (x *RemoveNetworkRule) String() string { func (*RemoveNetworkRule) ProtoMessage() {} func (x *RemoveNetworkRule) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[134] + mi := &file_openshell_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9708,7 +10013,7 @@ func (x *RemoveNetworkRule) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveNetworkRule.ProtoReflect.Descriptor instead. func (*RemoveNetworkRule) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{134} + return file_openshell_proto_rawDescGZIP(), []int{136} } func (x *RemoveNetworkRule) GetRuleName() string { @@ -9729,7 +10034,7 @@ type AddDenyRules struct { func (x *AddDenyRules) Reset() { *x = AddDenyRules{} - mi := &file_openshell_proto_msgTypes[135] + mi := &file_openshell_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9741,7 +10046,7 @@ func (x *AddDenyRules) String() string { func (*AddDenyRules) ProtoMessage() {} func (x *AddDenyRules) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[135] + mi := &file_openshell_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9754,7 +10059,7 @@ func (x *AddDenyRules) ProtoReflect() protoreflect.Message { // Deprecated: Use AddDenyRules.ProtoReflect.Descriptor instead. func (*AddDenyRules) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{135} + return file_openshell_proto_rawDescGZIP(), []int{137} } func (x *AddDenyRules) GetHost() string { @@ -9789,7 +10094,7 @@ type AddAllowRules struct { func (x *AddAllowRules) Reset() { *x = AddAllowRules{} - mi := &file_openshell_proto_msgTypes[136] + mi := &file_openshell_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9801,7 +10106,7 @@ func (x *AddAllowRules) String() string { func (*AddAllowRules) ProtoMessage() {} func (x *AddAllowRules) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[136] + mi := &file_openshell_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9814,7 +10119,7 @@ func (x *AddAllowRules) ProtoReflect() protoreflect.Message { // Deprecated: Use AddAllowRules.ProtoReflect.Descriptor instead. func (*AddAllowRules) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{136} + return file_openshell_proto_rawDescGZIP(), []int{138} } func (x *AddAllowRules) GetHost() string { @@ -9848,7 +10153,7 @@ type RemoveNetworkBinary struct { func (x *RemoveNetworkBinary) Reset() { *x = RemoveNetworkBinary{} - mi := &file_openshell_proto_msgTypes[137] + mi := &file_openshell_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9860,7 +10165,7 @@ func (x *RemoveNetworkBinary) String() string { func (*RemoveNetworkBinary) ProtoMessage() {} func (x *RemoveNetworkBinary) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[137] + mi := &file_openshell_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9873,7 +10178,7 @@ func (x *RemoveNetworkBinary) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveNetworkBinary.ProtoReflect.Descriptor instead. func (*RemoveNetworkBinary) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{137} + return file_openshell_proto_rawDescGZIP(), []int{139} } func (x *RemoveNetworkBinary) GetRuleName() string { @@ -9909,7 +10214,7 @@ type UpdateConfigResponse struct { func (x *UpdateConfigResponse) Reset() { *x = UpdateConfigResponse{} - mi := &file_openshell_proto_msgTypes[138] + mi := &file_openshell_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9921,7 +10226,7 @@ func (x *UpdateConfigResponse) String() string { func (*UpdateConfigResponse) ProtoMessage() {} func (x *UpdateConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[138] + mi := &file_openshell_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9934,7 +10239,7 @@ func (x *UpdateConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateConfigResponse.ProtoReflect.Descriptor instead. func (*UpdateConfigResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{138} + return file_openshell_proto_rawDescGZIP(), []int{140} } func (x *UpdateConfigResponse) GetVersion() uint32 { @@ -9989,7 +10294,7 @@ type GetSandboxPolicyStatusRequest struct { func (x *GetSandboxPolicyStatusRequest) Reset() { *x = GetSandboxPolicyStatusRequest{} - mi := &file_openshell_proto_msgTypes[139] + mi := &file_openshell_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10001,7 +10306,7 @@ func (x *GetSandboxPolicyStatusRequest) String() string { func (*GetSandboxPolicyStatusRequest) ProtoMessage() {} func (x *GetSandboxPolicyStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[139] + mi := &file_openshell_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10014,7 +10319,7 @@ func (x *GetSandboxPolicyStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSandboxPolicyStatusRequest.ProtoReflect.Descriptor instead. func (*GetSandboxPolicyStatusRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{139} + return file_openshell_proto_rawDescGZIP(), []int{141} } func (x *GetSandboxPolicyStatusRequest) GetName() string { @@ -10058,7 +10363,7 @@ type GetSandboxPolicyStatusResponse struct { func (x *GetSandboxPolicyStatusResponse) Reset() { *x = GetSandboxPolicyStatusResponse{} - mi := &file_openshell_proto_msgTypes[140] + mi := &file_openshell_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10070,7 +10375,7 @@ func (x *GetSandboxPolicyStatusResponse) String() string { func (*GetSandboxPolicyStatusResponse) ProtoMessage() {} func (x *GetSandboxPolicyStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[140] + mi := &file_openshell_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10083,7 +10388,7 @@ func (x *GetSandboxPolicyStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSandboxPolicyStatusResponse.ProtoReflect.Descriptor instead. func (*GetSandboxPolicyStatusResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{140} + return file_openshell_proto_rawDescGZIP(), []int{142} } func (x *GetSandboxPolicyStatusResponse) GetRevision() *SandboxPolicyRevision { @@ -10117,7 +10422,7 @@ type ListSandboxPoliciesRequest struct { func (x *ListSandboxPoliciesRequest) Reset() { *x = ListSandboxPoliciesRequest{} - mi := &file_openshell_proto_msgTypes[141] + mi := &file_openshell_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10129,7 +10434,7 @@ func (x *ListSandboxPoliciesRequest) String() string { func (*ListSandboxPoliciesRequest) ProtoMessage() {} func (x *ListSandboxPoliciesRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[141] + mi := &file_openshell_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10142,7 +10447,7 @@ func (x *ListSandboxPoliciesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSandboxPoliciesRequest.ProtoReflect.Descriptor instead. func (*ListSandboxPoliciesRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{141} + return file_openshell_proto_rawDescGZIP(), []int{143} } func (x *ListSandboxPoliciesRequest) GetName() string { @@ -10192,7 +10497,7 @@ type ListSandboxPoliciesResponse struct { func (x *ListSandboxPoliciesResponse) Reset() { *x = ListSandboxPoliciesResponse{} - mi := &file_openshell_proto_msgTypes[142] + mi := &file_openshell_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10204,7 +10509,7 @@ func (x *ListSandboxPoliciesResponse) String() string { func (*ListSandboxPoliciesResponse) ProtoMessage() {} func (x *ListSandboxPoliciesResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[142] + mi := &file_openshell_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10217,7 +10522,7 @@ func (x *ListSandboxPoliciesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSandboxPoliciesResponse.ProtoReflect.Descriptor instead. func (*ListSandboxPoliciesResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{142} + return file_openshell_proto_rawDescGZIP(), []int{144} } func (x *ListSandboxPoliciesResponse) GetRevisions() []*SandboxPolicyRevision { @@ -10244,7 +10549,7 @@ type ReportPolicyStatusRequest struct { func (x *ReportPolicyStatusRequest) Reset() { *x = ReportPolicyStatusRequest{} - mi := &file_openshell_proto_msgTypes[143] + mi := &file_openshell_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10256,7 +10561,7 @@ func (x *ReportPolicyStatusRequest) String() string { func (*ReportPolicyStatusRequest) ProtoMessage() {} func (x *ReportPolicyStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[143] + mi := &file_openshell_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10269,7 +10574,7 @@ func (x *ReportPolicyStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportPolicyStatusRequest.ProtoReflect.Descriptor instead. func (*ReportPolicyStatusRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{143} + return file_openshell_proto_rawDescGZIP(), []int{145} } func (x *ReportPolicyStatusRequest) GetSandboxId() string { @@ -10309,7 +10614,7 @@ type ReportPolicyStatusResponse struct { func (x *ReportPolicyStatusResponse) Reset() { *x = ReportPolicyStatusResponse{} - mi := &file_openshell_proto_msgTypes[144] + mi := &file_openshell_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10321,7 +10626,7 @@ func (x *ReportPolicyStatusResponse) String() string { func (*ReportPolicyStatusResponse) ProtoMessage() {} func (x *ReportPolicyStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[144] + mi := &file_openshell_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10334,7 +10639,7 @@ func (x *ReportPolicyStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportPolicyStatusResponse.ProtoReflect.Descriptor instead. func (*ReportPolicyStatusResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{144} + return file_openshell_proto_rawDescGZIP(), []int{146} } // A versioned policy revision with metadata. @@ -10367,7 +10672,7 @@ type SandboxPolicyRevision struct { func (x *SandboxPolicyRevision) Reset() { *x = SandboxPolicyRevision{} - mi := &file_openshell_proto_msgTypes[145] + mi := &file_openshell_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10379,7 +10684,7 @@ func (x *SandboxPolicyRevision) String() string { func (*SandboxPolicyRevision) ProtoMessage() {} func (x *SandboxPolicyRevision) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[145] + mi := &file_openshell_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10392,7 +10697,7 @@ func (x *SandboxPolicyRevision) ProtoReflect() protoreflect.Message { // Deprecated: Use SandboxPolicyRevision.ProtoReflect.Descriptor instead. func (*SandboxPolicyRevision) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{145} + return file_openshell_proto_rawDescGZIP(), []int{147} } func (x *SandboxPolicyRevision) GetVersion() uint32 { @@ -10472,7 +10777,7 @@ type GetSandboxLogsRequest struct { func (x *GetSandboxLogsRequest) Reset() { *x = GetSandboxLogsRequest{} - mi := &file_openshell_proto_msgTypes[146] + mi := &file_openshell_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10484,7 +10789,7 @@ func (x *GetSandboxLogsRequest) String() string { func (*GetSandboxLogsRequest) ProtoMessage() {} func (x *GetSandboxLogsRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[146] + mi := &file_openshell_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10497,7 +10802,7 @@ func (x *GetSandboxLogsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSandboxLogsRequest.ProtoReflect.Descriptor instead. func (*GetSandboxLogsRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{146} + return file_openshell_proto_rawDescGZIP(), []int{148} } func (x *GetSandboxLogsRequest) GetSandboxId() string { @@ -10555,7 +10860,7 @@ type PushSandboxLogsRequest struct { func (x *PushSandboxLogsRequest) Reset() { *x = PushSandboxLogsRequest{} - mi := &file_openshell_proto_msgTypes[147] + mi := &file_openshell_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10567,7 +10872,7 @@ func (x *PushSandboxLogsRequest) String() string { func (*PushSandboxLogsRequest) ProtoMessage() {} func (x *PushSandboxLogsRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[147] + mi := &file_openshell_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10580,7 +10885,7 @@ func (x *PushSandboxLogsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PushSandboxLogsRequest.ProtoReflect.Descriptor instead. func (*PushSandboxLogsRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{147} + return file_openshell_proto_rawDescGZIP(), []int{149} } func (x *PushSandboxLogsRequest) GetSandboxId() string { @@ -10606,7 +10911,7 @@ type PushSandboxLogsResponse struct { func (x *PushSandboxLogsResponse) Reset() { *x = PushSandboxLogsResponse{} - mi := &file_openshell_proto_msgTypes[148] + mi := &file_openshell_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10618,7 +10923,7 @@ func (x *PushSandboxLogsResponse) String() string { func (*PushSandboxLogsResponse) ProtoMessage() {} func (x *PushSandboxLogsResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[148] + mi := &file_openshell_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10631,7 +10936,7 @@ func (x *PushSandboxLogsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PushSandboxLogsResponse.ProtoReflect.Descriptor instead. func (*PushSandboxLogsResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{148} + return file_openshell_proto_rawDescGZIP(), []int{150} } // Get sandbox logs response. @@ -10647,7 +10952,7 @@ type GetSandboxLogsResponse struct { func (x *GetSandboxLogsResponse) Reset() { *x = GetSandboxLogsResponse{} - mi := &file_openshell_proto_msgTypes[149] + mi := &file_openshell_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10659,7 +10964,7 @@ func (x *GetSandboxLogsResponse) String() string { func (*GetSandboxLogsResponse) ProtoMessage() {} func (x *GetSandboxLogsResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[149] + mi := &file_openshell_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10672,7 +10977,7 @@ func (x *GetSandboxLogsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSandboxLogsResponse.ProtoReflect.Descriptor instead. func (*GetSandboxLogsResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{149} + return file_openshell_proto_rawDescGZIP(), []int{151} } func (x *GetSandboxLogsResponse) GetLogs() []*SandboxLogLine { @@ -10698,6 +11003,8 @@ type SupervisorMessage struct { // *SupervisorMessage_Heartbeat // *SupervisorMessage_RelayOpenResult // *SupervisorMessage_RelayClose + // *SupervisorMessage_ConfigUpdateResult + // *SupervisorMessage_ConfigBootstrapResult Payload isSupervisorMessage_Payload `protobuf_oneof:"payload"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -10705,7 +11012,7 @@ type SupervisorMessage struct { func (x *SupervisorMessage) Reset() { *x = SupervisorMessage{} - mi := &file_openshell_proto_msgTypes[150] + mi := &file_openshell_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10717,7 +11024,7 @@ func (x *SupervisorMessage) String() string { func (*SupervisorMessage) ProtoMessage() {} func (x *SupervisorMessage) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[150] + mi := &file_openshell_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10730,7 +11037,7 @@ func (x *SupervisorMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use SupervisorMessage.ProtoReflect.Descriptor instead. func (*SupervisorMessage) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{150} + return file_openshell_proto_rawDescGZIP(), []int{152} } func (x *SupervisorMessage) GetPayload() isSupervisorMessage_Payload { @@ -10776,6 +11083,24 @@ func (x *SupervisorMessage) GetRelayClose() *RelayClose { return nil } +func (x *SupervisorMessage) GetConfigUpdateResult() *ConfigUpdateResult { + if x != nil { + if x, ok := x.Payload.(*SupervisorMessage_ConfigUpdateResult); ok { + return x.ConfigUpdateResult + } + } + return nil +} + +func (x *SupervisorMessage) GetConfigBootstrapResult() *ConfigBootstrapResult { + if x != nil { + if x, ok := x.Payload.(*SupervisorMessage_ConfigBootstrapResult); ok { + return x.ConfigBootstrapResult + } + } + return nil +} + type isSupervisorMessage_Payload interface { isSupervisorMessage_Payload() } @@ -10796,6 +11121,14 @@ type SupervisorMessage_RelayClose struct { RelayClose *RelayClose `protobuf:"bytes,4,opt,name=relay_close,json=relayClose,proto3,oneof"` } +type SupervisorMessage_ConfigUpdateResult struct { + ConfigUpdateResult *ConfigUpdateResult `protobuf:"bytes,5,opt,name=config_update_result,json=configUpdateResult,proto3,oneof"` +} + +type SupervisorMessage_ConfigBootstrapResult struct { + ConfigBootstrapResult *ConfigBootstrapResult `protobuf:"bytes,6,opt,name=config_bootstrap_result,json=configBootstrapResult,proto3,oneof"` +} + func (*SupervisorMessage_Hello) isSupervisorMessage_Payload() {} func (*SupervisorMessage_Heartbeat) isSupervisorMessage_Payload() {} @@ -10804,6 +11137,10 @@ func (*SupervisorMessage_RelayOpenResult) isSupervisorMessage_Payload() {} func (*SupervisorMessage_RelayClose) isSupervisorMessage_Payload() {} +func (*SupervisorMessage_ConfigUpdateResult) isSupervisorMessage_Payload() {} + +func (*SupervisorMessage_ConfigBootstrapResult) isSupervisorMessage_Payload() {} + // Envelope for gateway-to-supervisor messages on the ConnectSupervisor stream. type GatewayMessage struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -10814,6 +11151,7 @@ type GatewayMessage struct { // *GatewayMessage_Heartbeat // *GatewayMessage_RelayOpen // *GatewayMessage_RelayClose + // *GatewayMessage_ConfigUpdate Payload isGatewayMessage_Payload `protobuf_oneof:"payload"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -10821,7 +11159,7 @@ type GatewayMessage struct { func (x *GatewayMessage) Reset() { *x = GatewayMessage{} - mi := &file_openshell_proto_msgTypes[151] + mi := &file_openshell_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10833,7 +11171,7 @@ func (x *GatewayMessage) String() string { func (*GatewayMessage) ProtoMessage() {} func (x *GatewayMessage) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[151] + mi := &file_openshell_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10846,7 +11184,7 @@ func (x *GatewayMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use GatewayMessage.ProtoReflect.Descriptor instead. func (*GatewayMessage) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{151} + return file_openshell_proto_rawDescGZIP(), []int{153} } func (x *GatewayMessage) GetPayload() isGatewayMessage_Payload { @@ -10901,6 +11239,15 @@ func (x *GatewayMessage) GetRelayClose() *RelayClose { return nil } +func (x *GatewayMessage) GetConfigUpdate() *ConfigUpdate { + if x != nil { + if x, ok := x.Payload.(*GatewayMessage_ConfigUpdate); ok { + return x.ConfigUpdate + } + } + return nil +} + type isGatewayMessage_Payload interface { isGatewayMessage_Payload() } @@ -10925,6 +11272,10 @@ type GatewayMessage_RelayClose struct { RelayClose *RelayClose `protobuf:"bytes,5,opt,name=relay_close,json=relayClose,proto3,oneof"` } +type GatewayMessage_ConfigUpdate struct { + ConfigUpdate *ConfigUpdate `protobuf:"bytes,6,opt,name=config_update,json=configUpdate,proto3,oneof"` +} + func (*GatewayMessage_SessionAccepted) isGatewayMessage_Payload() {} func (*GatewayMessage_SessionRejected) isGatewayMessage_Payload() {} @@ -10935,20 +11286,24 @@ func (*GatewayMessage_RelayOpen) isGatewayMessage_Payload() {} func (*GatewayMessage_RelayClose) isGatewayMessage_Payload() {} +func (*GatewayMessage_ConfigUpdate) isGatewayMessage_Payload() {} + // Supervisor identifies itself and the sandbox it manages. type SupervisorHello struct { state protoimpl.MessageState `protogen:"open.v1"` // Sandbox ID this supervisor manages. SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` // Supervisor instance ID (e.g. boot id or process epoch). - InstanceId string `protobuf:"bytes,2,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + InstanceId string `protobuf:"bytes,2,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` + // Exact internal stream protocol revision implemented by this supervisor. + ProtocolRevision uint32 `protobuf:"varint,3,opt,name=protocol_revision,json=protocolRevision,proto3" json:"protocol_revision,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SupervisorHello) Reset() { *x = SupervisorHello{} - mi := &file_openshell_proto_msgTypes[152] + mi := &file_openshell_proto_msgTypes[154] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10960,7 +11315,7 @@ func (x *SupervisorHello) String() string { func (*SupervisorHello) ProtoMessage() {} func (x *SupervisorHello) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[152] + mi := &file_openshell_proto_msgTypes[154] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10973,7 +11328,7 @@ func (x *SupervisorHello) ProtoReflect() protoreflect.Message { // Deprecated: Use SupervisorHello.ProtoReflect.Descriptor instead. func (*SupervisorHello) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{152} + return file_openshell_proto_rawDescGZIP(), []int{154} } func (x *SupervisorHello) GetSandboxId() string { @@ -10990,6 +11345,13 @@ func (x *SupervisorHello) GetInstanceId() string { return "" } +func (x *SupervisorHello) GetProtocolRevision() uint32 { + if x != nil { + return x.ProtocolRevision + } + return 0 +} + // Gateway accepts the supervisor session. type SessionAccepted struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -10997,13 +11359,18 @@ type SessionAccepted struct { SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` // Recommended heartbeat interval in seconds. HeartbeatIntervalSecs uint32 `protobuf:"varint,2,opt,name=heartbeat_interval_secs,json=heartbeatIntervalSecs,proto3" json:"heartbeat_interval_secs,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // Complete gateway-owned configuration. During the staged rollout this may + // be omitted only when the gateway cannot build the projection. + Bootstrap *ConfigBootstrap `protobuf:"bytes,3,opt,name=bootstrap,proto3" json:"bootstrap,omitempty"` + // Exact internal stream protocol revision implemented by this gateway. + ProtocolRevision uint32 `protobuf:"varint,4,opt,name=protocol_revision,json=protocolRevision,proto3" json:"protocol_revision,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SessionAccepted) Reset() { *x = SessionAccepted{} - mi := &file_openshell_proto_msgTypes[153] + mi := &file_openshell_proto_msgTypes[155] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11015,7 +11382,7 @@ func (x *SessionAccepted) String() string { func (*SessionAccepted) ProtoMessage() {} func (x *SessionAccepted) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[153] + mi := &file_openshell_proto_msgTypes[155] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11028,7 +11395,7 @@ func (x *SessionAccepted) ProtoReflect() protoreflect.Message { // Deprecated: Use SessionAccepted.ProtoReflect.Descriptor instead. func (*SessionAccepted) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{153} + return file_openshell_proto_rawDescGZIP(), []int{155} } func (x *SessionAccepted) GetSessionId() string { @@ -11045,30 +11412,44 @@ func (x *SessionAccepted) GetHeartbeatIntervalSecs() uint32 { return 0 } -// Gateway rejects the supervisor session. -type SessionRejected struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Human-readable rejection reason. - Reason string `protobuf:"bytes,1,opt,name=reason,proto3" json:"reason,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache +func (x *SessionAccepted) GetBootstrap() *ConfigBootstrap { + if x != nil { + return x.Bootstrap + } + return nil } -func (x *SessionRejected) Reset() { - *x = SessionRejected{} - mi := &file_openshell_proto_msgTypes[154] +func (x *SessionAccepted) GetProtocolRevision() uint32 { + if x != nil { + return x.ProtocolRevision + } + return 0 +} + +// Complete gateway-owned configuration for a supervisor session. +type ConfigBootstrap struct { + state protoimpl.MessageState `protogen:"open.v1"` + SandboxConfig *sandboxv1.SandboxConfigSnapshot `protobuf:"bytes,1,opt,name=sandbox_config,json=sandboxConfig,proto3" json:"sandbox_config,omitempty"` + ProviderEnvironment *ProviderEnvironmentSnapshot `protobuf:"bytes,2,opt,name=provider_environment,json=providerEnvironment,proto3" json:"provider_environment,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfigBootstrap) Reset() { + *x = ConfigBootstrap{} + mi := &file_openshell_proto_msgTypes[156] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *SessionRejected) String() string { +func (x *ConfigBootstrap) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SessionRejected) ProtoMessage() {} +func (*ConfigBootstrap) ProtoMessage() {} -func (x *SessionRejected) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[154] +func (x *ConfigBootstrap) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[156] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11079,40 +11460,57 @@ func (x *SessionRejected) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SessionRejected.ProtoReflect.Descriptor instead. -func (*SessionRejected) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{154} +// Deprecated: Use ConfigBootstrap.ProtoReflect.Descriptor instead. +func (*ConfigBootstrap) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{156} } -func (x *SessionRejected) GetReason() string { +func (x *ConfigBootstrap) GetSandboxConfig() *sandboxv1.SandboxConfigSnapshot { if x != nil { - return x.Reason + return x.SandboxConfig } - return "" + return nil } -// Supervisor heartbeat. -type SupervisorHeartbeat struct { - state protoimpl.MessageState `protogen:"open.v1"` +func (x *ConfigBootstrap) GetProviderEnvironment() *ProviderEnvironmentSnapshot { + if x != nil { + return x.ProviderEnvironment + } + return nil +} + +// A complete replacement snapshot for exactly one configuration component. +type ConfigUpdate struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Opaque non-empty identifier scoped to the active supervisor session. + UpdateId string `protobuf:"bytes,1,opt,name=update_id,json=updateId,proto3" json:"update_id,omitempty"` + // Monotonic within one session and component. Snapshot revisions are + // content identities and must only be compared for equality. + ComponentSequence uint64 `protobuf:"varint,2,opt,name=component_sequence,json=componentSequence,proto3" json:"component_sequence,omitempty"` + // Types that are valid to be assigned to Component: + // + // *ConfigUpdate_SandboxConfig + // *ConfigUpdate_ProviderEnvironment + Component isConfigUpdate_Component `protobuf_oneof:"component"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *SupervisorHeartbeat) Reset() { - *x = SupervisorHeartbeat{} - mi := &file_openshell_proto_msgTypes[155] +func (x *ConfigUpdate) Reset() { + *x = ConfigUpdate{} + mi := &file_openshell_proto_msgTypes[157] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *SupervisorHeartbeat) String() string { +func (x *ConfigUpdate) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SupervisorHeartbeat) ProtoMessage() {} +func (*ConfigUpdate) ProtoMessage() {} -func (x *SupervisorHeartbeat) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[155] +func (x *ConfigUpdate) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[157] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11123,75 +11521,616 @@ func (x *SupervisorHeartbeat) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SupervisorHeartbeat.ProtoReflect.Descriptor instead. -func (*SupervisorHeartbeat) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{155} +// Deprecated: Use ConfigUpdate.ProtoReflect.Descriptor instead. +func (*ConfigUpdate) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{157} } -// Gateway heartbeat. -type GatewayHeartbeat struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache +func (x *ConfigUpdate) GetUpdateId() string { + if x != nil { + return x.UpdateId + } + return "" } -func (x *GatewayHeartbeat) Reset() { - *x = GatewayHeartbeat{} - mi := &file_openshell_proto_msgTypes[156] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) +func (x *ConfigUpdate) GetComponentSequence() uint64 { + if x != nil { + return x.ComponentSequence + } + return 0 } -func (x *GatewayHeartbeat) String() string { - return protoimpl.X.MessageStringOf(x) +func (x *ConfigUpdate) GetComponent() isConfigUpdate_Component { + if x != nil { + return x.Component + } + return nil } -func (*GatewayHeartbeat) ProtoMessage() {} +func (x *ConfigUpdate) GetSandboxConfig() *sandboxv1.SandboxConfigSnapshot { + if x != nil { + if x, ok := x.Component.(*ConfigUpdate_SandboxConfig); ok { + return x.SandboxConfig + } + } + return nil +} -func (x *GatewayHeartbeat) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[156] +func (x *ConfigUpdate) GetProviderEnvironment() *ProviderEnvironmentSnapshot { if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) + if x, ok := x.Component.(*ConfigUpdate_ProviderEnvironment); ok { + return x.ProviderEnvironment } - return ms } - return mi.MessageOf(x) + return nil } -// Deprecated: Use GatewayHeartbeat.ProtoReflect.Descriptor instead. -func (*GatewayHeartbeat) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{156} +type isConfigUpdate_Component interface { + isConfigUpdate_Component() } -// Terminal result reported before the supervisor shuts down. A successful RPC -// response confirms that the result was durably handled by the gateway. -type ReportMainProcessExitRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` - InstanceId string `protobuf:"bytes,2,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` - // Normalized process result. Signal exits use 128 + signal number. - ExitCode int32 `protobuf:"varint,3,opt,name=exit_code,json=exitCode,proto3" json:"exit_code,omitempty"` +type ConfigUpdate_SandboxConfig struct { + SandboxConfig *sandboxv1.SandboxConfigSnapshot `protobuf:"bytes,3,opt,name=sandbox_config,json=sandboxConfig,proto3,oneof"` +} + +type ConfigUpdate_ProviderEnvironment struct { + ProviderEnvironment *ProviderEnvironmentSnapshot `protobuf:"bytes,4,opt,name=provider_environment,json=providerEnvironment,proto3,oneof"` +} + +func (*ConfigUpdate_SandboxConfig) isConfigUpdate_Component() {} + +func (*ConfigUpdate_ProviderEnvironment) isConfigUpdate_Component() {} + +// Identifies one component snapshot revision. Revisions are equality tokens, +// not members of one shared ordering domain. +type ConfigSnapshotRevision struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Component: + // + // *ConfigSnapshotRevision_SandboxConfig + // *ConfigSnapshotRevision_ProviderEnvironment + Component isConfigSnapshotRevision_Component `protobuf_oneof:"component"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ReportMainProcessExitRequest) Reset() { - *x = ReportMainProcessExitRequest{} - mi := &file_openshell_proto_msgTypes[157] +func (x *ConfigSnapshotRevision) Reset() { + *x = ConfigSnapshotRevision{} + mi := &file_openshell_proto_msgTypes[158] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ReportMainProcessExitRequest) String() string { +func (x *ConfigSnapshotRevision) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfigSnapshotRevision) ProtoMessage() {} + +func (x *ConfigSnapshotRevision) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[158] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfigSnapshotRevision.ProtoReflect.Descriptor instead. +func (*ConfigSnapshotRevision) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{158} +} + +func (x *ConfigSnapshotRevision) GetComponent() isConfigSnapshotRevision_Component { + if x != nil { + return x.Component + } + return nil +} + +func (x *ConfigSnapshotRevision) GetSandboxConfig() *SandboxConfigRevision { + if x != nil { + if x, ok := x.Component.(*ConfigSnapshotRevision_SandboxConfig); ok { + return x.SandboxConfig + } + } + return nil +} + +func (x *ConfigSnapshotRevision) GetProviderEnvironment() uint64 { + if x != nil { + if x, ok := x.Component.(*ConfigSnapshotRevision_ProviderEnvironment); ok { + return x.ProviderEnvironment + } + } + return 0 +} + +type isConfigSnapshotRevision_Component interface { + isConfigSnapshotRevision_Component() +} + +type ConfigSnapshotRevision_SandboxConfig struct { + SandboxConfig *SandboxConfigRevision `protobuf:"bytes,1,opt,name=sandbox_config,json=sandboxConfig,proto3,oneof"` +} + +type ConfigSnapshotRevision_ProviderEnvironment struct { + ProviderEnvironment uint64 `protobuf:"varint,2,opt,name=provider_environment,json=providerEnvironment,proto3,oneof"` +} + +func (*ConfigSnapshotRevision_SandboxConfig) isConfigSnapshotRevision_Component() {} + +func (*ConfigSnapshotRevision_ProviderEnvironment) isConfigSnapshotRevision_Component() {} + +// Identity needed to correlate effective sandbox configuration with the +// policy-history row whose apply status the gateway records. +type SandboxConfigRevision struct { + state protoimpl.MessageState `protogen:"open.v1"` + ConfigRevision uint64 `protobuf:"varint,1,opt,name=config_revision,json=configRevision,proto3" json:"config_revision,omitempty"` + PolicyVersion uint32 `protobuf:"varint,2,opt,name=policy_version,json=policyVersion,proto3" json:"policy_version,omitempty"` + PolicySource sandboxv1.PolicySource `protobuf:"varint,3,opt,name=policy_source,json=policySource,proto3,enum=openshell.sandbox.v1.PolicySource" json:"policy_source,omitempty"` + GlobalPolicyVersion uint32 `protobuf:"varint,4,opt,name=global_policy_version,json=globalPolicyVersion,proto3" json:"global_policy_version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SandboxConfigRevision) Reset() { + *x = SandboxConfigRevision{} + mi := &file_openshell_proto_msgTypes[159] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SandboxConfigRevision) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SandboxConfigRevision) ProtoMessage() {} + +func (x *SandboxConfigRevision) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[159] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SandboxConfigRevision.ProtoReflect.Descriptor instead. +func (*SandboxConfigRevision) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{159} +} + +func (x *SandboxConfigRevision) GetConfigRevision() uint64 { + if x != nil { + return x.ConfigRevision + } + return 0 +} + +func (x *SandboxConfigRevision) GetPolicyVersion() uint32 { + if x != nil { + return x.PolicyVersion + } + return 0 +} + +func (x *SandboxConfigRevision) GetPolicySource() sandboxv1.PolicySource { + if x != nil { + return x.PolicySource + } + return sandboxv1.PolicySource(0) +} + +func (x *SandboxConfigRevision) GetGlobalPolicyVersion() uint32 { + if x != nil { + return x.GlobalPolicyVersion + } + return 0 +} + +// Sanitized application failure. Messages must not contain configuration +// payloads, credentials, or provider values. +type ConfigApplyFailure struct { + state protoimpl.MessageState `protogen:"open.v1"` + Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + Retryable bool `protobuf:"varint,3,opt,name=retryable,proto3" json:"retryable,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfigApplyFailure) Reset() { + *x = ConfigApplyFailure{} + mi := &file_openshell_proto_msgTypes[160] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfigApplyFailure) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfigApplyFailure) ProtoMessage() {} + +func (x *ConfigApplyFailure) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[160] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfigApplyFailure.ProtoReflect.Descriptor instead. +func (*ConfigApplyFailure) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{160} +} + +func (x *ConfigApplyFailure) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +func (x *ConfigApplyFailure) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *ConfigApplyFailure) GetRetryable() bool { + if x != nil { + return x.Retryable + } + return false +} + +type ConfigComponentApplyResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + Component ConfigComponent `protobuf:"varint,1,opt,name=component,proto3,enum=openshell.v1.ConfigComponent" json:"component,omitempty"` + // Revision extracted from the received snapshot. + RequestedRevision *ConfigSnapshotRevision `protobuf:"bytes,2,opt,name=requested_revision,json=requestedRevision,proto3" json:"requested_revision,omitempty"` + // Revision active after this attempt. Omitted when the received snapshot + // was not installed or a local override has no gateway revision. + AppliedRevision *ConfigSnapshotRevision `protobuf:"bytes,3,opt,name=applied_revision,json=appliedRevision,proto3" json:"applied_revision,omitempty"` + Outcome ConfigApplyOutcome `protobuf:"varint,4,opt,name=outcome,proto3,enum=openshell.v1.ConfigApplyOutcome" json:"outcome,omitempty"` + Failure *ConfigApplyFailure `protobuf:"bytes,5,opt,name=failure,proto3" json:"failure,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfigComponentApplyResult) Reset() { + *x = ConfigComponentApplyResult{} + mi := &file_openshell_proto_msgTypes[161] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfigComponentApplyResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfigComponentApplyResult) ProtoMessage() {} + +func (x *ConfigComponentApplyResult) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[161] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfigComponentApplyResult.ProtoReflect.Descriptor instead. +func (*ConfigComponentApplyResult) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{161} +} + +func (x *ConfigComponentApplyResult) GetComponent() ConfigComponent { + if x != nil { + return x.Component + } + return ConfigComponent_CONFIG_COMPONENT_UNSPECIFIED +} + +func (x *ConfigComponentApplyResult) GetRequestedRevision() *ConfigSnapshotRevision { + if x != nil { + return x.RequestedRevision + } + return nil +} + +func (x *ConfigComponentApplyResult) GetAppliedRevision() *ConfigSnapshotRevision { + if x != nil { + return x.AppliedRevision + } + return nil +} + +func (x *ConfigComponentApplyResult) GetOutcome() ConfigApplyOutcome { + if x != nil { + return x.Outcome + } + return ConfigApplyOutcome_CONFIG_APPLY_OUTCOME_UNSPECIFIED +} + +func (x *ConfigComponentApplyResult) GetFailure() *ConfigApplyFailure { + if x != nil { + return x.Failure + } + return nil +} + +// Application result for one ConfigUpdate. +type ConfigUpdateResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Echoes ConfigUpdate.update_id for session-local correlation. + UpdateId string `protobuf:"bytes,1,opt,name=update_id,json=updateId,proto3" json:"update_id,omitempty"` + // Echoes ConfigUpdate.component_sequence. + ComponentSequence uint64 `protobuf:"varint,2,opt,name=component_sequence,json=componentSequence,proto3" json:"component_sequence,omitempty"` + Result *ConfigComponentApplyResult `protobuf:"bytes,3,opt,name=result,proto3" json:"result,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfigUpdateResult) Reset() { + *x = ConfigUpdateResult{} + mi := &file_openshell_proto_msgTypes[162] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfigUpdateResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfigUpdateResult) ProtoMessage() {} + +func (x *ConfigUpdateResult) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[162] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfigUpdateResult.ProtoReflect.Descriptor instead. +func (*ConfigUpdateResult) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{162} +} + +func (x *ConfigUpdateResult) GetUpdateId() string { + if x != nil { + return x.UpdateId + } + return "" +} + +func (x *ConfigUpdateResult) GetComponentSequence() uint64 { + if x != nil { + return x.ComponentSequence + } + return 0 +} + +func (x *ConfigUpdateResult) GetResult() *ConfigComponentApplyResult { + if x != nil { + return x.Result + } + return nil +} + +// Aggregate application result for the SessionAccepted bootstrap. +type ConfigBootstrapResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + Results []*ConfigComponentApplyResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfigBootstrapResult) Reset() { + *x = ConfigBootstrapResult{} + mi := &file_openshell_proto_msgTypes[163] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfigBootstrapResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfigBootstrapResult) ProtoMessage() {} + +func (x *ConfigBootstrapResult) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[163] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfigBootstrapResult.ProtoReflect.Descriptor instead. +func (*ConfigBootstrapResult) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{163} +} + +func (x *ConfigBootstrapResult) GetResults() []*ConfigComponentApplyResult { + if x != nil { + return x.Results + } + return nil +} + +// Gateway rejects the supervisor session. +type SessionRejected struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Human-readable rejection reason. + Reason string `protobuf:"bytes,1,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SessionRejected) Reset() { + *x = SessionRejected{} + mi := &file_openshell_proto_msgTypes[164] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionRejected) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionRejected) ProtoMessage() {} + +func (x *SessionRejected) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[164] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionRejected.ProtoReflect.Descriptor instead. +func (*SessionRejected) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{164} +} + +func (x *SessionRejected) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +// Supervisor heartbeat. +type SupervisorHeartbeat struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SupervisorHeartbeat) Reset() { + *x = SupervisorHeartbeat{} + mi := &file_openshell_proto_msgTypes[165] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SupervisorHeartbeat) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SupervisorHeartbeat) ProtoMessage() {} + +func (x *SupervisorHeartbeat) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[165] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SupervisorHeartbeat.ProtoReflect.Descriptor instead. +func (*SupervisorHeartbeat) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{165} +} + +// Gateway heartbeat. +type GatewayHeartbeat struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GatewayHeartbeat) Reset() { + *x = GatewayHeartbeat{} + mi := &file_openshell_proto_msgTypes[166] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GatewayHeartbeat) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GatewayHeartbeat) ProtoMessage() {} + +func (x *GatewayHeartbeat) ProtoReflect() protoreflect.Message { + mi := &file_openshell_proto_msgTypes[166] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GatewayHeartbeat.ProtoReflect.Descriptor instead. +func (*GatewayHeartbeat) Descriptor() ([]byte, []int) { + return file_openshell_proto_rawDescGZIP(), []int{166} +} + +// Terminal result reported before the supervisor shuts down. A successful RPC +// response confirms that the result was durably handled by the gateway. +type ReportMainProcessExitRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + InstanceId string `protobuf:"bytes,2,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` + // Normalized process result. Signal exits use 128 + signal number. + ExitCode int32 `protobuf:"varint,3,opt,name=exit_code,json=exitCode,proto3" json:"exit_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReportMainProcessExitRequest) Reset() { + *x = ReportMainProcessExitRequest{} + mi := &file_openshell_proto_msgTypes[167] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReportMainProcessExitRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*ReportMainProcessExitRequest) ProtoMessage() {} func (x *ReportMainProcessExitRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[157] + mi := &file_openshell_proto_msgTypes[167] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11204,7 +12143,7 @@ func (x *ReportMainProcessExitRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportMainProcessExitRequest.ProtoReflect.Descriptor instead. func (*ReportMainProcessExitRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{157} + return file_openshell_proto_rawDescGZIP(), []int{167} } func (x *ReportMainProcessExitRequest) GetSandboxId() string { @@ -11236,7 +12175,7 @@ type ReportMainProcessExitResponse struct { func (x *ReportMainProcessExitResponse) Reset() { *x = ReportMainProcessExitResponse{} - mi := &file_openshell_proto_msgTypes[158] + mi := &file_openshell_proto_msgTypes[168] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11248,7 +12187,7 @@ func (x *ReportMainProcessExitResponse) String() string { func (*ReportMainProcessExitResponse) ProtoMessage() {} func (x *ReportMainProcessExitResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[158] + mi := &file_openshell_proto_msgTypes[168] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11261,7 +12200,7 @@ func (x *ReportMainProcessExitResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportMainProcessExitResponse.ProtoReflect.Descriptor instead. func (*ReportMainProcessExitResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{158} + return file_openshell_proto_rawDescGZIP(), []int{168} } // Terminal-delivery completion reported after all expected foreground SSH @@ -11276,7 +12215,7 @@ type FinalizeMainProcessExitRequest struct { func (x *FinalizeMainProcessExitRequest) Reset() { *x = FinalizeMainProcessExitRequest{} - mi := &file_openshell_proto_msgTypes[159] + mi := &file_openshell_proto_msgTypes[169] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11288,7 +12227,7 @@ func (x *FinalizeMainProcessExitRequest) String() string { func (*FinalizeMainProcessExitRequest) ProtoMessage() {} func (x *FinalizeMainProcessExitRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[159] + mi := &file_openshell_proto_msgTypes[169] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11301,7 +12240,7 @@ func (x *FinalizeMainProcessExitRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FinalizeMainProcessExitRequest.ProtoReflect.Descriptor instead. func (*FinalizeMainProcessExitRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{159} + return file_openshell_proto_rawDescGZIP(), []int{169} } func (x *FinalizeMainProcessExitRequest) GetSandboxId() string { @@ -11326,7 +12265,7 @@ type FinalizeMainProcessExitResponse struct { func (x *FinalizeMainProcessExitResponse) Reset() { *x = FinalizeMainProcessExitResponse{} - mi := &file_openshell_proto_msgTypes[160] + mi := &file_openshell_proto_msgTypes[170] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11338,7 +12277,7 @@ func (x *FinalizeMainProcessExitResponse) String() string { func (*FinalizeMainProcessExitResponse) ProtoMessage() {} func (x *FinalizeMainProcessExitResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[160] + mi := &file_openshell_proto_msgTypes[170] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11351,7 +12290,7 @@ func (x *FinalizeMainProcessExitResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FinalizeMainProcessExitResponse.ProtoReflect.Descriptor instead. func (*FinalizeMainProcessExitResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{160} + return file_openshell_proto_rawDescGZIP(), []int{170} } // Gateway requests the supervisor to open a relay channel. @@ -11380,7 +12319,7 @@ type RelayOpen struct { func (x *RelayOpen) Reset() { *x = RelayOpen{} - mi := &file_openshell_proto_msgTypes[161] + mi := &file_openshell_proto_msgTypes[171] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11392,7 +12331,7 @@ func (x *RelayOpen) String() string { func (*RelayOpen) ProtoMessage() {} func (x *RelayOpen) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[161] + mi := &file_openshell_proto_msgTypes[171] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11405,7 +12344,7 @@ func (x *RelayOpen) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayOpen.ProtoReflect.Descriptor instead. func (*RelayOpen) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{161} + return file_openshell_proto_rawDescGZIP(), []int{171} } func (x *RelayOpen) GetChannelId() string { @@ -11472,7 +12411,7 @@ type SshRelayTarget struct { func (x *SshRelayTarget) Reset() { *x = SshRelayTarget{} - mi := &file_openshell_proto_msgTypes[162] + mi := &file_openshell_proto_msgTypes[172] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11484,7 +12423,7 @@ func (x *SshRelayTarget) String() string { func (*SshRelayTarget) ProtoMessage() {} func (x *SshRelayTarget) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[162] + mi := &file_openshell_proto_msgTypes[172] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11497,7 +12436,7 @@ func (x *SshRelayTarget) ProtoReflect() protoreflect.Message { // Deprecated: Use SshRelayTarget.ProtoReflect.Descriptor instead. func (*SshRelayTarget) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{162} + return file_openshell_proto_rawDescGZIP(), []int{172} } // TCP target dialed by the supervisor from inside the sandbox. @@ -11513,7 +12452,7 @@ type TcpRelayTarget struct { func (x *TcpRelayTarget) Reset() { *x = TcpRelayTarget{} - mi := &file_openshell_proto_msgTypes[163] + mi := &file_openshell_proto_msgTypes[173] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11525,7 +12464,7 @@ func (x *TcpRelayTarget) String() string { func (*TcpRelayTarget) ProtoMessage() {} func (x *TcpRelayTarget) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[163] + mi := &file_openshell_proto_msgTypes[173] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11538,7 +12477,7 @@ func (x *TcpRelayTarget) ProtoReflect() protoreflect.Message { // Deprecated: Use TcpRelayTarget.ProtoReflect.Descriptor instead. func (*TcpRelayTarget) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{163} + return file_openshell_proto_rawDescGZIP(), []int{173} } func (x *TcpRelayTarget) GetHost() string { @@ -11566,7 +12505,7 @@ type RelayInit struct { func (x *RelayInit) Reset() { *x = RelayInit{} - mi := &file_openshell_proto_msgTypes[164] + mi := &file_openshell_proto_msgTypes[174] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11578,7 +12517,7 @@ func (x *RelayInit) String() string { func (*RelayInit) ProtoMessage() {} func (x *RelayInit) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[164] + mi := &file_openshell_proto_msgTypes[174] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11591,7 +12530,7 @@ func (x *RelayInit) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayInit.ProtoReflect.Descriptor instead. func (*RelayInit) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{164} + return file_openshell_proto_rawDescGZIP(), []int{174} } func (x *RelayInit) GetChannelId() string { @@ -11618,7 +12557,7 @@ type RelayFrame struct { func (x *RelayFrame) Reset() { *x = RelayFrame{} - mi := &file_openshell_proto_msgTypes[165] + mi := &file_openshell_proto_msgTypes[175] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11630,7 +12569,7 @@ func (x *RelayFrame) String() string { func (*RelayFrame) ProtoMessage() {} func (x *RelayFrame) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[165] + mi := &file_openshell_proto_msgTypes[175] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11643,7 +12582,7 @@ func (x *RelayFrame) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayFrame.ProtoReflect.Descriptor instead. func (*RelayFrame) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{165} + return file_openshell_proto_rawDescGZIP(), []int{175} } func (x *RelayFrame) GetPayload() isRelayFrame_Payload { @@ -11702,7 +12641,7 @@ type RelayOpenResult struct { func (x *RelayOpenResult) Reset() { *x = RelayOpenResult{} - mi := &file_openshell_proto_msgTypes[166] + mi := &file_openshell_proto_msgTypes[176] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11714,7 +12653,7 @@ func (x *RelayOpenResult) String() string { func (*RelayOpenResult) ProtoMessage() {} func (x *RelayOpenResult) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[166] + mi := &file_openshell_proto_msgTypes[176] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11727,7 +12666,7 @@ func (x *RelayOpenResult) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayOpenResult.ProtoReflect.Descriptor instead. func (*RelayOpenResult) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{166} + return file_openshell_proto_rawDescGZIP(), []int{176} } func (x *RelayOpenResult) GetChannelId() string { @@ -11764,7 +12703,7 @@ type RelayClose struct { func (x *RelayClose) Reset() { *x = RelayClose{} - mi := &file_openshell_proto_msgTypes[167] + mi := &file_openshell_proto_msgTypes[177] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11776,7 +12715,7 @@ func (x *RelayClose) String() string { func (*RelayClose) ProtoMessage() {} func (x *RelayClose) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[167] + mi := &file_openshell_proto_msgTypes[177] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11789,7 +12728,7 @@ func (x *RelayClose) ProtoReflect() protoreflect.Message { // Deprecated: Use RelayClose.ProtoReflect.Descriptor instead. func (*RelayClose) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{167} + return file_openshell_proto_rawDescGZIP(), []int{177} } func (x *RelayClose) GetChannelId() string { @@ -11823,7 +12762,7 @@ type L7RequestSample struct { func (x *L7RequestSample) Reset() { *x = L7RequestSample{} - mi := &file_openshell_proto_msgTypes[168] + mi := &file_openshell_proto_msgTypes[178] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11835,7 +12774,7 @@ func (x *L7RequestSample) String() string { func (*L7RequestSample) ProtoMessage() {} func (x *L7RequestSample) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[168] + mi := &file_openshell_proto_msgTypes[178] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11848,7 +12787,7 @@ func (x *L7RequestSample) ProtoReflect() protoreflect.Message { // Deprecated: Use L7RequestSample.ProtoReflect.Descriptor instead. func (*L7RequestSample) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{168} + return file_openshell_proto_rawDescGZIP(), []int{178} } func (x *L7RequestSample) GetMethod() string { @@ -11922,7 +12861,7 @@ type DenialSummary struct { func (x *DenialSummary) Reset() { *x = DenialSummary{} - mi := &file_openshell_proto_msgTypes[169] + mi := &file_openshell_proto_msgTypes[179] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11934,7 +12873,7 @@ func (x *DenialSummary) String() string { func (*DenialSummary) ProtoMessage() {} func (x *DenialSummary) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[169] + mi := &file_openshell_proto_msgTypes[179] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11947,7 +12886,7 @@ func (x *DenialSummary) ProtoReflect() protoreflect.Message { // Deprecated: Use DenialSummary.ProtoReflect.Descriptor instead. func (*DenialSummary) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{169} + return file_openshell_proto_rawDescGZIP(), []int{179} } func (x *DenialSummary) GetSandboxId() string { @@ -12082,7 +13021,7 @@ type DenialGroupCount struct { func (x *DenialGroupCount) Reset() { *x = DenialGroupCount{} - mi := &file_openshell_proto_msgTypes[170] + mi := &file_openshell_proto_msgTypes[180] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12094,7 +13033,7 @@ func (x *DenialGroupCount) String() string { func (*DenialGroupCount) ProtoMessage() {} func (x *DenialGroupCount) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[170] + mi := &file_openshell_proto_msgTypes[180] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12107,7 +13046,7 @@ func (x *DenialGroupCount) ProtoReflect() protoreflect.Message { // Deprecated: Use DenialGroupCount.ProtoReflect.Descriptor instead. func (*DenialGroupCount) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{170} + return file_openshell_proto_rawDescGZIP(), []int{180} } func (x *DenialGroupCount) GetDenyGroup() string { @@ -12140,7 +13079,7 @@ type NetworkActivitySummary struct { func (x *NetworkActivitySummary) Reset() { *x = NetworkActivitySummary{} - mi := &file_openshell_proto_msgTypes[171] + mi := &file_openshell_proto_msgTypes[181] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12152,7 +13091,7 @@ func (x *NetworkActivitySummary) String() string { func (*NetworkActivitySummary) ProtoMessage() {} func (x *NetworkActivitySummary) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[171] + mi := &file_openshell_proto_msgTypes[181] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12165,7 +13104,7 @@ func (x *NetworkActivitySummary) ProtoReflect() protoreflect.Message { // Deprecated: Use NetworkActivitySummary.ProtoReflect.Descriptor instead. func (*NetworkActivitySummary) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{171} + return file_openshell_proto_rawDescGZIP(), []int{181} } func (x *NetworkActivitySummary) GetNetworkActivityCount() uint32 { @@ -12253,7 +13192,7 @@ type PolicyChunk struct { func (x *PolicyChunk) Reset() { *x = PolicyChunk{} - mi := &file_openshell_proto_msgTypes[172] + mi := &file_openshell_proto_msgTypes[182] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12265,7 +13204,7 @@ func (x *PolicyChunk) String() string { func (*PolicyChunk) ProtoMessage() {} func (x *PolicyChunk) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[172] + mi := &file_openshell_proto_msgTypes[182] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12278,7 +13217,7 @@ func (x *PolicyChunk) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicyChunk.ProtoReflect.Descriptor instead. func (*PolicyChunk) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{172} + return file_openshell_proto_rawDescGZIP(), []int{182} } func (x *PolicyChunk) GetId() string { @@ -12466,7 +13405,7 @@ type DraftPolicyUpdate struct { func (x *DraftPolicyUpdate) Reset() { *x = DraftPolicyUpdate{} - mi := &file_openshell_proto_msgTypes[173] + mi := &file_openshell_proto_msgTypes[183] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12478,7 +13417,7 @@ func (x *DraftPolicyUpdate) String() string { func (*DraftPolicyUpdate) ProtoMessage() {} func (x *DraftPolicyUpdate) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[173] + mi := &file_openshell_proto_msgTypes[183] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12491,7 +13430,7 @@ func (x *DraftPolicyUpdate) ProtoReflect() protoreflect.Message { // Deprecated: Use DraftPolicyUpdate.ProtoReflect.Descriptor instead. func (*DraftPolicyUpdate) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{173} + return file_openshell_proto_rawDescGZIP(), []int{183} } func (x *DraftPolicyUpdate) GetDraftVersion() uint64 { @@ -12549,7 +13488,7 @@ type SubmitPolicyAnalysisRequest struct { func (x *SubmitPolicyAnalysisRequest) Reset() { *x = SubmitPolicyAnalysisRequest{} - mi := &file_openshell_proto_msgTypes[174] + mi := &file_openshell_proto_msgTypes[184] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12561,7 +13500,7 @@ func (x *SubmitPolicyAnalysisRequest) String() string { func (*SubmitPolicyAnalysisRequest) ProtoMessage() {} func (x *SubmitPolicyAnalysisRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[174] + mi := &file_openshell_proto_msgTypes[184] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12574,7 +13513,7 @@ func (x *SubmitPolicyAnalysisRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitPolicyAnalysisRequest.ProtoReflect.Descriptor instead. func (*SubmitPolicyAnalysisRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{174} + return file_openshell_proto_rawDescGZIP(), []int{184} } func (x *SubmitPolicyAnalysisRequest) GetSummaries() []*DenialSummary { @@ -12637,7 +13576,7 @@ type SubmitPolicyAnalysisResponse struct { func (x *SubmitPolicyAnalysisResponse) Reset() { *x = SubmitPolicyAnalysisResponse{} - mi := &file_openshell_proto_msgTypes[175] + mi := &file_openshell_proto_msgTypes[185] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12649,7 +13588,7 @@ func (x *SubmitPolicyAnalysisResponse) String() string { func (*SubmitPolicyAnalysisResponse) ProtoMessage() {} func (x *SubmitPolicyAnalysisResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[175] + mi := &file_openshell_proto_msgTypes[185] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12662,7 +13601,7 @@ func (x *SubmitPolicyAnalysisResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitPolicyAnalysisResponse.ProtoReflect.Descriptor instead. func (*SubmitPolicyAnalysisResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{175} + return file_openshell_proto_rawDescGZIP(), []int{185} } func (x *SubmitPolicyAnalysisResponse) GetAcceptedChunks() uint32 { @@ -12708,7 +13647,7 @@ type GetDraftPolicyRequest struct { func (x *GetDraftPolicyRequest) Reset() { *x = GetDraftPolicyRequest{} - mi := &file_openshell_proto_msgTypes[176] + mi := &file_openshell_proto_msgTypes[186] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12720,7 +13659,7 @@ func (x *GetDraftPolicyRequest) String() string { func (*GetDraftPolicyRequest) ProtoMessage() {} func (x *GetDraftPolicyRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[176] + mi := &file_openshell_proto_msgTypes[186] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12733,7 +13672,7 @@ func (x *GetDraftPolicyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDraftPolicyRequest.ProtoReflect.Descriptor instead. func (*GetDraftPolicyRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{176} + return file_openshell_proto_rawDescGZIP(), []int{186} } func (x *GetDraftPolicyRequest) GetName() string { @@ -12773,7 +13712,7 @@ type GetDraftPolicyResponse struct { func (x *GetDraftPolicyResponse) Reset() { *x = GetDraftPolicyResponse{} - mi := &file_openshell_proto_msgTypes[177] + mi := &file_openshell_proto_msgTypes[187] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12785,7 +13724,7 @@ func (x *GetDraftPolicyResponse) String() string { func (*GetDraftPolicyResponse) ProtoMessage() {} func (x *GetDraftPolicyResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[177] + mi := &file_openshell_proto_msgTypes[187] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12798,7 +13737,7 @@ func (x *GetDraftPolicyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDraftPolicyResponse.ProtoReflect.Descriptor instead. func (*GetDraftPolicyResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{177} + return file_openshell_proto_rawDescGZIP(), []int{187} } func (x *GetDraftPolicyResponse) GetChunks() []*PolicyChunk { @@ -12847,7 +13786,7 @@ type ApproveDraftChunkRequest struct { func (x *ApproveDraftChunkRequest) Reset() { *x = ApproveDraftChunkRequest{} - mi := &file_openshell_proto_msgTypes[178] + mi := &file_openshell_proto_msgTypes[188] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12859,7 +13798,7 @@ func (x *ApproveDraftChunkRequest) String() string { func (*ApproveDraftChunkRequest) ProtoMessage() {} func (x *ApproveDraftChunkRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[178] + mi := &file_openshell_proto_msgTypes[188] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12872,7 +13811,7 @@ func (x *ApproveDraftChunkRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApproveDraftChunkRequest.ProtoReflect.Descriptor instead. func (*ApproveDraftChunkRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{178} + return file_openshell_proto_rawDescGZIP(), []int{188} } func (x *ApproveDraftChunkRequest) GetName() string { @@ -12915,7 +13854,7 @@ type ApproveDraftChunkResponse struct { func (x *ApproveDraftChunkResponse) Reset() { *x = ApproveDraftChunkResponse{} - mi := &file_openshell_proto_msgTypes[179] + mi := &file_openshell_proto_msgTypes[189] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12927,7 +13866,7 @@ func (x *ApproveDraftChunkResponse) String() string { func (*ApproveDraftChunkResponse) ProtoMessage() {} func (x *ApproveDraftChunkResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[179] + mi := &file_openshell_proto_msgTypes[189] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12940,7 +13879,7 @@ func (x *ApproveDraftChunkResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApproveDraftChunkResponse.ProtoReflect.Descriptor instead. func (*ApproveDraftChunkResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{179} + return file_openshell_proto_rawDescGZIP(), []int{189} } func (x *ApproveDraftChunkResponse) GetPolicyVersion() uint32 { @@ -12974,7 +13913,7 @@ type RejectDraftChunkRequest struct { func (x *RejectDraftChunkRequest) Reset() { *x = RejectDraftChunkRequest{} - mi := &file_openshell_proto_msgTypes[180] + mi := &file_openshell_proto_msgTypes[190] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12986,7 +13925,7 @@ func (x *RejectDraftChunkRequest) String() string { func (*RejectDraftChunkRequest) ProtoMessage() {} func (x *RejectDraftChunkRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[180] + mi := &file_openshell_proto_msgTypes[190] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12999,7 +13938,7 @@ func (x *RejectDraftChunkRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RejectDraftChunkRequest.ProtoReflect.Descriptor instead. func (*RejectDraftChunkRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{180} + return file_openshell_proto_rawDescGZIP(), []int{190} } func (x *RejectDraftChunkRequest) GetName() string { @@ -13038,7 +13977,7 @@ type RejectDraftChunkResponse struct { func (x *RejectDraftChunkResponse) Reset() { *x = RejectDraftChunkResponse{} - mi := &file_openshell_proto_msgTypes[181] + mi := &file_openshell_proto_msgTypes[191] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13050,7 +13989,7 @@ func (x *RejectDraftChunkResponse) String() string { func (*RejectDraftChunkResponse) ProtoMessage() {} func (x *RejectDraftChunkResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[181] + mi := &file_openshell_proto_msgTypes[191] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13063,7 +14002,7 @@ func (x *RejectDraftChunkResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RejectDraftChunkResponse.ProtoReflect.Descriptor instead. func (*RejectDraftChunkResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{181} + return file_openshell_proto_rawDescGZIP(), []int{191} } // Approve all pending chunks. @@ -13077,7 +14016,7 @@ type DraftChunkApproval struct { func (x *DraftChunkApproval) Reset() { *x = DraftChunkApproval{} - mi := &file_openshell_proto_msgTypes[182] + mi := &file_openshell_proto_msgTypes[192] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13089,7 +14028,7 @@ func (x *DraftChunkApproval) String() string { func (*DraftChunkApproval) ProtoMessage() {} func (x *DraftChunkApproval) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[182] + mi := &file_openshell_proto_msgTypes[192] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13102,7 +14041,7 @@ func (x *DraftChunkApproval) ProtoReflect() protoreflect.Message { // Deprecated: Use DraftChunkApproval.ProtoReflect.Descriptor instead. func (*DraftChunkApproval) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{182} + return file_openshell_proto_rawDescGZIP(), []int{192} } func (x *DraftChunkApproval) GetChunkId() string { @@ -13136,7 +14075,7 @@ type ApproveAllDraftChunksRequest struct { func (x *ApproveAllDraftChunksRequest) Reset() { *x = ApproveAllDraftChunksRequest{} - mi := &file_openshell_proto_msgTypes[183] + mi := &file_openshell_proto_msgTypes[193] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13148,7 +14087,7 @@ func (x *ApproveAllDraftChunksRequest) String() string { func (*ApproveAllDraftChunksRequest) ProtoMessage() {} func (x *ApproveAllDraftChunksRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[183] + mi := &file_openshell_proto_msgTypes[193] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13161,7 +14100,7 @@ func (x *ApproveAllDraftChunksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApproveAllDraftChunksRequest.ProtoReflect.Descriptor instead. func (*ApproveAllDraftChunksRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{183} + return file_openshell_proto_rawDescGZIP(), []int{193} } func (x *ApproveAllDraftChunksRequest) GetName() string { @@ -13209,7 +14148,7 @@ type ApproveAllDraftChunksResponse struct { func (x *ApproveAllDraftChunksResponse) Reset() { *x = ApproveAllDraftChunksResponse{} - mi := &file_openshell_proto_msgTypes[184] + mi := &file_openshell_proto_msgTypes[194] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13221,7 +14160,7 @@ func (x *ApproveAllDraftChunksResponse) String() string { func (*ApproveAllDraftChunksResponse) ProtoMessage() {} func (x *ApproveAllDraftChunksResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[184] + mi := &file_openshell_proto_msgTypes[194] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13234,7 +14173,7 @@ func (x *ApproveAllDraftChunksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApproveAllDraftChunksResponse.ProtoReflect.Descriptor instead. func (*ApproveAllDraftChunksResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{184} + return file_openshell_proto_rawDescGZIP(), []int{194} } func (x *ApproveAllDraftChunksResponse) GetPolicyVersion() uint32 { @@ -13282,7 +14221,7 @@ type EditDraftChunkRequest struct { func (x *EditDraftChunkRequest) Reset() { *x = EditDraftChunkRequest{} - mi := &file_openshell_proto_msgTypes[185] + mi := &file_openshell_proto_msgTypes[195] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13294,7 +14233,7 @@ func (x *EditDraftChunkRequest) String() string { func (*EditDraftChunkRequest) ProtoMessage() {} func (x *EditDraftChunkRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[185] + mi := &file_openshell_proto_msgTypes[195] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13307,7 +14246,7 @@ func (x *EditDraftChunkRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EditDraftChunkRequest.ProtoReflect.Descriptor instead. func (*EditDraftChunkRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{185} + return file_openshell_proto_rawDescGZIP(), []int{195} } func (x *EditDraftChunkRequest) GetName() string { @@ -13346,7 +14285,7 @@ type EditDraftChunkResponse struct { func (x *EditDraftChunkResponse) Reset() { *x = EditDraftChunkResponse{} - mi := &file_openshell_proto_msgTypes[186] + mi := &file_openshell_proto_msgTypes[196] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13358,7 +14297,7 @@ func (x *EditDraftChunkResponse) String() string { func (*EditDraftChunkResponse) ProtoMessage() {} func (x *EditDraftChunkResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[186] + mi := &file_openshell_proto_msgTypes[196] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13371,7 +14310,7 @@ func (x *EditDraftChunkResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EditDraftChunkResponse.ProtoReflect.Descriptor instead. func (*EditDraftChunkResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{186} + return file_openshell_proto_rawDescGZIP(), []int{196} } // Reverse an approval (remove merged rule from active policy). @@ -13389,7 +14328,7 @@ type UndoDraftChunkRequest struct { func (x *UndoDraftChunkRequest) Reset() { *x = UndoDraftChunkRequest{} - mi := &file_openshell_proto_msgTypes[187] + mi := &file_openshell_proto_msgTypes[197] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13401,7 +14340,7 @@ func (x *UndoDraftChunkRequest) String() string { func (*UndoDraftChunkRequest) ProtoMessage() {} func (x *UndoDraftChunkRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[187] + mi := &file_openshell_proto_msgTypes[197] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13414,7 +14353,7 @@ func (x *UndoDraftChunkRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UndoDraftChunkRequest.ProtoReflect.Descriptor instead. func (*UndoDraftChunkRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{187} + return file_openshell_proto_rawDescGZIP(), []int{197} } func (x *UndoDraftChunkRequest) GetName() string { @@ -13450,7 +14389,7 @@ type UndoDraftChunkResponse struct { func (x *UndoDraftChunkResponse) Reset() { *x = UndoDraftChunkResponse{} - mi := &file_openshell_proto_msgTypes[188] + mi := &file_openshell_proto_msgTypes[198] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13462,7 +14401,7 @@ func (x *UndoDraftChunkResponse) String() string { func (*UndoDraftChunkResponse) ProtoMessage() {} func (x *UndoDraftChunkResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[188] + mi := &file_openshell_proto_msgTypes[198] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13475,7 +14414,7 @@ func (x *UndoDraftChunkResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UndoDraftChunkResponse.ProtoReflect.Descriptor instead. func (*UndoDraftChunkResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{188} + return file_openshell_proto_rawDescGZIP(), []int{198} } func (x *UndoDraftChunkResponse) GetPolicyVersion() uint32 { @@ -13505,7 +14444,7 @@ type ClearDraftChunksRequest struct { func (x *ClearDraftChunksRequest) Reset() { *x = ClearDraftChunksRequest{} - mi := &file_openshell_proto_msgTypes[189] + mi := &file_openshell_proto_msgTypes[199] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13517,7 +14456,7 @@ func (x *ClearDraftChunksRequest) String() string { func (*ClearDraftChunksRequest) ProtoMessage() {} func (x *ClearDraftChunksRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[189] + mi := &file_openshell_proto_msgTypes[199] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13530,7 +14469,7 @@ func (x *ClearDraftChunksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ClearDraftChunksRequest.ProtoReflect.Descriptor instead. func (*ClearDraftChunksRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{189} + return file_openshell_proto_rawDescGZIP(), []int{199} } func (x *ClearDraftChunksRequest) GetName() string { @@ -13557,7 +14496,7 @@ type ClearDraftChunksResponse struct { func (x *ClearDraftChunksResponse) Reset() { *x = ClearDraftChunksResponse{} - mi := &file_openshell_proto_msgTypes[190] + mi := &file_openshell_proto_msgTypes[200] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13569,7 +14508,7 @@ func (x *ClearDraftChunksResponse) String() string { func (*ClearDraftChunksResponse) ProtoMessage() {} func (x *ClearDraftChunksResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[190] + mi := &file_openshell_proto_msgTypes[200] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13582,7 +14521,7 @@ func (x *ClearDraftChunksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ClearDraftChunksResponse.ProtoReflect.Descriptor instead. func (*ClearDraftChunksResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{190} + return file_openshell_proto_rawDescGZIP(), []int{200} } func (x *ClearDraftChunksResponse) GetChunksCleared() uint32 { @@ -13605,7 +14544,7 @@ type GetDraftHistoryRequest struct { func (x *GetDraftHistoryRequest) Reset() { *x = GetDraftHistoryRequest{} - mi := &file_openshell_proto_msgTypes[191] + mi := &file_openshell_proto_msgTypes[201] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13617,7 +14556,7 @@ func (x *GetDraftHistoryRequest) String() string { func (*GetDraftHistoryRequest) ProtoMessage() {} func (x *GetDraftHistoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[191] + mi := &file_openshell_proto_msgTypes[201] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13630,7 +14569,7 @@ func (x *GetDraftHistoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDraftHistoryRequest.ProtoReflect.Descriptor instead. func (*GetDraftHistoryRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{191} + return file_openshell_proto_rawDescGZIP(), []int{201} } func (x *GetDraftHistoryRequest) GetName() string { @@ -13664,7 +14603,7 @@ type DraftHistoryEntry struct { func (x *DraftHistoryEntry) Reset() { *x = DraftHistoryEntry{} - mi := &file_openshell_proto_msgTypes[192] + mi := &file_openshell_proto_msgTypes[202] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13676,7 +14615,7 @@ func (x *DraftHistoryEntry) String() string { func (*DraftHistoryEntry) ProtoMessage() {} func (x *DraftHistoryEntry) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[192] + mi := &file_openshell_proto_msgTypes[202] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13689,7 +14628,7 @@ func (x *DraftHistoryEntry) ProtoReflect() protoreflect.Message { // Deprecated: Use DraftHistoryEntry.ProtoReflect.Descriptor instead. func (*DraftHistoryEntry) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{192} + return file_openshell_proto_rawDescGZIP(), []int{202} } func (x *DraftHistoryEntry) GetTimestampMs() int64 { @@ -13730,7 +14669,7 @@ type GetDraftHistoryResponse struct { func (x *GetDraftHistoryResponse) Reset() { *x = GetDraftHistoryResponse{} - mi := &file_openshell_proto_msgTypes[193] + mi := &file_openshell_proto_msgTypes[203] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13742,7 +14681,7 @@ func (x *GetDraftHistoryResponse) String() string { func (*GetDraftHistoryResponse) ProtoMessage() {} func (x *GetDraftHistoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[193] + mi := &file_openshell_proto_msgTypes[203] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13755,7 +14694,7 @@ func (x *GetDraftHistoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDraftHistoryResponse.ProtoReflect.Descriptor instead. func (*GetDraftHistoryResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{193} + return file_openshell_proto_rawDescGZIP(), []int{203} } func (x *GetDraftHistoryResponse) GetEntries() []*DraftHistoryEntry { @@ -13784,7 +14723,7 @@ type PolicyRevisionPayload struct { func (x *PolicyRevisionPayload) Reset() { *x = PolicyRevisionPayload{} - mi := &file_openshell_proto_msgTypes[194] + mi := &file_openshell_proto_msgTypes[204] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13796,7 +14735,7 @@ func (x *PolicyRevisionPayload) String() string { func (*PolicyRevisionPayload) ProtoMessage() {} func (x *PolicyRevisionPayload) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[194] + mi := &file_openshell_proto_msgTypes[204] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13809,7 +14748,7 @@ func (x *PolicyRevisionPayload) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicyRevisionPayload.ProtoReflect.Descriptor instead. func (*PolicyRevisionPayload) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{194} + return file_openshell_proto_rawDescGZIP(), []int{204} } func (x *PolicyRevisionPayload) GetPolicy() *sandboxv1.SandboxPolicy { @@ -13888,7 +14827,7 @@ type DraftChunkPayload struct { func (x *DraftChunkPayload) Reset() { *x = DraftChunkPayload{} - mi := &file_openshell_proto_msgTypes[195] + mi := &file_openshell_proto_msgTypes[205] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13900,7 +14839,7 @@ func (x *DraftChunkPayload) String() string { func (*DraftChunkPayload) ProtoMessage() {} func (x *DraftChunkPayload) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[195] + mi := &file_openshell_proto_msgTypes[205] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13913,7 +14852,7 @@ func (x *DraftChunkPayload) ProtoReflect() protoreflect.Message { // Deprecated: Use DraftChunkPayload.ProtoReflect.Descriptor instead. func (*DraftChunkPayload) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{195} + return file_openshell_proto_rawDescGZIP(), []int{205} } func (x *DraftChunkPayload) GetRuleName() string { @@ -14061,7 +15000,7 @@ type StoredPolicyRevision struct { func (x *StoredPolicyRevision) Reset() { *x = StoredPolicyRevision{} - mi := &file_openshell_proto_msgTypes[196] + mi := &file_openshell_proto_msgTypes[206] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14073,7 +15012,7 @@ func (x *StoredPolicyRevision) String() string { func (*StoredPolicyRevision) ProtoMessage() {} func (x *StoredPolicyRevision) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[196] + mi := &file_openshell_proto_msgTypes[206] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14086,7 +15025,7 @@ func (x *StoredPolicyRevision) ProtoReflect() protoreflect.Message { // Deprecated: Use StoredPolicyRevision.ProtoReflect.Descriptor instead. func (*StoredPolicyRevision) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{196} + return file_openshell_proto_rawDescGZIP(), []int{206} } func (x *StoredPolicyRevision) GetId() string { @@ -14195,7 +15134,7 @@ type StoredDraftChunk struct { func (x *StoredDraftChunk) Reset() { *x = StoredDraftChunk{} - mi := &file_openshell_proto_msgTypes[197] + mi := &file_openshell_proto_msgTypes[207] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14207,7 +15146,7 @@ func (x *StoredDraftChunk) String() string { func (*StoredDraftChunk) ProtoMessage() {} func (x *StoredDraftChunk) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[197] + mi := &file_openshell_proto_msgTypes[207] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14220,7 +15159,7 @@ func (x *StoredDraftChunk) ProtoReflect() protoreflect.Message { // Deprecated: Use StoredDraftChunk.ProtoReflect.Descriptor instead. func (*StoredDraftChunk) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{197} + return file_openshell_proto_rawDescGZIP(), []int{207} } func (x *StoredDraftChunk) GetId() string { @@ -14411,7 +15350,7 @@ type CreateWorkspaceRequest struct { func (x *CreateWorkspaceRequest) Reset() { *x = CreateWorkspaceRequest{} - mi := &file_openshell_proto_msgTypes[198] + mi := &file_openshell_proto_msgTypes[208] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14423,7 +15362,7 @@ func (x *CreateWorkspaceRequest) String() string { func (*CreateWorkspaceRequest) ProtoMessage() {} func (x *CreateWorkspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[198] + mi := &file_openshell_proto_msgTypes[208] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14436,7 +15375,7 @@ func (x *CreateWorkspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateWorkspaceRequest.ProtoReflect.Descriptor instead. func (*CreateWorkspaceRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{198} + return file_openshell_proto_rawDescGZIP(), []int{208} } func (x *CreateWorkspaceRequest) GetName() string { @@ -14463,7 +15402,7 @@ type CreateWorkspaceResponse struct { func (x *CreateWorkspaceResponse) Reset() { *x = CreateWorkspaceResponse{} - mi := &file_openshell_proto_msgTypes[199] + mi := &file_openshell_proto_msgTypes[209] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14475,7 +15414,7 @@ func (x *CreateWorkspaceResponse) String() string { func (*CreateWorkspaceResponse) ProtoMessage() {} func (x *CreateWorkspaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[199] + mi := &file_openshell_proto_msgTypes[209] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14488,7 +15427,7 @@ func (x *CreateWorkspaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateWorkspaceResponse.ProtoReflect.Descriptor instead. func (*CreateWorkspaceResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{199} + return file_openshell_proto_rawDescGZIP(), []int{209} } func (x *CreateWorkspaceResponse) GetWorkspace() *datamodelv1.Workspace { @@ -14509,7 +15448,7 @@ type GetWorkspaceRequest struct { func (x *GetWorkspaceRequest) Reset() { *x = GetWorkspaceRequest{} - mi := &file_openshell_proto_msgTypes[200] + mi := &file_openshell_proto_msgTypes[210] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14521,7 +15460,7 @@ func (x *GetWorkspaceRequest) String() string { func (*GetWorkspaceRequest) ProtoMessage() {} func (x *GetWorkspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[200] + mi := &file_openshell_proto_msgTypes[210] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14534,7 +15473,7 @@ func (x *GetWorkspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWorkspaceRequest.ProtoReflect.Descriptor instead. func (*GetWorkspaceRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{200} + return file_openshell_proto_rawDescGZIP(), []int{210} } func (x *GetWorkspaceRequest) GetName() string { @@ -14554,7 +15493,7 @@ type GetWorkspaceResponse struct { func (x *GetWorkspaceResponse) Reset() { *x = GetWorkspaceResponse{} - mi := &file_openshell_proto_msgTypes[201] + mi := &file_openshell_proto_msgTypes[211] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14566,7 +15505,7 @@ func (x *GetWorkspaceResponse) String() string { func (*GetWorkspaceResponse) ProtoMessage() {} func (x *GetWorkspaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[201] + mi := &file_openshell_proto_msgTypes[211] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14579,7 +15518,7 @@ func (x *GetWorkspaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWorkspaceResponse.ProtoReflect.Descriptor instead. func (*GetWorkspaceResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{201} + return file_openshell_proto_rawDescGZIP(), []int{211} } func (x *GetWorkspaceResponse) GetWorkspace() *datamodelv1.Workspace { @@ -14602,7 +15541,7 @@ type ListWorkspacesRequest struct { func (x *ListWorkspacesRequest) Reset() { *x = ListWorkspacesRequest{} - mi := &file_openshell_proto_msgTypes[202] + mi := &file_openshell_proto_msgTypes[212] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14614,7 +15553,7 @@ func (x *ListWorkspacesRequest) String() string { func (*ListWorkspacesRequest) ProtoMessage() {} func (x *ListWorkspacesRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[202] + mi := &file_openshell_proto_msgTypes[212] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14627,7 +15566,7 @@ func (x *ListWorkspacesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkspacesRequest.ProtoReflect.Descriptor instead. func (*ListWorkspacesRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{202} + return file_openshell_proto_rawDescGZIP(), []int{212} } func (x *ListWorkspacesRequest) GetLimit() uint32 { @@ -14661,7 +15600,7 @@ type ListWorkspacesResponse struct { func (x *ListWorkspacesResponse) Reset() { *x = ListWorkspacesResponse{} - mi := &file_openshell_proto_msgTypes[203] + mi := &file_openshell_proto_msgTypes[213] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14673,7 +15612,7 @@ func (x *ListWorkspacesResponse) String() string { func (*ListWorkspacesResponse) ProtoMessage() {} func (x *ListWorkspacesResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[203] + mi := &file_openshell_proto_msgTypes[213] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14686,7 +15625,7 @@ func (x *ListWorkspacesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkspacesResponse.ProtoReflect.Descriptor instead. func (*ListWorkspacesResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{203} + return file_openshell_proto_rawDescGZIP(), []int{213} } func (x *ListWorkspacesResponse) GetWorkspaces() []*datamodelv1.Workspace { @@ -14707,7 +15646,7 @@ type DeleteWorkspaceRequest struct { func (x *DeleteWorkspaceRequest) Reset() { *x = DeleteWorkspaceRequest{} - mi := &file_openshell_proto_msgTypes[204] + mi := &file_openshell_proto_msgTypes[214] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14719,7 +15658,7 @@ func (x *DeleteWorkspaceRequest) String() string { func (*DeleteWorkspaceRequest) ProtoMessage() {} func (x *DeleteWorkspaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[204] + mi := &file_openshell_proto_msgTypes[214] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14732,7 +15671,7 @@ func (x *DeleteWorkspaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteWorkspaceRequest.ProtoReflect.Descriptor instead. func (*DeleteWorkspaceRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{204} + return file_openshell_proto_rawDescGZIP(), []int{214} } func (x *DeleteWorkspaceRequest) GetName() string { @@ -14752,7 +15691,7 @@ type DeleteWorkspaceResponse struct { func (x *DeleteWorkspaceResponse) Reset() { *x = DeleteWorkspaceResponse{} - mi := &file_openshell_proto_msgTypes[205] + mi := &file_openshell_proto_msgTypes[215] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14764,7 +15703,7 @@ func (x *DeleteWorkspaceResponse) String() string { func (*DeleteWorkspaceResponse) ProtoMessage() {} func (x *DeleteWorkspaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[205] + mi := &file_openshell_proto_msgTypes[215] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14777,7 +15716,7 @@ func (x *DeleteWorkspaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteWorkspaceResponse.ProtoReflect.Descriptor instead. func (*DeleteWorkspaceResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{205} + return file_openshell_proto_rawDescGZIP(), []int{215} } func (x *DeleteWorkspaceResponse) GetDeleted() bool { @@ -14801,7 +15740,7 @@ type WorkspaceMember struct { func (x *WorkspaceMember) Reset() { *x = WorkspaceMember{} - mi := &file_openshell_proto_msgTypes[206] + mi := &file_openshell_proto_msgTypes[216] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14813,7 +15752,7 @@ func (x *WorkspaceMember) String() string { func (*WorkspaceMember) ProtoMessage() {} func (x *WorkspaceMember) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[206] + mi := &file_openshell_proto_msgTypes[216] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14826,7 +15765,7 @@ func (x *WorkspaceMember) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkspaceMember.ProtoReflect.Descriptor instead. func (*WorkspaceMember) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{206} + return file_openshell_proto_rawDescGZIP(), []int{216} } func (x *WorkspaceMember) GetMetadata() *datamodelv1.ObjectMeta { @@ -14865,7 +15804,7 @@ type AddWorkspaceMemberRequest struct { func (x *AddWorkspaceMemberRequest) Reset() { *x = AddWorkspaceMemberRequest{} - mi := &file_openshell_proto_msgTypes[207] + mi := &file_openshell_proto_msgTypes[217] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14877,7 +15816,7 @@ func (x *AddWorkspaceMemberRequest) String() string { func (*AddWorkspaceMemberRequest) ProtoMessage() {} func (x *AddWorkspaceMemberRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[207] + mi := &file_openshell_proto_msgTypes[217] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14890,7 +15829,7 @@ func (x *AddWorkspaceMemberRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddWorkspaceMemberRequest.ProtoReflect.Descriptor instead. func (*AddWorkspaceMemberRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{207} + return file_openshell_proto_rawDescGZIP(), []int{217} } func (x *AddWorkspaceMemberRequest) GetWorkspace() string { @@ -14924,7 +15863,7 @@ type AddWorkspaceMemberResponse struct { func (x *AddWorkspaceMemberResponse) Reset() { *x = AddWorkspaceMemberResponse{} - mi := &file_openshell_proto_msgTypes[208] + mi := &file_openshell_proto_msgTypes[218] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14936,7 +15875,7 @@ func (x *AddWorkspaceMemberResponse) String() string { func (*AddWorkspaceMemberResponse) ProtoMessage() {} func (x *AddWorkspaceMemberResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[208] + mi := &file_openshell_proto_msgTypes[218] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14949,7 +15888,7 @@ func (x *AddWorkspaceMemberResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddWorkspaceMemberResponse.ProtoReflect.Descriptor instead. func (*AddWorkspaceMemberResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{208} + return file_openshell_proto_rawDescGZIP(), []int{218} } func (x *AddWorkspaceMemberResponse) GetMember() *WorkspaceMember { @@ -14972,7 +15911,7 @@ type RemoveWorkspaceMemberRequest struct { func (x *RemoveWorkspaceMemberRequest) Reset() { *x = RemoveWorkspaceMemberRequest{} - mi := &file_openshell_proto_msgTypes[209] + mi := &file_openshell_proto_msgTypes[219] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14984,7 +15923,7 @@ func (x *RemoveWorkspaceMemberRequest) String() string { func (*RemoveWorkspaceMemberRequest) ProtoMessage() {} func (x *RemoveWorkspaceMemberRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[209] + mi := &file_openshell_proto_msgTypes[219] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14997,7 +15936,7 @@ func (x *RemoveWorkspaceMemberRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveWorkspaceMemberRequest.ProtoReflect.Descriptor instead. func (*RemoveWorkspaceMemberRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{209} + return file_openshell_proto_rawDescGZIP(), []int{219} } func (x *RemoveWorkspaceMemberRequest) GetWorkspace() string { @@ -15024,7 +15963,7 @@ type RemoveWorkspaceMemberResponse struct { func (x *RemoveWorkspaceMemberResponse) Reset() { *x = RemoveWorkspaceMemberResponse{} - mi := &file_openshell_proto_msgTypes[210] + mi := &file_openshell_proto_msgTypes[220] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15036,7 +15975,7 @@ func (x *RemoveWorkspaceMemberResponse) String() string { func (*RemoveWorkspaceMemberResponse) ProtoMessage() {} func (x *RemoveWorkspaceMemberResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[210] + mi := &file_openshell_proto_msgTypes[220] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15049,7 +15988,7 @@ func (x *RemoveWorkspaceMemberResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveWorkspaceMemberResponse.ProtoReflect.Descriptor instead. func (*RemoveWorkspaceMemberResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{210} + return file_openshell_proto_rawDescGZIP(), []int{220} } func (x *RemoveWorkspaceMemberResponse) GetRemoved() bool { @@ -15072,7 +16011,7 @@ type ListWorkspaceMembersRequest struct { func (x *ListWorkspaceMembersRequest) Reset() { *x = ListWorkspaceMembersRequest{} - mi := &file_openshell_proto_msgTypes[211] + mi := &file_openshell_proto_msgTypes[221] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15084,7 +16023,7 @@ func (x *ListWorkspaceMembersRequest) String() string { func (*ListWorkspaceMembersRequest) ProtoMessage() {} func (x *ListWorkspaceMembersRequest) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[211] + mi := &file_openshell_proto_msgTypes[221] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15097,7 +16036,7 @@ func (x *ListWorkspaceMembersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkspaceMembersRequest.ProtoReflect.Descriptor instead. func (*ListWorkspaceMembersRequest) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{211} + return file_openshell_proto_rawDescGZIP(), []int{221} } func (x *ListWorkspaceMembersRequest) GetWorkspace() string { @@ -15131,7 +16070,7 @@ type ListWorkspaceMembersResponse struct { func (x *ListWorkspaceMembersResponse) Reset() { *x = ListWorkspaceMembersResponse{} - mi := &file_openshell_proto_msgTypes[212] + mi := &file_openshell_proto_msgTypes[222] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15143,7 +16082,7 @@ func (x *ListWorkspaceMembersResponse) String() string { func (*ListWorkspaceMembersResponse) ProtoMessage() {} func (x *ListWorkspaceMembersResponse) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[212] + mi := &file_openshell_proto_msgTypes[222] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15156,7 +16095,7 @@ func (x *ListWorkspaceMembersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkspaceMembersResponse.ProtoReflect.Descriptor instead. func (*ListWorkspaceMembersResponse) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{212} + return file_openshell_proto_rawDescGZIP(), []int{222} } func (x *ListWorkspaceMembersResponse) GetMembers() []*WorkspaceMember { @@ -15184,7 +16123,7 @@ type ExtensionServiceCredential struct { func (x *ExtensionServiceCredential) Reset() { *x = ExtensionServiceCredential{} - mi := &file_openshell_proto_msgTypes[213] + mi := &file_openshell_proto_msgTypes[223] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15196,7 +16135,7 @@ func (x *ExtensionServiceCredential) String() string { func (*ExtensionServiceCredential) ProtoMessage() {} func (x *ExtensionServiceCredential) ProtoReflect() protoreflect.Message { - mi := &file_openshell_proto_msgTypes[213] + mi := &file_openshell_proto_msgTypes[223] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15209,7 +16148,7 @@ func (x *ExtensionServiceCredential) ProtoReflect() protoreflect.Message { // Deprecated: Use ExtensionServiceCredential.ProtoReflect.Descriptor instead. func (*ExtensionServiceCredential) Descriptor() ([]byte, []int) { - return file_openshell_proto_rawDescGZIP(), []int{213} + return file_openshell_proto_rawDescGZIP(), []int{223} } func (x *ExtensionServiceCredential) GetServiceName() string { @@ -15899,7 +16838,21 @@ const file_openshell_proto_rawDesc = "" + "\x05value\x18\x02 \x01(\v2'.openshell.v1.ProviderProfileCredentialR\x05value:\x028\x01\x1ar\n" + "\x1dStaticCredentialBindingsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12;\n" + - "\x05value\x18\x02 \x01(\v2%.openshell.v1.StaticCredentialBindingR\x05value:\x028\x01\"\xbd\x01\n" + + "\x05value\x18\x02 \x01(\v2%.openshell.v1.StaticCredentialBindingR\x05value:\x028\x01\"\xc6\x02\n" + + "\x18ProviderEnvironmentValue\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x1a\n" + + "\x05value\x18\x02 \x01(\tB\x04\x88\xb5\x18\x01R\x05value\x12'\n" + + "\rexpires_at_ms\x18\x03 \x01(\x03H\x00R\vexpiresAtMs\x88\x01\x01\x12\\\n" + + "\x0eclassification\x18\x04 \x01(\x0e24.openshell.v1.ProviderEnvironmentValueClassificationR\x0eclassification\x12a\n" + + "\x19static_credential_binding\x18\x05 \x01(\v2%.openshell.v1.StaticCredentialBindingR\x17staticCredentialBindingB\x10\n" + + "\x0e_expires_at_ms\"\xf5\x02\n" + + "\x1bProviderEnvironmentSnapshot\x122\n" + + "\x15provider_env_revision\x18\x01 \x01(\x04R\x13providerEnvRevision\x12>\n" + + "\x06values\x18\x02 \x03(\v2&.openshell.v1.ProviderEnvironmentValueR\x06values\x12r\n" + + "\x13dynamic_credentials\x18\x03 \x03(\v2A.openshell.v1.ProviderEnvironmentSnapshot.DynamicCredentialsEntryR\x12dynamicCredentials\x1an\n" + + "\x17DynamicCredentialsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12=\n" + + "\x05value\x18\x02 \x01(\v2'.openshell.v1.ProviderProfileCredentialR\x05value:\x028\x01\"\xbd\x01\n" + "#ExchangeProviderSubjectTokenRequest\x12\x1d\n" + "\n" + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\x12\x1a\n" + @@ -16025,14 +16978,16 @@ const file_openshell_proto_rawDesc = "" + "\x17PushSandboxLogsResponse\"m\n" + "\x16GetSandboxLogsResponse\x120\n" + "\x04logs\x18\x01 \x03(\v2\x1c.openshell.v1.SandboxLogLineR\x04logs\x12!\n" + - "\fbuffer_total\x18\x02 \x01(\rR\vbufferTotal\"\xa2\x02\n" + + "\fbuffer_total\x18\x02 \x01(\rR\vbufferTotal\"\xd7\x03\n" + "\x11SupervisorMessage\x125\n" + "\x05hello\x18\x01 \x01(\v2\x1d.openshell.v1.SupervisorHelloH\x00R\x05hello\x12A\n" + "\theartbeat\x18\x02 \x01(\v2!.openshell.v1.SupervisorHeartbeatH\x00R\theartbeat\x12K\n" + "\x11relay_open_result\x18\x03 \x01(\v2\x1d.openshell.v1.RelayOpenResultH\x00R\x0frelayOpenResult\x12;\n" + "\vrelay_close\x18\x04 \x01(\v2\x18.openshell.v1.RelayCloseH\x00R\n" + - "relayCloseB\t\n" + - "\apayload\"\xea\x02\n" + + "relayClose\x12T\n" + + "\x14config_update_result\x18\x05 \x01(\v2 .openshell.v1.ConfigUpdateResultH\x00R\x12configUpdateResult\x12]\n" + + "\x17config_bootstrap_result\x18\x06 \x01(\v2#.openshell.v1.ConfigBootstrapResultH\x00R\x15configBootstrapResultB\t\n" + + "\apayload\"\xad\x03\n" + "\x0eGatewayMessage\x12J\n" + "\x10session_accepted\x18\x01 \x01(\v2\x1d.openshell.v1.SessionAcceptedH\x00R\x0fsessionAccepted\x12J\n" + "\x10session_rejected\x18\x02 \x01(\v2\x1d.openshell.v1.SessionRejectedH\x00R\x0fsessionRejected\x12>\n" + @@ -16040,17 +16995,55 @@ const file_openshell_proto_rawDesc = "" + "\n" + "relay_open\x18\x04 \x01(\v2\x17.openshell.v1.RelayOpenH\x00R\trelayOpen\x12;\n" + "\vrelay_close\x18\x05 \x01(\v2\x18.openshell.v1.RelayCloseH\x00R\n" + - "relayCloseB\t\n" + - "\apayload\"Q\n" + + "relayClose\x12A\n" + + "\rconfig_update\x18\x06 \x01(\v2\x1a.openshell.v1.ConfigUpdateH\x00R\fconfigUpdateB\t\n" + + "\apayload\"~\n" + "\x0fSupervisorHello\x12\x1d\n" + "\n" + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\x12\x1f\n" + "\vinstance_id\x18\x02 \x01(\tR\n" + - "instanceId\"h\n" + + "instanceId\x12+\n" + + "\x11protocol_revision\x18\x03 \x01(\rR\x10protocolRevision\"\xd2\x01\n" + "\x0fSessionAccepted\x12\x1d\n" + "\n" + "session_id\x18\x01 \x01(\tR\tsessionId\x126\n" + - "\x17heartbeat_interval_secs\x18\x02 \x01(\rR\x15heartbeatIntervalSecs\")\n" + + "\x17heartbeat_interval_secs\x18\x02 \x01(\rR\x15heartbeatIntervalSecs\x12;\n" + + "\tbootstrap\x18\x03 \x01(\v2\x1d.openshell.v1.ConfigBootstrapR\tbootstrap\x12+\n" + + "\x11protocol_revision\x18\x04 \x01(\rR\x10protocolRevision\"\xc3\x01\n" + + "\x0fConfigBootstrap\x12R\n" + + "\x0esandbox_config\x18\x01 \x01(\v2+.openshell.sandbox.v1.SandboxConfigSnapshotR\rsandboxConfig\x12\\\n" + + "\x14provider_environment\x18\x02 \x01(\v2).openshell.v1.ProviderEnvironmentSnapshotR\x13providerEnvironment\"\x9d\x02\n" + + "\fConfigUpdate\x12\x1b\n" + + "\tupdate_id\x18\x01 \x01(\tR\bupdateId\x12-\n" + + "\x12component_sequence\x18\x02 \x01(\x04R\x11componentSequence\x12T\n" + + "\x0esandbox_config\x18\x03 \x01(\v2+.openshell.sandbox.v1.SandboxConfigSnapshotH\x00R\rsandboxConfig\x12^\n" + + "\x14provider_environment\x18\x04 \x01(\v2).openshell.v1.ProviderEnvironmentSnapshotH\x00R\x13providerEnvironmentB\v\n" + + "\tcomponent\"\xa8\x01\n" + + "\x16ConfigSnapshotRevision\x12L\n" + + "\x0esandbox_config\x18\x01 \x01(\v2#.openshell.v1.SandboxConfigRevisionH\x00R\rsandboxConfig\x123\n" + + "\x14provider_environment\x18\x02 \x01(\x04H\x00R\x13providerEnvironmentB\v\n" + + "\tcomponent\"\xe4\x01\n" + + "\x15SandboxConfigRevision\x12'\n" + + "\x0fconfig_revision\x18\x01 \x01(\x04R\x0econfigRevision\x12%\n" + + "\x0epolicy_version\x18\x02 \x01(\rR\rpolicyVersion\x12G\n" + + "\rpolicy_source\x18\x03 \x01(\x0e2\".openshell.sandbox.v1.PolicySourceR\fpolicySource\x122\n" + + "\x15global_policy_version\x18\x04 \x01(\rR\x13globalPolicyVersion\"`\n" + + "\x12ConfigApplyFailure\x12\x12\n" + + "\x04code\x18\x01 \x01(\tR\x04code\x12\x18\n" + + "\amessage\x18\x02 \x01(\tR\amessage\x12\x1c\n" + + "\tretryable\x18\x03 \x01(\bR\tretryable\"\xf7\x02\n" + + "\x1aConfigComponentApplyResult\x12;\n" + + "\tcomponent\x18\x01 \x01(\x0e2\x1d.openshell.v1.ConfigComponentR\tcomponent\x12S\n" + + "\x12requested_revision\x18\x02 \x01(\v2$.openshell.v1.ConfigSnapshotRevisionR\x11requestedRevision\x12O\n" + + "\x10applied_revision\x18\x03 \x01(\v2$.openshell.v1.ConfigSnapshotRevisionR\x0fappliedRevision\x12:\n" + + "\aoutcome\x18\x04 \x01(\x0e2 .openshell.v1.ConfigApplyOutcomeR\aoutcome\x12:\n" + + "\afailure\x18\x05 \x01(\v2 .openshell.v1.ConfigApplyFailureR\afailure\"\xa2\x01\n" + + "\x12ConfigUpdateResult\x12\x1b\n" + + "\tupdate_id\x18\x01 \x01(\tR\bupdateId\x12-\n" + + "\x12component_sequence\x18\x02 \x01(\x04R\x11componentSequence\x12@\n" + + "\x06result\x18\x03 \x01(\v2(.openshell.v1.ConfigComponentApplyResultR\x06result\"[\n" + + "\x15ConfigBootstrapResult\x12B\n" + + "\aresults\x18\x01 \x03(\v2(.openshell.v1.ConfigComponentApplyResultR\aresults\")\n" + "\x0fSessionRejected\x12\x16\n" + "\x06reason\x18\x01 \x01(\tR\x06reason\"\x15\n" + "\x13SupervisorHeartbeat\"\x12\n" + @@ -16421,13 +17414,31 @@ const file_openshell_proto_rawDesc = "" + "(PROVIDER_PROFILE_CATEGORY_SOURCE_CONTROL\x10\x04\x12'\n" + "#PROVIDER_PROFILE_CATEGORY_MESSAGING\x10\x05\x12\"\n" + "\x1ePROVIDER_PROFILE_CATEGORY_DATA\x10\x06\x12'\n" + - "#PROVIDER_PROFILE_CATEGORY_KNOWLEDGE\x10\a*\x9a\x01\n" + + "#PROVIDER_PROFILE_CATEGORY_KNOWLEDGE\x10\a*\xde\x01\n" + + "&ProviderEnvironmentValueClassification\x129\n" + + "5PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_UNSPECIFIED\x10\x00\x128\n" + + "4PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_NON_SECRET\x10\x01\x12?\n" + + ";PROVIDER_ENVIRONMENT_VALUE_CLASSIFICATION_STATIC_CREDENTIAL\x10\x02*\x9a\x01\n" + "\fPolicyStatus\x12\x1d\n" + "\x19POLICY_STATUS_UNSPECIFIED\x10\x00\x12\x19\n" + "\x15POLICY_STATUS_PENDING\x10\x01\x12\x18\n" + "\x14POLICY_STATUS_LOADED\x10\x02\x12\x18\n" + "\x14POLICY_STATUS_FAILED\x10\x03\x12\x1c\n" + - "\x18POLICY_STATUS_SUPERSEDED\x10\x04*\x86\x01\n" + + "\x18POLICY_STATUS_SUPERSEDED\x10\x04*\x83\x01\n" + + "\x0fConfigComponent\x12 \n" + + "\x1cCONFIG_COMPONENT_UNSPECIFIED\x10\x00\x12#\n" + + "\x1fCONFIG_COMPONENT_SANDBOX_CONFIG\x10\x01\x12)\n" + + "%CONFIG_COMPONENT_PROVIDER_ENVIRONMENT\x10\x02*\x8d\x03\n" + + "\x12ConfigApplyOutcome\x12$\n" + + " CONFIG_APPLY_OUTCOME_UNSPECIFIED\x10\x00\x12 \n" + + "\x1cCONFIG_APPLY_OUTCOME_APPLIED\x10\x01\x12*\n" + + "&CONFIG_APPLY_OUTCOME_IGNORED_DUPLICATE\x10\x02\x12&\n" + + "\"CONFIG_APPLY_OUTCOME_IGNORED_STALE\x10\x03\x120\n" + + ",CONFIG_APPLY_OUTCOME_RETAINED_LOCAL_OVERRIDE\x10\x04\x12!\n" + + "\x1dCONFIG_APPLY_OUTCOME_DEGRADED\x10\x05\x128\n" + + "4CONFIG_APPLY_OUTCOME_FAILED_RETAINED_LAST_KNOWN_GOOD\x10\x06\x12&\n" + + "\"CONFIG_APPLY_OUTCOME_FAILED_CLOSED\x10\a\x12$\n" + + " CONFIG_APPLY_OUTCOME_UNSUPPORTED\x10\b*\x86\x01\n" + "\rServiceStatus\x12\x1e\n" + "\x1aSERVICE_STATUS_UNSPECIFIED\x10\x00\x12\x1a\n" + "\x16SERVICE_STATUS_HEALTHY\x10\x01\x12\x1b\n" + @@ -16608,613 +17619,651 @@ func file_openshell_proto_rawDescGZIP() []byte { return file_openshell_proto_rawDescData } -var file_openshell_proto_enumTypes = make([]protoimpl.EnumInfo, 8) -var file_openshell_proto_msgTypes = make([]protoimpl.MessageInfo, 240) +var file_openshell_proto_enumTypes = make([]protoimpl.EnumInfo, 11) +var file_openshell_proto_msgTypes = make([]protoimpl.MessageInfo, 251) var file_openshell_proto_goTypes = []any{ (SandboxPhase)(0), // 0: openshell.v1.SandboxPhase (ProviderCredentialTokenGrantType)(0), // 1: openshell.v1.ProviderCredentialTokenGrantType (ProviderCredentialRefreshStrategy)(0), // 2: openshell.v1.ProviderCredentialRefreshStrategy (ProviderProfileCategory)(0), // 3: openshell.v1.ProviderProfileCategory - (PolicyStatus)(0), // 4: openshell.v1.PolicyStatus - (ServiceStatus)(0), // 5: openshell.v1.ServiceStatus - (WorkspaceRole)(0), // 6: openshell.v1.WorkspaceRole - (ProviderCredentialRefreshRecoveryAction)(0), // 7: openshell.v1.ProviderCredentialRefreshRecoveryAction - (*IssueSandboxTokenRequest)(nil), // 8: openshell.v1.IssueSandboxTokenRequest - (*IssueSandboxTokenResponse)(nil), // 9: openshell.v1.IssueSandboxTokenResponse - (*RefreshSandboxTokenRequest)(nil), // 10: openshell.v1.RefreshSandboxTokenRequest - (*RefreshSandboxTokenResponse)(nil), // 11: openshell.v1.RefreshSandboxTokenResponse - (*HealthRequest)(nil), // 12: openshell.v1.HealthRequest - (*HealthResponse)(nil), // 13: openshell.v1.HealthResponse - (*GetCurrentUserRequest)(nil), // 14: openshell.v1.GetCurrentUserRequest - (*GetCurrentUserResponse)(nil), // 15: openshell.v1.GetCurrentUserResponse - (*GetGatewayInfoRequest)(nil), // 16: openshell.v1.GetGatewayInfoRequest - (*GetGatewayInfoResponse)(nil), // 17: openshell.v1.GetGatewayInfoResponse - (*ComputeDriverInfo)(nil), // 18: openshell.v1.ComputeDriverInfo - (*ComputeDriverCapabilities)(nil), // 19: openshell.v1.ComputeDriverCapabilities - (*ResourceCapabilities)(nil), // 20: openshell.v1.ResourceCapabilities - (*CpuResourceCapabilities)(nil), // 21: openshell.v1.CpuResourceCapabilities - (*MemoryResourceCapabilities)(nil), // 22: openshell.v1.MemoryResourceCapabilities - (*GpuResourceCapabilities)(nil), // 23: openshell.v1.GpuResourceCapabilities - (*Sandbox)(nil), // 24: openshell.v1.Sandbox - (*SandboxSpec)(nil), // 25: openshell.v1.SandboxSpec - (*ResourceRequirements)(nil), // 26: openshell.v1.ResourceRequirements - (*GpuResourceRequirements)(nil), // 27: openshell.v1.GpuResourceRequirements - (*SandboxTemplate)(nil), // 28: openshell.v1.SandboxTemplate - (*SandboxWorkloadTemplate)(nil), // 29: openshell.v1.SandboxWorkloadTemplate - (*SandboxWorkloadTemplateSpec)(nil), // 30: openshell.v1.SandboxWorkloadTemplateSpec - (*SandboxWorkloadConfig)(nil), // 31: openshell.v1.SandboxWorkloadConfig - (*SandboxResources)(nil), // 32: openshell.v1.SandboxResources - (*SandboxServiceLevel)(nil), // 33: openshell.v1.SandboxServiceLevel - (*SandboxStartup)(nil), // 34: openshell.v1.SandboxStartup - (*SandboxWorkloadTemplateProvenance)(nil), // 35: openshell.v1.SandboxWorkloadTemplateProvenance - (*SandboxStatus)(nil), // 36: openshell.v1.SandboxStatus - (*SandboxCondition)(nil), // 37: openshell.v1.SandboxCondition - (*PlatformEvent)(nil), // 38: openshell.v1.PlatformEvent - (*CreateSandboxRequest)(nil), // 39: openshell.v1.CreateSandboxRequest - (*CreateSandboxTemplateRequest)(nil), // 40: openshell.v1.CreateSandboxTemplateRequest - (*GetSandboxTemplateRequest)(nil), // 41: openshell.v1.GetSandboxTemplateRequest - (*ListSandboxTemplatesRequest)(nil), // 42: openshell.v1.ListSandboxTemplatesRequest - (*DeleteSandboxTemplateRequest)(nil), // 43: openshell.v1.DeleteSandboxTemplateRequest - (*SandboxTemplateResponse)(nil), // 44: openshell.v1.SandboxTemplateResponse - (*ListSandboxTemplatesResponse)(nil), // 45: openshell.v1.ListSandboxTemplatesResponse - (*DeleteSandboxTemplateResponse)(nil), // 46: openshell.v1.DeleteSandboxTemplateResponse - (*BeginRootfsTarStagingRequest)(nil), // 47: openshell.v1.BeginRootfsTarStagingRequest - (*BeginRootfsTarStagingResponse)(nil), // 48: openshell.v1.BeginRootfsTarStagingResponse - (*GetSandboxRequest)(nil), // 49: openshell.v1.GetSandboxRequest - (*ListSandboxesRequest)(nil), // 50: openshell.v1.ListSandboxesRequest - (*ListSandboxProvidersRequest)(nil), // 51: openshell.v1.ListSandboxProvidersRequest - (*AttachSandboxProviderRequest)(nil), // 52: openshell.v1.AttachSandboxProviderRequest - (*DetachSandboxProviderRequest)(nil), // 53: openshell.v1.DetachSandboxProviderRequest - (*DeleteSandboxRequest)(nil), // 54: openshell.v1.DeleteSandboxRequest - (*StopSandboxRequest)(nil), // 55: openshell.v1.StopSandboxRequest - (*StartSandboxRequest)(nil), // 56: openshell.v1.StartSandboxRequest - (*SandboxResponse)(nil), // 57: openshell.v1.SandboxResponse - (*ListSandboxesResponse)(nil), // 58: openshell.v1.ListSandboxesResponse - (*ListSandboxProvidersResponse)(nil), // 59: openshell.v1.ListSandboxProvidersResponse - (*AttachSandboxProviderResponse)(nil), // 60: openshell.v1.AttachSandboxProviderResponse - (*DetachSandboxProviderResponse)(nil), // 61: openshell.v1.DetachSandboxProviderResponse - (*DeleteSandboxResponse)(nil), // 62: openshell.v1.DeleteSandboxResponse - (*CreateSshSessionRequest)(nil), // 63: openshell.v1.CreateSshSessionRequest - (*CreateSshSessionResponse)(nil), // 64: openshell.v1.CreateSshSessionResponse - (*ExposeServiceRequest)(nil), // 65: openshell.v1.ExposeServiceRequest - (*GetServiceRequest)(nil), // 66: openshell.v1.GetServiceRequest - (*ListServicesRequest)(nil), // 67: openshell.v1.ListServicesRequest - (*ListServicesResponse)(nil), // 68: openshell.v1.ListServicesResponse - (*DeleteServiceRequest)(nil), // 69: openshell.v1.DeleteServiceRequest - (*DeleteServiceResponse)(nil), // 70: openshell.v1.DeleteServiceResponse - (*ServiceEndpoint)(nil), // 71: openshell.v1.ServiceEndpoint - (*ServiceEndpointResponse)(nil), // 72: openshell.v1.ServiceEndpointResponse - (*RevokeSshSessionRequest)(nil), // 73: openshell.v1.RevokeSshSessionRequest - (*RevokeSshSessionResponse)(nil), // 74: openshell.v1.RevokeSshSessionResponse - (*ExecSandboxRequest)(nil), // 75: openshell.v1.ExecSandboxRequest - (*ExecSandboxStdout)(nil), // 76: openshell.v1.ExecSandboxStdout - (*ExecSandboxStderr)(nil), // 77: openshell.v1.ExecSandboxStderr - (*ExecSandboxExit)(nil), // 78: openshell.v1.ExecSandboxExit - (*ExecSandboxEvent)(nil), // 79: openshell.v1.ExecSandboxEvent - (*TcpForwardInit)(nil), // 80: openshell.v1.TcpForwardInit - (*TcpForwardFrame)(nil), // 81: openshell.v1.TcpForwardFrame - (*ExecSandboxInput)(nil), // 82: openshell.v1.ExecSandboxInput - (*ExecSandboxWindowResize)(nil), // 83: openshell.v1.ExecSandboxWindowResize - (*SshSession)(nil), // 84: openshell.v1.SshSession - (*WatchSandboxRequest)(nil), // 85: openshell.v1.WatchSandboxRequest - (*SandboxStreamEvent)(nil), // 86: openshell.v1.SandboxStreamEvent - (*SandboxLogLine)(nil), // 87: openshell.v1.SandboxLogLine - (*SandboxStreamWarning)(nil), // 88: openshell.v1.SandboxStreamWarning - (*CreateProviderRequest)(nil), // 89: openshell.v1.CreateProviderRequest - (*GetProviderRequest)(nil), // 90: openshell.v1.GetProviderRequest - (*ListProvidersRequest)(nil), // 91: openshell.v1.ListProvidersRequest - (*UpdateProviderRequest)(nil), // 92: openshell.v1.UpdateProviderRequest - (*DeleteProviderRequest)(nil), // 93: openshell.v1.DeleteProviderRequest - (*ProviderResponse)(nil), // 94: openshell.v1.ProviderResponse - (*ListProvidersResponse)(nil), // 95: openshell.v1.ListProvidersResponse - (*ListProviderProfilesRequest)(nil), // 96: openshell.v1.ListProviderProfilesRequest - (*GetProviderProfileRequest)(nil), // 97: openshell.v1.GetProviderProfileRequest - (*ProviderProfileImportItem)(nil), // 98: openshell.v1.ProviderProfileImportItem - (*ProviderProfileDiagnostic)(nil), // 99: openshell.v1.ProviderProfileDiagnostic - (*ProviderCredentialTokenGrantAudienceOverride)(nil), // 100: openshell.v1.ProviderCredentialTokenGrantAudienceOverride - (*ProviderCredentialTokenGrantSubjectToken)(nil), // 101: openshell.v1.ProviderCredentialTokenGrantSubjectToken - (*ProviderCredentialTokenGrant)(nil), // 102: openshell.v1.ProviderCredentialTokenGrant - (*ProviderProfileCredential)(nil), // 103: openshell.v1.ProviderProfileCredential - (*ProviderCredentialRefreshMaterial)(nil), // 104: openshell.v1.ProviderCredentialRefreshMaterial - (*ProviderCredentialRefreshOutput)(nil), // 105: openshell.v1.ProviderCredentialRefreshOutput - (*ProviderCredentialRefresh)(nil), // 106: openshell.v1.ProviderCredentialRefresh - (*ProviderCredentialRefreshStatus)(nil), // 107: openshell.v1.ProviderCredentialRefreshStatus - (*ProviderProfileDiscovery)(nil), // 108: openshell.v1.ProviderProfileDiscovery - (*StoredProviderCredentialRefreshState)(nil), // 109: openshell.v1.StoredProviderCredentialRefreshState - (*StoredRefreshMaterialDeletion)(nil), // 110: openshell.v1.StoredRefreshMaterialDeletion - (*GetProviderRefreshStatusRequest)(nil), // 111: openshell.v1.GetProviderRefreshStatusRequest - (*GetProviderRefreshStatusResponse)(nil), // 112: openshell.v1.GetProviderRefreshStatusResponse - (*ConfigureProviderRefreshRequest)(nil), // 113: openshell.v1.ConfigureProviderRefreshRequest - (*ConfigureProviderRefreshResponse)(nil), // 114: openshell.v1.ConfigureProviderRefreshResponse - (*RotateProviderCredentialRequest)(nil), // 115: openshell.v1.RotateProviderCredentialRequest - (*RotateProviderCredentialResponse)(nil), // 116: openshell.v1.RotateProviderCredentialResponse - (*DeleteProviderRefreshRequest)(nil), // 117: openshell.v1.DeleteProviderRefreshRequest - (*DeleteProviderRefreshResponse)(nil), // 118: openshell.v1.DeleteProviderRefreshResponse - (*ProviderProfile)(nil), // 119: openshell.v1.ProviderProfile - (*StoredProviderProfile)(nil), // 120: openshell.v1.StoredProviderProfile - (*ProviderProfileResponse)(nil), // 121: openshell.v1.ProviderProfileResponse - (*ListProviderProfilesResponse)(nil), // 122: openshell.v1.ListProviderProfilesResponse - (*ImportProviderProfilesRequest)(nil), // 123: openshell.v1.ImportProviderProfilesRequest - (*ImportProviderProfilesResponse)(nil), // 124: openshell.v1.ImportProviderProfilesResponse - (*UpdateProviderProfilesRequest)(nil), // 125: openshell.v1.UpdateProviderProfilesRequest - (*UpdateProviderProfilesResponse)(nil), // 126: openshell.v1.UpdateProviderProfilesResponse - (*LintProviderProfilesRequest)(nil), // 127: openshell.v1.LintProviderProfilesRequest - (*LintProviderProfilesResponse)(nil), // 128: openshell.v1.LintProviderProfilesResponse - (*DeleteProviderResponse)(nil), // 129: openshell.v1.DeleteProviderResponse - (*DeleteProviderProfileRequest)(nil), // 130: openshell.v1.DeleteProviderProfileRequest - (*DeleteProviderProfileResponse)(nil), // 131: openshell.v1.DeleteProviderProfileResponse - (*GetSandboxProviderEnvironmentRequest)(nil), // 132: openshell.v1.GetSandboxProviderEnvironmentRequest - (*StaticCredentialEndpointBinding)(nil), // 133: openshell.v1.StaticCredentialEndpointBinding - (*StaticCredentialBinding)(nil), // 134: openshell.v1.StaticCredentialBinding - (*GetSandboxProviderEnvironmentResponse)(nil), // 135: openshell.v1.GetSandboxProviderEnvironmentResponse - (*ExchangeProviderSubjectTokenRequest)(nil), // 136: openshell.v1.ExchangeProviderSubjectTokenRequest - (*ExchangeProviderSubjectTokenResponse)(nil), // 137: openshell.v1.ExchangeProviderSubjectTokenResponse - (*UpdateConfigRequest)(nil), // 138: openshell.v1.UpdateConfigRequest - (*PolicyMergeOperation)(nil), // 139: openshell.v1.PolicyMergeOperation - (*AddNetworkRule)(nil), // 140: openshell.v1.AddNetworkRule - (*RemoveNetworkEndpoint)(nil), // 141: openshell.v1.RemoveNetworkEndpoint - (*RemoveNetworkRule)(nil), // 142: openshell.v1.RemoveNetworkRule - (*AddDenyRules)(nil), // 143: openshell.v1.AddDenyRules - (*AddAllowRules)(nil), // 144: openshell.v1.AddAllowRules - (*RemoveNetworkBinary)(nil), // 145: openshell.v1.RemoveNetworkBinary - (*UpdateConfigResponse)(nil), // 146: openshell.v1.UpdateConfigResponse - (*GetSandboxPolicyStatusRequest)(nil), // 147: openshell.v1.GetSandboxPolicyStatusRequest - (*GetSandboxPolicyStatusResponse)(nil), // 148: openshell.v1.GetSandboxPolicyStatusResponse - (*ListSandboxPoliciesRequest)(nil), // 149: openshell.v1.ListSandboxPoliciesRequest - (*ListSandboxPoliciesResponse)(nil), // 150: openshell.v1.ListSandboxPoliciesResponse - (*ReportPolicyStatusRequest)(nil), // 151: openshell.v1.ReportPolicyStatusRequest - (*ReportPolicyStatusResponse)(nil), // 152: openshell.v1.ReportPolicyStatusResponse - (*SandboxPolicyRevision)(nil), // 153: openshell.v1.SandboxPolicyRevision - (*GetSandboxLogsRequest)(nil), // 154: openshell.v1.GetSandboxLogsRequest - (*PushSandboxLogsRequest)(nil), // 155: openshell.v1.PushSandboxLogsRequest - (*PushSandboxLogsResponse)(nil), // 156: openshell.v1.PushSandboxLogsResponse - (*GetSandboxLogsResponse)(nil), // 157: openshell.v1.GetSandboxLogsResponse - (*SupervisorMessage)(nil), // 158: openshell.v1.SupervisorMessage - (*GatewayMessage)(nil), // 159: openshell.v1.GatewayMessage - (*SupervisorHello)(nil), // 160: openshell.v1.SupervisorHello - (*SessionAccepted)(nil), // 161: openshell.v1.SessionAccepted - (*SessionRejected)(nil), // 162: openshell.v1.SessionRejected - (*SupervisorHeartbeat)(nil), // 163: openshell.v1.SupervisorHeartbeat - (*GatewayHeartbeat)(nil), // 164: openshell.v1.GatewayHeartbeat - (*ReportMainProcessExitRequest)(nil), // 165: openshell.v1.ReportMainProcessExitRequest - (*ReportMainProcessExitResponse)(nil), // 166: openshell.v1.ReportMainProcessExitResponse - (*FinalizeMainProcessExitRequest)(nil), // 167: openshell.v1.FinalizeMainProcessExitRequest - (*FinalizeMainProcessExitResponse)(nil), // 168: openshell.v1.FinalizeMainProcessExitResponse - (*RelayOpen)(nil), // 169: openshell.v1.RelayOpen - (*SshRelayTarget)(nil), // 170: openshell.v1.SshRelayTarget - (*TcpRelayTarget)(nil), // 171: openshell.v1.TcpRelayTarget - (*RelayInit)(nil), // 172: openshell.v1.RelayInit - (*RelayFrame)(nil), // 173: openshell.v1.RelayFrame - (*RelayOpenResult)(nil), // 174: openshell.v1.RelayOpenResult - (*RelayClose)(nil), // 175: openshell.v1.RelayClose - (*L7RequestSample)(nil), // 176: openshell.v1.L7RequestSample - (*DenialSummary)(nil), // 177: openshell.v1.DenialSummary - (*DenialGroupCount)(nil), // 178: openshell.v1.DenialGroupCount - (*NetworkActivitySummary)(nil), // 179: openshell.v1.NetworkActivitySummary - (*PolicyChunk)(nil), // 180: openshell.v1.PolicyChunk - (*DraftPolicyUpdate)(nil), // 181: openshell.v1.DraftPolicyUpdate - (*SubmitPolicyAnalysisRequest)(nil), // 182: openshell.v1.SubmitPolicyAnalysisRequest - (*SubmitPolicyAnalysisResponse)(nil), // 183: openshell.v1.SubmitPolicyAnalysisResponse - (*GetDraftPolicyRequest)(nil), // 184: openshell.v1.GetDraftPolicyRequest - (*GetDraftPolicyResponse)(nil), // 185: openshell.v1.GetDraftPolicyResponse - (*ApproveDraftChunkRequest)(nil), // 186: openshell.v1.ApproveDraftChunkRequest - (*ApproveDraftChunkResponse)(nil), // 187: openshell.v1.ApproveDraftChunkResponse - (*RejectDraftChunkRequest)(nil), // 188: openshell.v1.RejectDraftChunkRequest - (*RejectDraftChunkResponse)(nil), // 189: openshell.v1.RejectDraftChunkResponse - (*DraftChunkApproval)(nil), // 190: openshell.v1.DraftChunkApproval - (*ApproveAllDraftChunksRequest)(nil), // 191: openshell.v1.ApproveAllDraftChunksRequest - (*ApproveAllDraftChunksResponse)(nil), // 192: openshell.v1.ApproveAllDraftChunksResponse - (*EditDraftChunkRequest)(nil), // 193: openshell.v1.EditDraftChunkRequest - (*EditDraftChunkResponse)(nil), // 194: openshell.v1.EditDraftChunkResponse - (*UndoDraftChunkRequest)(nil), // 195: openshell.v1.UndoDraftChunkRequest - (*UndoDraftChunkResponse)(nil), // 196: openshell.v1.UndoDraftChunkResponse - (*ClearDraftChunksRequest)(nil), // 197: openshell.v1.ClearDraftChunksRequest - (*ClearDraftChunksResponse)(nil), // 198: openshell.v1.ClearDraftChunksResponse - (*GetDraftHistoryRequest)(nil), // 199: openshell.v1.GetDraftHistoryRequest - (*DraftHistoryEntry)(nil), // 200: openshell.v1.DraftHistoryEntry - (*GetDraftHistoryResponse)(nil), // 201: openshell.v1.GetDraftHistoryResponse - (*PolicyRevisionPayload)(nil), // 202: openshell.v1.PolicyRevisionPayload - (*DraftChunkPayload)(nil), // 203: openshell.v1.DraftChunkPayload - (*StoredPolicyRevision)(nil), // 204: openshell.v1.StoredPolicyRevision - (*StoredDraftChunk)(nil), // 205: openshell.v1.StoredDraftChunk - (*CreateWorkspaceRequest)(nil), // 206: openshell.v1.CreateWorkspaceRequest - (*CreateWorkspaceResponse)(nil), // 207: openshell.v1.CreateWorkspaceResponse - (*GetWorkspaceRequest)(nil), // 208: openshell.v1.GetWorkspaceRequest - (*GetWorkspaceResponse)(nil), // 209: openshell.v1.GetWorkspaceResponse - (*ListWorkspacesRequest)(nil), // 210: openshell.v1.ListWorkspacesRequest - (*ListWorkspacesResponse)(nil), // 211: openshell.v1.ListWorkspacesResponse - (*DeleteWorkspaceRequest)(nil), // 212: openshell.v1.DeleteWorkspaceRequest - (*DeleteWorkspaceResponse)(nil), // 213: openshell.v1.DeleteWorkspaceResponse - (*WorkspaceMember)(nil), // 214: openshell.v1.WorkspaceMember - (*AddWorkspaceMemberRequest)(nil), // 215: openshell.v1.AddWorkspaceMemberRequest - (*AddWorkspaceMemberResponse)(nil), // 216: openshell.v1.AddWorkspaceMemberResponse - (*RemoveWorkspaceMemberRequest)(nil), // 217: openshell.v1.RemoveWorkspaceMemberRequest - (*RemoveWorkspaceMemberResponse)(nil), // 218: openshell.v1.RemoveWorkspaceMemberResponse - (*ListWorkspaceMembersRequest)(nil), // 219: openshell.v1.ListWorkspaceMembersRequest - (*ListWorkspaceMembersResponse)(nil), // 220: openshell.v1.ListWorkspaceMembersResponse - (*ExtensionServiceCredential)(nil), // 221: openshell.v1.ExtensionServiceCredential - nil, // 222: openshell.v1.SandboxSpec.EnvironmentEntry - nil, // 223: openshell.v1.SandboxTemplate.LabelsEntry - nil, // 224: openshell.v1.SandboxTemplate.AnnotationsEntry - nil, // 225: openshell.v1.SandboxTemplate.EnvironmentEntry - nil, // 226: openshell.v1.SandboxWorkloadConfig.EnvironmentEntry - nil, // 227: openshell.v1.PlatformEvent.MetadataEntry - nil, // 228: openshell.v1.CreateSandboxRequest.LabelsEntry - nil, // 229: openshell.v1.CreateSandboxRequest.AnnotationsEntry - nil, // 230: openshell.v1.ExecSandboxRequest.EnvironmentEntry - nil, // 231: openshell.v1.SandboxLogLine.FieldsEntry - nil, // 232: openshell.v1.UpdateProviderRequest.CredentialExpiresAtMsEntry - nil, // 233: openshell.v1.StoredProviderCredentialRefreshState.MaterialEntry - nil, // 234: openshell.v1.StoredProviderCredentialRefreshState.AdditionalOutputKeysEntry - nil, // 235: openshell.v1.StoredProviderCredentialRefreshState.SecretMaterialHandlesEntry - nil, // 236: openshell.v1.ConfigureProviderRefreshRequest.MaterialEntry - nil, // 237: openshell.v1.ProviderProfile.AnnotationsEntry - nil, // 238: openshell.v1.GetSandboxProviderEnvironmentResponse.EnvironmentEntry - nil, // 239: openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpiresAtMsEntry - nil, // 240: openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry - nil, // 241: openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry - nil, // 242: openshell.v1.UpdateConfigRequest.AnnotationsEntry - nil, // 243: openshell.v1.UpdateConfigResponse.AnnotationsEntry - nil, // 244: openshell.v1.SandboxPolicyRevision.ProvenanceEntry - nil, // 245: openshell.v1.PolicyRevisionPayload.ProvenanceEntry - nil, // 246: openshell.v1.StoredPolicyRevision.ProvenanceEntry - nil, // 247: openshell.v1.CreateWorkspaceRequest.LabelsEntry - (*datamodelv1.ObjectMeta)(nil), // 248: openshell.datamodel.v1.ObjectMeta - (*sandboxv1.SandboxPolicy)(nil), // 249: openshell.sandbox.v1.SandboxPolicy - (*structpb.Struct)(nil), // 250: google.protobuf.Struct - (*durationpb.Duration)(nil), // 251: google.protobuf.Duration - (*datamodelv1.Provider)(nil), // 252: openshell.datamodel.v1.Provider - (*datamodelv1.CredentialHandle)(nil), // 253: openshell.datamodel.v1.CredentialHandle - (*sandboxv1.NetworkEndpoint)(nil), // 254: openshell.sandbox.v1.NetworkEndpoint - (*sandboxv1.NetworkBinary)(nil), // 255: openshell.sandbox.v1.NetworkBinary - (*sandboxv1.SettingValue)(nil), // 256: openshell.sandbox.v1.SettingValue - (*sandboxv1.NetworkPolicyRule)(nil), // 257: openshell.sandbox.v1.NetworkPolicyRule - (*sandboxv1.L7DenyRule)(nil), // 258: openshell.sandbox.v1.L7DenyRule - (*sandboxv1.L7Rule)(nil), // 259: openshell.sandbox.v1.L7Rule - (*datamodelv1.Workspace)(nil), // 260: openshell.datamodel.v1.Workspace - (*sandboxv1.GetSandboxConfigRequest)(nil), // 261: openshell.sandbox.v1.GetSandboxConfigRequest - (*sandboxv1.GetGatewayConfigRequest)(nil), // 262: openshell.sandbox.v1.GetGatewayConfigRequest - (*sandboxv1.GetSandboxConfigResponse)(nil), // 263: openshell.sandbox.v1.GetSandboxConfigResponse - (*sandboxv1.GetGatewayConfigResponse)(nil), // 264: openshell.sandbox.v1.GetGatewayConfigResponse + (ProviderEnvironmentValueClassification)(0), // 4: openshell.v1.ProviderEnvironmentValueClassification + (PolicyStatus)(0), // 5: openshell.v1.PolicyStatus + (ConfigComponent)(0), // 6: openshell.v1.ConfigComponent + (ConfigApplyOutcome)(0), // 7: openshell.v1.ConfigApplyOutcome + (ServiceStatus)(0), // 8: openshell.v1.ServiceStatus + (WorkspaceRole)(0), // 9: openshell.v1.WorkspaceRole + (ProviderCredentialRefreshRecoveryAction)(0), // 10: openshell.v1.ProviderCredentialRefreshRecoveryAction + (*IssueSandboxTokenRequest)(nil), // 11: openshell.v1.IssueSandboxTokenRequest + (*IssueSandboxTokenResponse)(nil), // 12: openshell.v1.IssueSandboxTokenResponse + (*RefreshSandboxTokenRequest)(nil), // 13: openshell.v1.RefreshSandboxTokenRequest + (*RefreshSandboxTokenResponse)(nil), // 14: openshell.v1.RefreshSandboxTokenResponse + (*HealthRequest)(nil), // 15: openshell.v1.HealthRequest + (*HealthResponse)(nil), // 16: openshell.v1.HealthResponse + (*GetCurrentUserRequest)(nil), // 17: openshell.v1.GetCurrentUserRequest + (*GetCurrentUserResponse)(nil), // 18: openshell.v1.GetCurrentUserResponse + (*GetGatewayInfoRequest)(nil), // 19: openshell.v1.GetGatewayInfoRequest + (*GetGatewayInfoResponse)(nil), // 20: openshell.v1.GetGatewayInfoResponse + (*ComputeDriverInfo)(nil), // 21: openshell.v1.ComputeDriverInfo + (*ComputeDriverCapabilities)(nil), // 22: openshell.v1.ComputeDriverCapabilities + (*ResourceCapabilities)(nil), // 23: openshell.v1.ResourceCapabilities + (*CpuResourceCapabilities)(nil), // 24: openshell.v1.CpuResourceCapabilities + (*MemoryResourceCapabilities)(nil), // 25: openshell.v1.MemoryResourceCapabilities + (*GpuResourceCapabilities)(nil), // 26: openshell.v1.GpuResourceCapabilities + (*Sandbox)(nil), // 27: openshell.v1.Sandbox + (*SandboxSpec)(nil), // 28: openshell.v1.SandboxSpec + (*ResourceRequirements)(nil), // 29: openshell.v1.ResourceRequirements + (*GpuResourceRequirements)(nil), // 30: openshell.v1.GpuResourceRequirements + (*SandboxTemplate)(nil), // 31: openshell.v1.SandboxTemplate + (*SandboxWorkloadTemplate)(nil), // 32: openshell.v1.SandboxWorkloadTemplate + (*SandboxWorkloadTemplateSpec)(nil), // 33: openshell.v1.SandboxWorkloadTemplateSpec + (*SandboxWorkloadConfig)(nil), // 34: openshell.v1.SandboxWorkloadConfig + (*SandboxResources)(nil), // 35: openshell.v1.SandboxResources + (*SandboxServiceLevel)(nil), // 36: openshell.v1.SandboxServiceLevel + (*SandboxStartup)(nil), // 37: openshell.v1.SandboxStartup + (*SandboxWorkloadTemplateProvenance)(nil), // 38: openshell.v1.SandboxWorkloadTemplateProvenance + (*SandboxStatus)(nil), // 39: openshell.v1.SandboxStatus + (*SandboxCondition)(nil), // 40: openshell.v1.SandboxCondition + (*PlatformEvent)(nil), // 41: openshell.v1.PlatformEvent + (*CreateSandboxRequest)(nil), // 42: openshell.v1.CreateSandboxRequest + (*CreateSandboxTemplateRequest)(nil), // 43: openshell.v1.CreateSandboxTemplateRequest + (*GetSandboxTemplateRequest)(nil), // 44: openshell.v1.GetSandboxTemplateRequest + (*ListSandboxTemplatesRequest)(nil), // 45: openshell.v1.ListSandboxTemplatesRequest + (*DeleteSandboxTemplateRequest)(nil), // 46: openshell.v1.DeleteSandboxTemplateRequest + (*SandboxTemplateResponse)(nil), // 47: openshell.v1.SandboxTemplateResponse + (*ListSandboxTemplatesResponse)(nil), // 48: openshell.v1.ListSandboxTemplatesResponse + (*DeleteSandboxTemplateResponse)(nil), // 49: openshell.v1.DeleteSandboxTemplateResponse + (*BeginRootfsTarStagingRequest)(nil), // 50: openshell.v1.BeginRootfsTarStagingRequest + (*BeginRootfsTarStagingResponse)(nil), // 51: openshell.v1.BeginRootfsTarStagingResponse + (*GetSandboxRequest)(nil), // 52: openshell.v1.GetSandboxRequest + (*ListSandboxesRequest)(nil), // 53: openshell.v1.ListSandboxesRequest + (*ListSandboxProvidersRequest)(nil), // 54: openshell.v1.ListSandboxProvidersRequest + (*AttachSandboxProviderRequest)(nil), // 55: openshell.v1.AttachSandboxProviderRequest + (*DetachSandboxProviderRequest)(nil), // 56: openshell.v1.DetachSandboxProviderRequest + (*DeleteSandboxRequest)(nil), // 57: openshell.v1.DeleteSandboxRequest + (*StopSandboxRequest)(nil), // 58: openshell.v1.StopSandboxRequest + (*StartSandboxRequest)(nil), // 59: openshell.v1.StartSandboxRequest + (*SandboxResponse)(nil), // 60: openshell.v1.SandboxResponse + (*ListSandboxesResponse)(nil), // 61: openshell.v1.ListSandboxesResponse + (*ListSandboxProvidersResponse)(nil), // 62: openshell.v1.ListSandboxProvidersResponse + (*AttachSandboxProviderResponse)(nil), // 63: openshell.v1.AttachSandboxProviderResponse + (*DetachSandboxProviderResponse)(nil), // 64: openshell.v1.DetachSandboxProviderResponse + (*DeleteSandboxResponse)(nil), // 65: openshell.v1.DeleteSandboxResponse + (*CreateSshSessionRequest)(nil), // 66: openshell.v1.CreateSshSessionRequest + (*CreateSshSessionResponse)(nil), // 67: openshell.v1.CreateSshSessionResponse + (*ExposeServiceRequest)(nil), // 68: openshell.v1.ExposeServiceRequest + (*GetServiceRequest)(nil), // 69: openshell.v1.GetServiceRequest + (*ListServicesRequest)(nil), // 70: openshell.v1.ListServicesRequest + (*ListServicesResponse)(nil), // 71: openshell.v1.ListServicesResponse + (*DeleteServiceRequest)(nil), // 72: openshell.v1.DeleteServiceRequest + (*DeleteServiceResponse)(nil), // 73: openshell.v1.DeleteServiceResponse + (*ServiceEndpoint)(nil), // 74: openshell.v1.ServiceEndpoint + (*ServiceEndpointResponse)(nil), // 75: openshell.v1.ServiceEndpointResponse + (*RevokeSshSessionRequest)(nil), // 76: openshell.v1.RevokeSshSessionRequest + (*RevokeSshSessionResponse)(nil), // 77: openshell.v1.RevokeSshSessionResponse + (*ExecSandboxRequest)(nil), // 78: openshell.v1.ExecSandboxRequest + (*ExecSandboxStdout)(nil), // 79: openshell.v1.ExecSandboxStdout + (*ExecSandboxStderr)(nil), // 80: openshell.v1.ExecSandboxStderr + (*ExecSandboxExit)(nil), // 81: openshell.v1.ExecSandboxExit + (*ExecSandboxEvent)(nil), // 82: openshell.v1.ExecSandboxEvent + (*TcpForwardInit)(nil), // 83: openshell.v1.TcpForwardInit + (*TcpForwardFrame)(nil), // 84: openshell.v1.TcpForwardFrame + (*ExecSandboxInput)(nil), // 85: openshell.v1.ExecSandboxInput + (*ExecSandboxWindowResize)(nil), // 86: openshell.v1.ExecSandboxWindowResize + (*SshSession)(nil), // 87: openshell.v1.SshSession + (*WatchSandboxRequest)(nil), // 88: openshell.v1.WatchSandboxRequest + (*SandboxStreamEvent)(nil), // 89: openshell.v1.SandboxStreamEvent + (*SandboxLogLine)(nil), // 90: openshell.v1.SandboxLogLine + (*SandboxStreamWarning)(nil), // 91: openshell.v1.SandboxStreamWarning + (*CreateProviderRequest)(nil), // 92: openshell.v1.CreateProviderRequest + (*GetProviderRequest)(nil), // 93: openshell.v1.GetProviderRequest + (*ListProvidersRequest)(nil), // 94: openshell.v1.ListProvidersRequest + (*UpdateProviderRequest)(nil), // 95: openshell.v1.UpdateProviderRequest + (*DeleteProviderRequest)(nil), // 96: openshell.v1.DeleteProviderRequest + (*ProviderResponse)(nil), // 97: openshell.v1.ProviderResponse + (*ListProvidersResponse)(nil), // 98: openshell.v1.ListProvidersResponse + (*ListProviderProfilesRequest)(nil), // 99: openshell.v1.ListProviderProfilesRequest + (*GetProviderProfileRequest)(nil), // 100: openshell.v1.GetProviderProfileRequest + (*ProviderProfileImportItem)(nil), // 101: openshell.v1.ProviderProfileImportItem + (*ProviderProfileDiagnostic)(nil), // 102: openshell.v1.ProviderProfileDiagnostic + (*ProviderCredentialTokenGrantAudienceOverride)(nil), // 103: openshell.v1.ProviderCredentialTokenGrantAudienceOverride + (*ProviderCredentialTokenGrantSubjectToken)(nil), // 104: openshell.v1.ProviderCredentialTokenGrantSubjectToken + (*ProviderCredentialTokenGrant)(nil), // 105: openshell.v1.ProviderCredentialTokenGrant + (*ProviderProfileCredential)(nil), // 106: openshell.v1.ProviderProfileCredential + (*ProviderCredentialRefreshMaterial)(nil), // 107: openshell.v1.ProviderCredentialRefreshMaterial + (*ProviderCredentialRefreshOutput)(nil), // 108: openshell.v1.ProviderCredentialRefreshOutput + (*ProviderCredentialRefresh)(nil), // 109: openshell.v1.ProviderCredentialRefresh + (*ProviderCredentialRefreshStatus)(nil), // 110: openshell.v1.ProviderCredentialRefreshStatus + (*ProviderProfileDiscovery)(nil), // 111: openshell.v1.ProviderProfileDiscovery + (*StoredProviderCredentialRefreshState)(nil), // 112: openshell.v1.StoredProviderCredentialRefreshState + (*StoredRefreshMaterialDeletion)(nil), // 113: openshell.v1.StoredRefreshMaterialDeletion + (*GetProviderRefreshStatusRequest)(nil), // 114: openshell.v1.GetProviderRefreshStatusRequest + (*GetProviderRefreshStatusResponse)(nil), // 115: openshell.v1.GetProviderRefreshStatusResponse + (*ConfigureProviderRefreshRequest)(nil), // 116: openshell.v1.ConfigureProviderRefreshRequest + (*ConfigureProviderRefreshResponse)(nil), // 117: openshell.v1.ConfigureProviderRefreshResponse + (*RotateProviderCredentialRequest)(nil), // 118: openshell.v1.RotateProviderCredentialRequest + (*RotateProviderCredentialResponse)(nil), // 119: openshell.v1.RotateProviderCredentialResponse + (*DeleteProviderRefreshRequest)(nil), // 120: openshell.v1.DeleteProviderRefreshRequest + (*DeleteProviderRefreshResponse)(nil), // 121: openshell.v1.DeleteProviderRefreshResponse + (*ProviderProfile)(nil), // 122: openshell.v1.ProviderProfile + (*StoredProviderProfile)(nil), // 123: openshell.v1.StoredProviderProfile + (*ProviderProfileResponse)(nil), // 124: openshell.v1.ProviderProfileResponse + (*ListProviderProfilesResponse)(nil), // 125: openshell.v1.ListProviderProfilesResponse + (*ImportProviderProfilesRequest)(nil), // 126: openshell.v1.ImportProviderProfilesRequest + (*ImportProviderProfilesResponse)(nil), // 127: openshell.v1.ImportProviderProfilesResponse + (*UpdateProviderProfilesRequest)(nil), // 128: openshell.v1.UpdateProviderProfilesRequest + (*UpdateProviderProfilesResponse)(nil), // 129: openshell.v1.UpdateProviderProfilesResponse + (*LintProviderProfilesRequest)(nil), // 130: openshell.v1.LintProviderProfilesRequest + (*LintProviderProfilesResponse)(nil), // 131: openshell.v1.LintProviderProfilesResponse + (*DeleteProviderResponse)(nil), // 132: openshell.v1.DeleteProviderResponse + (*DeleteProviderProfileRequest)(nil), // 133: openshell.v1.DeleteProviderProfileRequest + (*DeleteProviderProfileResponse)(nil), // 134: openshell.v1.DeleteProviderProfileResponse + (*GetSandboxProviderEnvironmentRequest)(nil), // 135: openshell.v1.GetSandboxProviderEnvironmentRequest + (*StaticCredentialEndpointBinding)(nil), // 136: openshell.v1.StaticCredentialEndpointBinding + (*StaticCredentialBinding)(nil), // 137: openshell.v1.StaticCredentialBinding + (*GetSandboxProviderEnvironmentResponse)(nil), // 138: openshell.v1.GetSandboxProviderEnvironmentResponse + (*ProviderEnvironmentValue)(nil), // 139: openshell.v1.ProviderEnvironmentValue + (*ProviderEnvironmentSnapshot)(nil), // 140: openshell.v1.ProviderEnvironmentSnapshot + (*ExchangeProviderSubjectTokenRequest)(nil), // 141: openshell.v1.ExchangeProviderSubjectTokenRequest + (*ExchangeProviderSubjectTokenResponse)(nil), // 142: openshell.v1.ExchangeProviderSubjectTokenResponse + (*UpdateConfigRequest)(nil), // 143: openshell.v1.UpdateConfigRequest + (*PolicyMergeOperation)(nil), // 144: openshell.v1.PolicyMergeOperation + (*AddNetworkRule)(nil), // 145: openshell.v1.AddNetworkRule + (*RemoveNetworkEndpoint)(nil), // 146: openshell.v1.RemoveNetworkEndpoint + (*RemoveNetworkRule)(nil), // 147: openshell.v1.RemoveNetworkRule + (*AddDenyRules)(nil), // 148: openshell.v1.AddDenyRules + (*AddAllowRules)(nil), // 149: openshell.v1.AddAllowRules + (*RemoveNetworkBinary)(nil), // 150: openshell.v1.RemoveNetworkBinary + (*UpdateConfigResponse)(nil), // 151: openshell.v1.UpdateConfigResponse + (*GetSandboxPolicyStatusRequest)(nil), // 152: openshell.v1.GetSandboxPolicyStatusRequest + (*GetSandboxPolicyStatusResponse)(nil), // 153: openshell.v1.GetSandboxPolicyStatusResponse + (*ListSandboxPoliciesRequest)(nil), // 154: openshell.v1.ListSandboxPoliciesRequest + (*ListSandboxPoliciesResponse)(nil), // 155: openshell.v1.ListSandboxPoliciesResponse + (*ReportPolicyStatusRequest)(nil), // 156: openshell.v1.ReportPolicyStatusRequest + (*ReportPolicyStatusResponse)(nil), // 157: openshell.v1.ReportPolicyStatusResponse + (*SandboxPolicyRevision)(nil), // 158: openshell.v1.SandboxPolicyRevision + (*GetSandboxLogsRequest)(nil), // 159: openshell.v1.GetSandboxLogsRequest + (*PushSandboxLogsRequest)(nil), // 160: openshell.v1.PushSandboxLogsRequest + (*PushSandboxLogsResponse)(nil), // 161: openshell.v1.PushSandboxLogsResponse + (*GetSandboxLogsResponse)(nil), // 162: openshell.v1.GetSandboxLogsResponse + (*SupervisorMessage)(nil), // 163: openshell.v1.SupervisorMessage + (*GatewayMessage)(nil), // 164: openshell.v1.GatewayMessage + (*SupervisorHello)(nil), // 165: openshell.v1.SupervisorHello + (*SessionAccepted)(nil), // 166: openshell.v1.SessionAccepted + (*ConfigBootstrap)(nil), // 167: openshell.v1.ConfigBootstrap + (*ConfigUpdate)(nil), // 168: openshell.v1.ConfigUpdate + (*ConfigSnapshotRevision)(nil), // 169: openshell.v1.ConfigSnapshotRevision + (*SandboxConfigRevision)(nil), // 170: openshell.v1.SandboxConfigRevision + (*ConfigApplyFailure)(nil), // 171: openshell.v1.ConfigApplyFailure + (*ConfigComponentApplyResult)(nil), // 172: openshell.v1.ConfigComponentApplyResult + (*ConfigUpdateResult)(nil), // 173: openshell.v1.ConfigUpdateResult + (*ConfigBootstrapResult)(nil), // 174: openshell.v1.ConfigBootstrapResult + (*SessionRejected)(nil), // 175: openshell.v1.SessionRejected + (*SupervisorHeartbeat)(nil), // 176: openshell.v1.SupervisorHeartbeat + (*GatewayHeartbeat)(nil), // 177: openshell.v1.GatewayHeartbeat + (*ReportMainProcessExitRequest)(nil), // 178: openshell.v1.ReportMainProcessExitRequest + (*ReportMainProcessExitResponse)(nil), // 179: openshell.v1.ReportMainProcessExitResponse + (*FinalizeMainProcessExitRequest)(nil), // 180: openshell.v1.FinalizeMainProcessExitRequest + (*FinalizeMainProcessExitResponse)(nil), // 181: openshell.v1.FinalizeMainProcessExitResponse + (*RelayOpen)(nil), // 182: openshell.v1.RelayOpen + (*SshRelayTarget)(nil), // 183: openshell.v1.SshRelayTarget + (*TcpRelayTarget)(nil), // 184: openshell.v1.TcpRelayTarget + (*RelayInit)(nil), // 185: openshell.v1.RelayInit + (*RelayFrame)(nil), // 186: openshell.v1.RelayFrame + (*RelayOpenResult)(nil), // 187: openshell.v1.RelayOpenResult + (*RelayClose)(nil), // 188: openshell.v1.RelayClose + (*L7RequestSample)(nil), // 189: openshell.v1.L7RequestSample + (*DenialSummary)(nil), // 190: openshell.v1.DenialSummary + (*DenialGroupCount)(nil), // 191: openshell.v1.DenialGroupCount + (*NetworkActivitySummary)(nil), // 192: openshell.v1.NetworkActivitySummary + (*PolicyChunk)(nil), // 193: openshell.v1.PolicyChunk + (*DraftPolicyUpdate)(nil), // 194: openshell.v1.DraftPolicyUpdate + (*SubmitPolicyAnalysisRequest)(nil), // 195: openshell.v1.SubmitPolicyAnalysisRequest + (*SubmitPolicyAnalysisResponse)(nil), // 196: openshell.v1.SubmitPolicyAnalysisResponse + (*GetDraftPolicyRequest)(nil), // 197: openshell.v1.GetDraftPolicyRequest + (*GetDraftPolicyResponse)(nil), // 198: openshell.v1.GetDraftPolicyResponse + (*ApproveDraftChunkRequest)(nil), // 199: openshell.v1.ApproveDraftChunkRequest + (*ApproveDraftChunkResponse)(nil), // 200: openshell.v1.ApproveDraftChunkResponse + (*RejectDraftChunkRequest)(nil), // 201: openshell.v1.RejectDraftChunkRequest + (*RejectDraftChunkResponse)(nil), // 202: openshell.v1.RejectDraftChunkResponse + (*DraftChunkApproval)(nil), // 203: openshell.v1.DraftChunkApproval + (*ApproveAllDraftChunksRequest)(nil), // 204: openshell.v1.ApproveAllDraftChunksRequest + (*ApproveAllDraftChunksResponse)(nil), // 205: openshell.v1.ApproveAllDraftChunksResponse + (*EditDraftChunkRequest)(nil), // 206: openshell.v1.EditDraftChunkRequest + (*EditDraftChunkResponse)(nil), // 207: openshell.v1.EditDraftChunkResponse + (*UndoDraftChunkRequest)(nil), // 208: openshell.v1.UndoDraftChunkRequest + (*UndoDraftChunkResponse)(nil), // 209: openshell.v1.UndoDraftChunkResponse + (*ClearDraftChunksRequest)(nil), // 210: openshell.v1.ClearDraftChunksRequest + (*ClearDraftChunksResponse)(nil), // 211: openshell.v1.ClearDraftChunksResponse + (*GetDraftHistoryRequest)(nil), // 212: openshell.v1.GetDraftHistoryRequest + (*DraftHistoryEntry)(nil), // 213: openshell.v1.DraftHistoryEntry + (*GetDraftHistoryResponse)(nil), // 214: openshell.v1.GetDraftHistoryResponse + (*PolicyRevisionPayload)(nil), // 215: openshell.v1.PolicyRevisionPayload + (*DraftChunkPayload)(nil), // 216: openshell.v1.DraftChunkPayload + (*StoredPolicyRevision)(nil), // 217: openshell.v1.StoredPolicyRevision + (*StoredDraftChunk)(nil), // 218: openshell.v1.StoredDraftChunk + (*CreateWorkspaceRequest)(nil), // 219: openshell.v1.CreateWorkspaceRequest + (*CreateWorkspaceResponse)(nil), // 220: openshell.v1.CreateWorkspaceResponse + (*GetWorkspaceRequest)(nil), // 221: openshell.v1.GetWorkspaceRequest + (*GetWorkspaceResponse)(nil), // 222: openshell.v1.GetWorkspaceResponse + (*ListWorkspacesRequest)(nil), // 223: openshell.v1.ListWorkspacesRequest + (*ListWorkspacesResponse)(nil), // 224: openshell.v1.ListWorkspacesResponse + (*DeleteWorkspaceRequest)(nil), // 225: openshell.v1.DeleteWorkspaceRequest + (*DeleteWorkspaceResponse)(nil), // 226: openshell.v1.DeleteWorkspaceResponse + (*WorkspaceMember)(nil), // 227: openshell.v1.WorkspaceMember + (*AddWorkspaceMemberRequest)(nil), // 228: openshell.v1.AddWorkspaceMemberRequest + (*AddWorkspaceMemberResponse)(nil), // 229: openshell.v1.AddWorkspaceMemberResponse + (*RemoveWorkspaceMemberRequest)(nil), // 230: openshell.v1.RemoveWorkspaceMemberRequest + (*RemoveWorkspaceMemberResponse)(nil), // 231: openshell.v1.RemoveWorkspaceMemberResponse + (*ListWorkspaceMembersRequest)(nil), // 232: openshell.v1.ListWorkspaceMembersRequest + (*ListWorkspaceMembersResponse)(nil), // 233: openshell.v1.ListWorkspaceMembersResponse + (*ExtensionServiceCredential)(nil), // 234: openshell.v1.ExtensionServiceCredential + nil, // 235: openshell.v1.SandboxSpec.EnvironmentEntry + nil, // 236: openshell.v1.SandboxTemplate.LabelsEntry + nil, // 237: openshell.v1.SandboxTemplate.AnnotationsEntry + nil, // 238: openshell.v1.SandboxTemplate.EnvironmentEntry + nil, // 239: openshell.v1.SandboxWorkloadConfig.EnvironmentEntry + nil, // 240: openshell.v1.PlatformEvent.MetadataEntry + nil, // 241: openshell.v1.CreateSandboxRequest.LabelsEntry + nil, // 242: openshell.v1.CreateSandboxRequest.AnnotationsEntry + nil, // 243: openshell.v1.ExecSandboxRequest.EnvironmentEntry + nil, // 244: openshell.v1.SandboxLogLine.FieldsEntry + nil, // 245: openshell.v1.UpdateProviderRequest.CredentialExpiresAtMsEntry + nil, // 246: openshell.v1.StoredProviderCredentialRefreshState.MaterialEntry + nil, // 247: openshell.v1.StoredProviderCredentialRefreshState.AdditionalOutputKeysEntry + nil, // 248: openshell.v1.StoredProviderCredentialRefreshState.SecretMaterialHandlesEntry + nil, // 249: openshell.v1.ConfigureProviderRefreshRequest.MaterialEntry + nil, // 250: openshell.v1.ProviderProfile.AnnotationsEntry + nil, // 251: openshell.v1.GetSandboxProviderEnvironmentResponse.EnvironmentEntry + nil, // 252: openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpiresAtMsEntry + nil, // 253: openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry + nil, // 254: openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry + nil, // 255: openshell.v1.ProviderEnvironmentSnapshot.DynamicCredentialsEntry + nil, // 256: openshell.v1.UpdateConfigRequest.AnnotationsEntry + nil, // 257: openshell.v1.UpdateConfigResponse.AnnotationsEntry + nil, // 258: openshell.v1.SandboxPolicyRevision.ProvenanceEntry + nil, // 259: openshell.v1.PolicyRevisionPayload.ProvenanceEntry + nil, // 260: openshell.v1.StoredPolicyRevision.ProvenanceEntry + nil, // 261: openshell.v1.CreateWorkspaceRequest.LabelsEntry + (*datamodelv1.ObjectMeta)(nil), // 262: openshell.datamodel.v1.ObjectMeta + (*sandboxv1.SandboxPolicy)(nil), // 263: openshell.sandbox.v1.SandboxPolicy + (*structpb.Struct)(nil), // 264: google.protobuf.Struct + (*durationpb.Duration)(nil), // 265: google.protobuf.Duration + (*datamodelv1.Provider)(nil), // 266: openshell.datamodel.v1.Provider + (*datamodelv1.CredentialHandle)(nil), // 267: openshell.datamodel.v1.CredentialHandle + (*sandboxv1.NetworkEndpoint)(nil), // 268: openshell.sandbox.v1.NetworkEndpoint + (*sandboxv1.NetworkBinary)(nil), // 269: openshell.sandbox.v1.NetworkBinary + (*sandboxv1.SettingValue)(nil), // 270: openshell.sandbox.v1.SettingValue + (*sandboxv1.NetworkPolicyRule)(nil), // 271: openshell.sandbox.v1.NetworkPolicyRule + (*sandboxv1.L7DenyRule)(nil), // 272: openshell.sandbox.v1.L7DenyRule + (*sandboxv1.L7Rule)(nil), // 273: openshell.sandbox.v1.L7Rule + (*sandboxv1.SandboxConfigSnapshot)(nil), // 274: openshell.sandbox.v1.SandboxConfigSnapshot + (sandboxv1.PolicySource)(0), // 275: openshell.sandbox.v1.PolicySource + (*datamodelv1.Workspace)(nil), // 276: openshell.datamodel.v1.Workspace + (*sandboxv1.GetSandboxConfigRequest)(nil), // 277: openshell.sandbox.v1.GetSandboxConfigRequest + (*sandboxv1.GetGatewayConfigRequest)(nil), // 278: openshell.sandbox.v1.GetGatewayConfigRequest + (*sandboxv1.GetSandboxConfigResponse)(nil), // 279: openshell.sandbox.v1.GetSandboxConfigResponse + (*sandboxv1.GetGatewayConfigResponse)(nil), // 280: openshell.sandbox.v1.GetGatewayConfigResponse } var file_openshell_proto_depIdxs = []int32{ - 221, // 0: openshell.v1.RefreshSandboxTokenResponse.extension_credentials:type_name -> openshell.v1.ExtensionServiceCredential - 5, // 1: openshell.v1.HealthResponse.status:type_name -> openshell.v1.ServiceStatus - 5, // 2: openshell.v1.GetGatewayInfoResponse.status:type_name -> openshell.v1.ServiceStatus - 18, // 3: openshell.v1.GetGatewayInfoResponse.compute_drivers:type_name -> openshell.v1.ComputeDriverInfo - 19, // 4: openshell.v1.ComputeDriverInfo.capabilities:type_name -> openshell.v1.ComputeDriverCapabilities - 20, // 5: openshell.v1.ComputeDriverCapabilities.resource_capabilities:type_name -> openshell.v1.ResourceCapabilities - 21, // 6: openshell.v1.ResourceCapabilities.cpu:type_name -> openshell.v1.CpuResourceCapabilities - 22, // 7: openshell.v1.ResourceCapabilities.memory:type_name -> openshell.v1.MemoryResourceCapabilities - 23, // 8: openshell.v1.ResourceCapabilities.gpu:type_name -> openshell.v1.GpuResourceCapabilities - 248, // 9: openshell.v1.Sandbox.metadata:type_name -> openshell.datamodel.v1.ObjectMeta - 25, // 10: openshell.v1.Sandbox.spec:type_name -> openshell.v1.SandboxSpec - 36, // 11: openshell.v1.Sandbox.status:type_name -> openshell.v1.SandboxStatus - 35, // 12: openshell.v1.Sandbox.created_from_workload_template:type_name -> openshell.v1.SandboxWorkloadTemplateProvenance - 222, // 13: openshell.v1.SandboxSpec.environment:type_name -> openshell.v1.SandboxSpec.EnvironmentEntry - 28, // 14: openshell.v1.SandboxSpec.template:type_name -> openshell.v1.SandboxTemplate - 249, // 15: openshell.v1.SandboxSpec.policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 26, // 16: openshell.v1.SandboxSpec.resource_requirements:type_name -> openshell.v1.ResourceRequirements - 27, // 17: openshell.v1.ResourceRequirements.gpu:type_name -> openshell.v1.GpuResourceRequirements - 223, // 18: openshell.v1.SandboxTemplate.labels:type_name -> openshell.v1.SandboxTemplate.LabelsEntry - 224, // 19: openshell.v1.SandboxTemplate.annotations:type_name -> openshell.v1.SandboxTemplate.AnnotationsEntry - 225, // 20: openshell.v1.SandboxTemplate.environment:type_name -> openshell.v1.SandboxTemplate.EnvironmentEntry - 250, // 21: openshell.v1.SandboxTemplate.resources:type_name -> google.protobuf.Struct - 250, // 22: openshell.v1.SandboxTemplate.driver_config:type_name -> google.protobuf.Struct - 248, // 23: openshell.v1.SandboxWorkloadTemplate.metadata:type_name -> openshell.datamodel.v1.ObjectMeta - 30, // 24: openshell.v1.SandboxWorkloadTemplate.spec:type_name -> openshell.v1.SandboxWorkloadTemplateSpec - 31, // 25: openshell.v1.SandboxWorkloadTemplateSpec.workload:type_name -> openshell.v1.SandboxWorkloadConfig - 250, // 26: openshell.v1.SandboxWorkloadTemplateSpec.driver_config:type_name -> google.protobuf.Struct - 33, // 27: openshell.v1.SandboxWorkloadTemplateSpec.desired_service_level:type_name -> openshell.v1.SandboxServiceLevel - 226, // 28: openshell.v1.SandboxWorkloadConfig.environment:type_name -> openshell.v1.SandboxWorkloadConfig.EnvironmentEntry - 32, // 29: openshell.v1.SandboxWorkloadConfig.resources:type_name -> openshell.v1.SandboxResources - 27, // 30: openshell.v1.SandboxResources.gpu:type_name -> openshell.v1.GpuResourceRequirements - 34, // 31: openshell.v1.SandboxServiceLevel.startup:type_name -> openshell.v1.SandboxStartup - 251, // 32: openshell.v1.SandboxStartup.ready_within:type_name -> google.protobuf.Duration - 37, // 33: openshell.v1.SandboxStatus.conditions:type_name -> openshell.v1.SandboxCondition + 234, // 0: openshell.v1.RefreshSandboxTokenResponse.extension_credentials:type_name -> openshell.v1.ExtensionServiceCredential + 8, // 1: openshell.v1.HealthResponse.status:type_name -> openshell.v1.ServiceStatus + 8, // 2: openshell.v1.GetGatewayInfoResponse.status:type_name -> openshell.v1.ServiceStatus + 21, // 3: openshell.v1.GetGatewayInfoResponse.compute_drivers:type_name -> openshell.v1.ComputeDriverInfo + 22, // 4: openshell.v1.ComputeDriverInfo.capabilities:type_name -> openshell.v1.ComputeDriverCapabilities + 23, // 5: openshell.v1.ComputeDriverCapabilities.resource_capabilities:type_name -> openshell.v1.ResourceCapabilities + 24, // 6: openshell.v1.ResourceCapabilities.cpu:type_name -> openshell.v1.CpuResourceCapabilities + 25, // 7: openshell.v1.ResourceCapabilities.memory:type_name -> openshell.v1.MemoryResourceCapabilities + 26, // 8: openshell.v1.ResourceCapabilities.gpu:type_name -> openshell.v1.GpuResourceCapabilities + 262, // 9: openshell.v1.Sandbox.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 28, // 10: openshell.v1.Sandbox.spec:type_name -> openshell.v1.SandboxSpec + 39, // 11: openshell.v1.Sandbox.status:type_name -> openshell.v1.SandboxStatus + 38, // 12: openshell.v1.Sandbox.created_from_workload_template:type_name -> openshell.v1.SandboxWorkloadTemplateProvenance + 235, // 13: openshell.v1.SandboxSpec.environment:type_name -> openshell.v1.SandboxSpec.EnvironmentEntry + 31, // 14: openshell.v1.SandboxSpec.template:type_name -> openshell.v1.SandboxTemplate + 263, // 15: openshell.v1.SandboxSpec.policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 29, // 16: openshell.v1.SandboxSpec.resource_requirements:type_name -> openshell.v1.ResourceRequirements + 30, // 17: openshell.v1.ResourceRequirements.gpu:type_name -> openshell.v1.GpuResourceRequirements + 236, // 18: openshell.v1.SandboxTemplate.labels:type_name -> openshell.v1.SandboxTemplate.LabelsEntry + 237, // 19: openshell.v1.SandboxTemplate.annotations:type_name -> openshell.v1.SandboxTemplate.AnnotationsEntry + 238, // 20: openshell.v1.SandboxTemplate.environment:type_name -> openshell.v1.SandboxTemplate.EnvironmentEntry + 264, // 21: openshell.v1.SandboxTemplate.resources:type_name -> google.protobuf.Struct + 264, // 22: openshell.v1.SandboxTemplate.driver_config:type_name -> google.protobuf.Struct + 262, // 23: openshell.v1.SandboxWorkloadTemplate.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 33, // 24: openshell.v1.SandboxWorkloadTemplate.spec:type_name -> openshell.v1.SandboxWorkloadTemplateSpec + 34, // 25: openshell.v1.SandboxWorkloadTemplateSpec.workload:type_name -> openshell.v1.SandboxWorkloadConfig + 264, // 26: openshell.v1.SandboxWorkloadTemplateSpec.driver_config:type_name -> google.protobuf.Struct + 36, // 27: openshell.v1.SandboxWorkloadTemplateSpec.desired_service_level:type_name -> openshell.v1.SandboxServiceLevel + 239, // 28: openshell.v1.SandboxWorkloadConfig.environment:type_name -> openshell.v1.SandboxWorkloadConfig.EnvironmentEntry + 35, // 29: openshell.v1.SandboxWorkloadConfig.resources:type_name -> openshell.v1.SandboxResources + 30, // 30: openshell.v1.SandboxResources.gpu:type_name -> openshell.v1.GpuResourceRequirements + 37, // 31: openshell.v1.SandboxServiceLevel.startup:type_name -> openshell.v1.SandboxStartup + 265, // 32: openshell.v1.SandboxStartup.ready_within:type_name -> google.protobuf.Duration + 40, // 33: openshell.v1.SandboxStatus.conditions:type_name -> openshell.v1.SandboxCondition 0, // 34: openshell.v1.SandboxStatus.phase:type_name -> openshell.v1.SandboxPhase - 227, // 35: openshell.v1.PlatformEvent.metadata:type_name -> openshell.v1.PlatformEvent.MetadataEntry - 25, // 36: openshell.v1.CreateSandboxRequest.spec:type_name -> openshell.v1.SandboxSpec - 228, // 37: openshell.v1.CreateSandboxRequest.labels:type_name -> openshell.v1.CreateSandboxRequest.LabelsEntry - 229, // 38: openshell.v1.CreateSandboxRequest.annotations:type_name -> openshell.v1.CreateSandboxRequest.AnnotationsEntry - 29, // 39: openshell.v1.CreateSandboxTemplateRequest.template:type_name -> openshell.v1.SandboxWorkloadTemplate - 29, // 40: openshell.v1.SandboxTemplateResponse.template:type_name -> openshell.v1.SandboxWorkloadTemplate - 29, // 41: openshell.v1.ListSandboxTemplatesResponse.templates:type_name -> openshell.v1.SandboxWorkloadTemplate - 24, // 42: openshell.v1.SandboxResponse.sandbox:type_name -> openshell.v1.Sandbox - 24, // 43: openshell.v1.ListSandboxesResponse.sandboxes:type_name -> openshell.v1.Sandbox - 252, // 44: openshell.v1.ListSandboxProvidersResponse.providers:type_name -> openshell.datamodel.v1.Provider - 24, // 45: openshell.v1.AttachSandboxProviderResponse.sandbox:type_name -> openshell.v1.Sandbox - 24, // 46: openshell.v1.DetachSandboxProviderResponse.sandbox:type_name -> openshell.v1.Sandbox - 72, // 47: openshell.v1.ListServicesResponse.services:type_name -> openshell.v1.ServiceEndpointResponse - 248, // 48: openshell.v1.ServiceEndpoint.metadata:type_name -> openshell.datamodel.v1.ObjectMeta - 71, // 49: openshell.v1.ServiceEndpointResponse.endpoint:type_name -> openshell.v1.ServiceEndpoint - 230, // 50: openshell.v1.ExecSandboxRequest.environment:type_name -> openshell.v1.ExecSandboxRequest.EnvironmentEntry - 76, // 51: openshell.v1.ExecSandboxEvent.stdout:type_name -> openshell.v1.ExecSandboxStdout - 77, // 52: openshell.v1.ExecSandboxEvent.stderr:type_name -> openshell.v1.ExecSandboxStderr - 78, // 53: openshell.v1.ExecSandboxEvent.exit:type_name -> openshell.v1.ExecSandboxExit - 170, // 54: openshell.v1.TcpForwardInit.ssh:type_name -> openshell.v1.SshRelayTarget - 171, // 55: openshell.v1.TcpForwardInit.tcp:type_name -> openshell.v1.TcpRelayTarget - 80, // 56: openshell.v1.TcpForwardFrame.init:type_name -> openshell.v1.TcpForwardInit - 75, // 57: openshell.v1.ExecSandboxInput.start:type_name -> openshell.v1.ExecSandboxRequest - 83, // 58: openshell.v1.ExecSandboxInput.resize:type_name -> openshell.v1.ExecSandboxWindowResize - 248, // 59: openshell.v1.SshSession.metadata:type_name -> openshell.datamodel.v1.ObjectMeta - 24, // 60: openshell.v1.SandboxStreamEvent.sandbox:type_name -> openshell.v1.Sandbox - 87, // 61: openshell.v1.SandboxStreamEvent.log:type_name -> openshell.v1.SandboxLogLine - 38, // 62: openshell.v1.SandboxStreamEvent.event:type_name -> openshell.v1.PlatformEvent - 88, // 63: openshell.v1.SandboxStreamEvent.warning:type_name -> openshell.v1.SandboxStreamWarning - 181, // 64: openshell.v1.SandboxStreamEvent.draft_policy_update:type_name -> openshell.v1.DraftPolicyUpdate - 231, // 65: openshell.v1.SandboxLogLine.fields:type_name -> openshell.v1.SandboxLogLine.FieldsEntry - 252, // 66: openshell.v1.CreateProviderRequest.provider:type_name -> openshell.datamodel.v1.Provider - 252, // 67: openshell.v1.UpdateProviderRequest.provider:type_name -> openshell.datamodel.v1.Provider - 232, // 68: openshell.v1.UpdateProviderRequest.credential_expires_at_ms:type_name -> openshell.v1.UpdateProviderRequest.CredentialExpiresAtMsEntry - 252, // 69: openshell.v1.ProviderResponse.provider:type_name -> openshell.datamodel.v1.Provider - 252, // 70: openshell.v1.ListProvidersResponse.providers:type_name -> openshell.datamodel.v1.Provider - 119, // 71: openshell.v1.ProviderProfileImportItem.profile:type_name -> openshell.v1.ProviderProfile - 100, // 72: openshell.v1.ProviderCredentialTokenGrant.audience_overrides:type_name -> openshell.v1.ProviderCredentialTokenGrantAudienceOverride + 240, // 35: openshell.v1.PlatformEvent.metadata:type_name -> openshell.v1.PlatformEvent.MetadataEntry + 28, // 36: openshell.v1.CreateSandboxRequest.spec:type_name -> openshell.v1.SandboxSpec + 241, // 37: openshell.v1.CreateSandboxRequest.labels:type_name -> openshell.v1.CreateSandboxRequest.LabelsEntry + 242, // 38: openshell.v1.CreateSandboxRequest.annotations:type_name -> openshell.v1.CreateSandboxRequest.AnnotationsEntry + 32, // 39: openshell.v1.CreateSandboxTemplateRequest.template:type_name -> openshell.v1.SandboxWorkloadTemplate + 32, // 40: openshell.v1.SandboxTemplateResponse.template:type_name -> openshell.v1.SandboxWorkloadTemplate + 32, // 41: openshell.v1.ListSandboxTemplatesResponse.templates:type_name -> openshell.v1.SandboxWorkloadTemplate + 27, // 42: openshell.v1.SandboxResponse.sandbox:type_name -> openshell.v1.Sandbox + 27, // 43: openshell.v1.ListSandboxesResponse.sandboxes:type_name -> openshell.v1.Sandbox + 266, // 44: openshell.v1.ListSandboxProvidersResponse.providers:type_name -> openshell.datamodel.v1.Provider + 27, // 45: openshell.v1.AttachSandboxProviderResponse.sandbox:type_name -> openshell.v1.Sandbox + 27, // 46: openshell.v1.DetachSandboxProviderResponse.sandbox:type_name -> openshell.v1.Sandbox + 75, // 47: openshell.v1.ListServicesResponse.services:type_name -> openshell.v1.ServiceEndpointResponse + 262, // 48: openshell.v1.ServiceEndpoint.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 74, // 49: openshell.v1.ServiceEndpointResponse.endpoint:type_name -> openshell.v1.ServiceEndpoint + 243, // 50: openshell.v1.ExecSandboxRequest.environment:type_name -> openshell.v1.ExecSandboxRequest.EnvironmentEntry + 79, // 51: openshell.v1.ExecSandboxEvent.stdout:type_name -> openshell.v1.ExecSandboxStdout + 80, // 52: openshell.v1.ExecSandboxEvent.stderr:type_name -> openshell.v1.ExecSandboxStderr + 81, // 53: openshell.v1.ExecSandboxEvent.exit:type_name -> openshell.v1.ExecSandboxExit + 183, // 54: openshell.v1.TcpForwardInit.ssh:type_name -> openshell.v1.SshRelayTarget + 184, // 55: openshell.v1.TcpForwardInit.tcp:type_name -> openshell.v1.TcpRelayTarget + 83, // 56: openshell.v1.TcpForwardFrame.init:type_name -> openshell.v1.TcpForwardInit + 78, // 57: openshell.v1.ExecSandboxInput.start:type_name -> openshell.v1.ExecSandboxRequest + 86, // 58: openshell.v1.ExecSandboxInput.resize:type_name -> openshell.v1.ExecSandboxWindowResize + 262, // 59: openshell.v1.SshSession.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 27, // 60: openshell.v1.SandboxStreamEvent.sandbox:type_name -> openshell.v1.Sandbox + 90, // 61: openshell.v1.SandboxStreamEvent.log:type_name -> openshell.v1.SandboxLogLine + 41, // 62: openshell.v1.SandboxStreamEvent.event:type_name -> openshell.v1.PlatformEvent + 91, // 63: openshell.v1.SandboxStreamEvent.warning:type_name -> openshell.v1.SandboxStreamWarning + 194, // 64: openshell.v1.SandboxStreamEvent.draft_policy_update:type_name -> openshell.v1.DraftPolicyUpdate + 244, // 65: openshell.v1.SandboxLogLine.fields:type_name -> openshell.v1.SandboxLogLine.FieldsEntry + 266, // 66: openshell.v1.CreateProviderRequest.provider:type_name -> openshell.datamodel.v1.Provider + 266, // 67: openshell.v1.UpdateProviderRequest.provider:type_name -> openshell.datamodel.v1.Provider + 245, // 68: openshell.v1.UpdateProviderRequest.credential_expires_at_ms:type_name -> openshell.v1.UpdateProviderRequest.CredentialExpiresAtMsEntry + 266, // 69: openshell.v1.ProviderResponse.provider:type_name -> openshell.datamodel.v1.Provider + 266, // 70: openshell.v1.ListProvidersResponse.providers:type_name -> openshell.datamodel.v1.Provider + 122, // 71: openshell.v1.ProviderProfileImportItem.profile:type_name -> openshell.v1.ProviderProfile + 103, // 72: openshell.v1.ProviderCredentialTokenGrant.audience_overrides:type_name -> openshell.v1.ProviderCredentialTokenGrantAudienceOverride 1, // 73: openshell.v1.ProviderCredentialTokenGrant.grant_type:type_name -> openshell.v1.ProviderCredentialTokenGrantType - 101, // 74: openshell.v1.ProviderCredentialTokenGrant.subject_token:type_name -> openshell.v1.ProviderCredentialTokenGrantSubjectToken - 106, // 75: openshell.v1.ProviderProfileCredential.refresh:type_name -> openshell.v1.ProviderCredentialRefresh - 102, // 76: openshell.v1.ProviderProfileCredential.token_grant:type_name -> openshell.v1.ProviderCredentialTokenGrant + 104, // 74: openshell.v1.ProviderCredentialTokenGrant.subject_token:type_name -> openshell.v1.ProviderCredentialTokenGrantSubjectToken + 109, // 75: openshell.v1.ProviderProfileCredential.refresh:type_name -> openshell.v1.ProviderCredentialRefresh + 105, // 76: openshell.v1.ProviderProfileCredential.token_grant:type_name -> openshell.v1.ProviderCredentialTokenGrant 2, // 77: openshell.v1.ProviderCredentialRefresh.strategy:type_name -> openshell.v1.ProviderCredentialRefreshStrategy - 104, // 78: openshell.v1.ProviderCredentialRefresh.material:type_name -> openshell.v1.ProviderCredentialRefreshMaterial - 105, // 79: openshell.v1.ProviderCredentialRefresh.additional_outputs:type_name -> openshell.v1.ProviderCredentialRefreshOutput + 107, // 78: openshell.v1.ProviderCredentialRefresh.material:type_name -> openshell.v1.ProviderCredentialRefreshMaterial + 108, // 79: openshell.v1.ProviderCredentialRefresh.additional_outputs:type_name -> openshell.v1.ProviderCredentialRefreshOutput 2, // 80: openshell.v1.ProviderCredentialRefreshStatus.strategy:type_name -> openshell.v1.ProviderCredentialRefreshStrategy - 7, // 81: openshell.v1.ProviderCredentialRefreshStatus.recovery_action:type_name -> openshell.v1.ProviderCredentialRefreshRecoveryAction - 248, // 82: openshell.v1.StoredProviderCredentialRefreshState.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 10, // 81: openshell.v1.ProviderCredentialRefreshStatus.recovery_action:type_name -> openshell.v1.ProviderCredentialRefreshRecoveryAction + 262, // 82: openshell.v1.StoredProviderCredentialRefreshState.metadata:type_name -> openshell.datamodel.v1.ObjectMeta 2, // 83: openshell.v1.StoredProviderCredentialRefreshState.strategy:type_name -> openshell.v1.ProviderCredentialRefreshStrategy - 233, // 84: openshell.v1.StoredProviderCredentialRefreshState.material:type_name -> openshell.v1.StoredProviderCredentialRefreshState.MaterialEntry - 234, // 85: openshell.v1.StoredProviderCredentialRefreshState.additional_output_keys:type_name -> openshell.v1.StoredProviderCredentialRefreshState.AdditionalOutputKeysEntry - 235, // 86: openshell.v1.StoredProviderCredentialRefreshState.secret_material_handles:type_name -> openshell.v1.StoredProviderCredentialRefreshState.SecretMaterialHandlesEntry - 110, // 87: openshell.v1.StoredProviderCredentialRefreshState.pending_secret_deletions:type_name -> openshell.v1.StoredRefreshMaterialDeletion - 7, // 88: openshell.v1.StoredProviderCredentialRefreshState.recovery_action:type_name -> openshell.v1.ProviderCredentialRefreshRecoveryAction - 253, // 89: openshell.v1.StoredRefreshMaterialDeletion.handle:type_name -> openshell.datamodel.v1.CredentialHandle - 107, // 90: openshell.v1.GetProviderRefreshStatusResponse.credentials:type_name -> openshell.v1.ProviderCredentialRefreshStatus + 246, // 84: openshell.v1.StoredProviderCredentialRefreshState.material:type_name -> openshell.v1.StoredProviderCredentialRefreshState.MaterialEntry + 247, // 85: openshell.v1.StoredProviderCredentialRefreshState.additional_output_keys:type_name -> openshell.v1.StoredProviderCredentialRefreshState.AdditionalOutputKeysEntry + 248, // 86: openshell.v1.StoredProviderCredentialRefreshState.secret_material_handles:type_name -> openshell.v1.StoredProviderCredentialRefreshState.SecretMaterialHandlesEntry + 113, // 87: openshell.v1.StoredProviderCredentialRefreshState.pending_secret_deletions:type_name -> openshell.v1.StoredRefreshMaterialDeletion + 10, // 88: openshell.v1.StoredProviderCredentialRefreshState.recovery_action:type_name -> openshell.v1.ProviderCredentialRefreshRecoveryAction + 267, // 89: openshell.v1.StoredRefreshMaterialDeletion.handle:type_name -> openshell.datamodel.v1.CredentialHandle + 110, // 90: openshell.v1.GetProviderRefreshStatusResponse.credentials:type_name -> openshell.v1.ProviderCredentialRefreshStatus 2, // 91: openshell.v1.ConfigureProviderRefreshRequest.strategy:type_name -> openshell.v1.ProviderCredentialRefreshStrategy - 236, // 92: openshell.v1.ConfigureProviderRefreshRequest.material:type_name -> openshell.v1.ConfigureProviderRefreshRequest.MaterialEntry - 107, // 93: openshell.v1.ConfigureProviderRefreshResponse.status:type_name -> openshell.v1.ProviderCredentialRefreshStatus - 107, // 94: openshell.v1.RotateProviderCredentialResponse.status:type_name -> openshell.v1.ProviderCredentialRefreshStatus + 249, // 92: openshell.v1.ConfigureProviderRefreshRequest.material:type_name -> openshell.v1.ConfigureProviderRefreshRequest.MaterialEntry + 110, // 93: openshell.v1.ConfigureProviderRefreshResponse.status:type_name -> openshell.v1.ProviderCredentialRefreshStatus + 110, // 94: openshell.v1.RotateProviderCredentialResponse.status:type_name -> openshell.v1.ProviderCredentialRefreshStatus 3, // 95: openshell.v1.ProviderProfile.category:type_name -> openshell.v1.ProviderProfileCategory - 103, // 96: openshell.v1.ProviderProfile.credentials:type_name -> openshell.v1.ProviderProfileCredential - 254, // 97: openshell.v1.ProviderProfile.endpoints:type_name -> openshell.sandbox.v1.NetworkEndpoint - 255, // 98: openshell.v1.ProviderProfile.binaries:type_name -> openshell.sandbox.v1.NetworkBinary - 108, // 99: openshell.v1.ProviderProfile.discovery:type_name -> openshell.v1.ProviderProfileDiscovery - 237, // 100: openshell.v1.ProviderProfile.annotations:type_name -> openshell.v1.ProviderProfile.AnnotationsEntry - 248, // 101: openshell.v1.StoredProviderProfile.metadata:type_name -> openshell.datamodel.v1.ObjectMeta - 119, // 102: openshell.v1.StoredProviderProfile.profile:type_name -> openshell.v1.ProviderProfile - 119, // 103: openshell.v1.ProviderProfileResponse.profile:type_name -> openshell.v1.ProviderProfile - 119, // 104: openshell.v1.ListProviderProfilesResponse.profiles:type_name -> openshell.v1.ProviderProfile - 98, // 105: openshell.v1.ImportProviderProfilesRequest.profiles:type_name -> openshell.v1.ProviderProfileImportItem - 99, // 106: openshell.v1.ImportProviderProfilesResponse.diagnostics:type_name -> openshell.v1.ProviderProfileDiagnostic - 119, // 107: openshell.v1.ImportProviderProfilesResponse.profiles:type_name -> openshell.v1.ProviderProfile - 98, // 108: openshell.v1.UpdateProviderProfilesRequest.profile:type_name -> openshell.v1.ProviderProfileImportItem - 99, // 109: openshell.v1.UpdateProviderProfilesResponse.diagnostics:type_name -> openshell.v1.ProviderProfileDiagnostic - 119, // 110: openshell.v1.UpdateProviderProfilesResponse.profile:type_name -> openshell.v1.ProviderProfile - 98, // 111: openshell.v1.LintProviderProfilesRequest.profiles:type_name -> openshell.v1.ProviderProfileImportItem - 99, // 112: openshell.v1.LintProviderProfilesResponse.diagnostics:type_name -> openshell.v1.ProviderProfileDiagnostic - 133, // 113: openshell.v1.StaticCredentialBinding.endpoints:type_name -> openshell.v1.StaticCredentialEndpointBinding - 238, // 114: openshell.v1.GetSandboxProviderEnvironmentResponse.environment:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.EnvironmentEntry - 239, // 115: openshell.v1.GetSandboxProviderEnvironmentResponse.credential_expires_at_ms:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpiresAtMsEntry - 240, // 116: openshell.v1.GetSandboxProviderEnvironmentResponse.dynamic_credentials:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry - 241, // 117: openshell.v1.GetSandboxProviderEnvironmentResponse.static_credential_bindings:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry - 249, // 118: openshell.v1.UpdateConfigRequest.policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 256, // 119: openshell.v1.UpdateConfigRequest.setting_value:type_name -> openshell.sandbox.v1.SettingValue - 139, // 120: openshell.v1.UpdateConfigRequest.merge_operations:type_name -> openshell.v1.PolicyMergeOperation - 242, // 121: openshell.v1.UpdateConfigRequest.annotations:type_name -> openshell.v1.UpdateConfigRequest.AnnotationsEntry - 140, // 122: openshell.v1.PolicyMergeOperation.add_rule:type_name -> openshell.v1.AddNetworkRule - 141, // 123: openshell.v1.PolicyMergeOperation.remove_endpoint:type_name -> openshell.v1.RemoveNetworkEndpoint - 142, // 124: openshell.v1.PolicyMergeOperation.remove_rule:type_name -> openshell.v1.RemoveNetworkRule - 143, // 125: openshell.v1.PolicyMergeOperation.add_deny_rules:type_name -> openshell.v1.AddDenyRules - 144, // 126: openshell.v1.PolicyMergeOperation.add_allow_rules:type_name -> openshell.v1.AddAllowRules - 145, // 127: openshell.v1.PolicyMergeOperation.remove_binary:type_name -> openshell.v1.RemoveNetworkBinary - 257, // 128: openshell.v1.AddNetworkRule.rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule - 258, // 129: openshell.v1.AddDenyRules.deny_rules:type_name -> openshell.sandbox.v1.L7DenyRule - 259, // 130: openshell.v1.AddAllowRules.rules:type_name -> openshell.sandbox.v1.L7Rule - 243, // 131: openshell.v1.UpdateConfigResponse.annotations:type_name -> openshell.v1.UpdateConfigResponse.AnnotationsEntry - 153, // 132: openshell.v1.GetSandboxPolicyStatusResponse.revision:type_name -> openshell.v1.SandboxPolicyRevision - 153, // 133: openshell.v1.ListSandboxPoliciesResponse.revisions:type_name -> openshell.v1.SandboxPolicyRevision - 4, // 134: openshell.v1.ReportPolicyStatusRequest.status:type_name -> openshell.v1.PolicyStatus - 4, // 135: openshell.v1.SandboxPolicyRevision.status:type_name -> openshell.v1.PolicyStatus - 249, // 136: openshell.v1.SandboxPolicyRevision.policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 244, // 137: openshell.v1.SandboxPolicyRevision.provenance:type_name -> openshell.v1.SandboxPolicyRevision.ProvenanceEntry - 87, // 138: openshell.v1.PushSandboxLogsRequest.logs:type_name -> openshell.v1.SandboxLogLine - 87, // 139: openshell.v1.GetSandboxLogsResponse.logs:type_name -> openshell.v1.SandboxLogLine - 160, // 140: openshell.v1.SupervisorMessage.hello:type_name -> openshell.v1.SupervisorHello - 163, // 141: openshell.v1.SupervisorMessage.heartbeat:type_name -> openshell.v1.SupervisorHeartbeat - 174, // 142: openshell.v1.SupervisorMessage.relay_open_result:type_name -> openshell.v1.RelayOpenResult - 175, // 143: openshell.v1.SupervisorMessage.relay_close:type_name -> openshell.v1.RelayClose - 161, // 144: openshell.v1.GatewayMessage.session_accepted:type_name -> openshell.v1.SessionAccepted - 162, // 145: openshell.v1.GatewayMessage.session_rejected:type_name -> openshell.v1.SessionRejected - 164, // 146: openshell.v1.GatewayMessage.heartbeat:type_name -> openshell.v1.GatewayHeartbeat - 169, // 147: openshell.v1.GatewayMessage.relay_open:type_name -> openshell.v1.RelayOpen - 175, // 148: openshell.v1.GatewayMessage.relay_close:type_name -> openshell.v1.RelayClose - 170, // 149: openshell.v1.RelayOpen.ssh:type_name -> openshell.v1.SshRelayTarget - 171, // 150: openshell.v1.RelayOpen.tcp:type_name -> openshell.v1.TcpRelayTarget - 172, // 151: openshell.v1.RelayFrame.init:type_name -> openshell.v1.RelayInit - 176, // 152: openshell.v1.DenialSummary.l7_request_samples:type_name -> openshell.v1.L7RequestSample - 178, // 153: openshell.v1.NetworkActivitySummary.denials_by_group:type_name -> openshell.v1.DenialGroupCount - 257, // 154: openshell.v1.PolicyChunk.proposed_rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule - 249, // 155: openshell.v1.PolicyChunk.current_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 249, // 156: openshell.v1.PolicyChunk.candidate_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 177, // 157: openshell.v1.SubmitPolicyAnalysisRequest.summaries:type_name -> openshell.v1.DenialSummary - 180, // 158: openshell.v1.SubmitPolicyAnalysisRequest.proposed_chunks:type_name -> openshell.v1.PolicyChunk - 179, // 159: openshell.v1.SubmitPolicyAnalysisRequest.network_activity_summaries:type_name -> openshell.v1.NetworkActivitySummary - 180, // 160: openshell.v1.GetDraftPolicyResponse.chunks:type_name -> openshell.v1.PolicyChunk - 190, // 161: openshell.v1.ApproveAllDraftChunksRequest.approvals:type_name -> openshell.v1.DraftChunkApproval - 257, // 162: openshell.v1.EditDraftChunkRequest.proposed_rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule - 200, // 163: openshell.v1.GetDraftHistoryResponse.entries:type_name -> openshell.v1.DraftHistoryEntry - 249, // 164: openshell.v1.PolicyRevisionPayload.policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 245, // 165: openshell.v1.PolicyRevisionPayload.provenance:type_name -> openshell.v1.PolicyRevisionPayload.ProvenanceEntry - 257, // 166: openshell.v1.DraftChunkPayload.proposed_rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule - 249, // 167: openshell.v1.DraftChunkPayload.current_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 249, // 168: openshell.v1.DraftChunkPayload.candidate_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 246, // 169: openshell.v1.StoredPolicyRevision.provenance:type_name -> openshell.v1.StoredPolicyRevision.ProvenanceEntry - 249, // 170: openshell.v1.StoredDraftChunk.current_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 249, // 171: openshell.v1.StoredDraftChunk.candidate_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 247, // 172: openshell.v1.CreateWorkspaceRequest.labels:type_name -> openshell.v1.CreateWorkspaceRequest.LabelsEntry - 260, // 173: openshell.v1.CreateWorkspaceResponse.workspace:type_name -> openshell.datamodel.v1.Workspace - 260, // 174: openshell.v1.GetWorkspaceResponse.workspace:type_name -> openshell.datamodel.v1.Workspace - 260, // 175: openshell.v1.ListWorkspacesResponse.workspaces:type_name -> openshell.datamodel.v1.Workspace - 248, // 176: openshell.v1.WorkspaceMember.metadata:type_name -> openshell.datamodel.v1.ObjectMeta - 6, // 177: openshell.v1.WorkspaceMember.role:type_name -> openshell.v1.WorkspaceRole - 6, // 178: openshell.v1.AddWorkspaceMemberRequest.role:type_name -> openshell.v1.WorkspaceRole - 214, // 179: openshell.v1.AddWorkspaceMemberResponse.member:type_name -> openshell.v1.WorkspaceMember - 214, // 180: openshell.v1.ListWorkspaceMembersResponse.members:type_name -> openshell.v1.WorkspaceMember - 253, // 181: openshell.v1.StoredProviderCredentialRefreshState.SecretMaterialHandlesEntry.value:type_name -> openshell.datamodel.v1.CredentialHandle - 103, // 182: openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry.value:type_name -> openshell.v1.ProviderProfileCredential - 134, // 183: openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry.value:type_name -> openshell.v1.StaticCredentialBinding - 12, // 184: openshell.v1.OpenShell.Health:input_type -> openshell.v1.HealthRequest - 14, // 185: openshell.v1.OpenShell.GetCurrentUser:input_type -> openshell.v1.GetCurrentUserRequest - 16, // 186: openshell.v1.OpenShell.GetGatewayInfo:input_type -> openshell.v1.GetGatewayInfoRequest - 39, // 187: openshell.v1.OpenShell.CreateSandbox:input_type -> openshell.v1.CreateSandboxRequest - 47, // 188: openshell.v1.OpenShell.BeginRootfsTarStaging:input_type -> openshell.v1.BeginRootfsTarStagingRequest - 49, // 189: openshell.v1.OpenShell.GetSandbox:input_type -> openshell.v1.GetSandboxRequest - 50, // 190: openshell.v1.OpenShell.ListSandboxes:input_type -> openshell.v1.ListSandboxesRequest - 40, // 191: openshell.v1.OpenShell.CreateSandboxTemplate:input_type -> openshell.v1.CreateSandboxTemplateRequest - 41, // 192: openshell.v1.OpenShell.GetSandboxTemplate:input_type -> openshell.v1.GetSandboxTemplateRequest - 42, // 193: openshell.v1.OpenShell.ListSandboxTemplates:input_type -> openshell.v1.ListSandboxTemplatesRequest - 43, // 194: openshell.v1.OpenShell.DeleteSandboxTemplate:input_type -> openshell.v1.DeleteSandboxTemplateRequest - 51, // 195: openshell.v1.OpenShell.ListSandboxProviders:input_type -> openshell.v1.ListSandboxProvidersRequest - 52, // 196: openshell.v1.OpenShell.AttachSandboxProvider:input_type -> openshell.v1.AttachSandboxProviderRequest - 53, // 197: openshell.v1.OpenShell.DetachSandboxProvider:input_type -> openshell.v1.DetachSandboxProviderRequest - 54, // 198: openshell.v1.OpenShell.DeleteSandbox:input_type -> openshell.v1.DeleteSandboxRequest - 55, // 199: openshell.v1.OpenShell.StopSandbox:input_type -> openshell.v1.StopSandboxRequest - 56, // 200: openshell.v1.OpenShell.StartSandbox:input_type -> openshell.v1.StartSandboxRequest - 63, // 201: openshell.v1.OpenShell.CreateSshSession:input_type -> openshell.v1.CreateSshSessionRequest - 65, // 202: openshell.v1.OpenShell.ExposeService:input_type -> openshell.v1.ExposeServiceRequest - 66, // 203: openshell.v1.OpenShell.GetService:input_type -> openshell.v1.GetServiceRequest - 67, // 204: openshell.v1.OpenShell.ListServices:input_type -> openshell.v1.ListServicesRequest - 69, // 205: openshell.v1.OpenShell.DeleteService:input_type -> openshell.v1.DeleteServiceRequest - 73, // 206: openshell.v1.OpenShell.RevokeSshSession:input_type -> openshell.v1.RevokeSshSessionRequest - 75, // 207: openshell.v1.OpenShell.ExecSandbox:input_type -> openshell.v1.ExecSandboxRequest - 81, // 208: openshell.v1.OpenShell.ForwardTcp:input_type -> openshell.v1.TcpForwardFrame - 82, // 209: openshell.v1.OpenShell.ExecSandboxInteractive:input_type -> openshell.v1.ExecSandboxInput - 89, // 210: openshell.v1.OpenShell.CreateProvider:input_type -> openshell.v1.CreateProviderRequest - 90, // 211: openshell.v1.OpenShell.GetProvider:input_type -> openshell.v1.GetProviderRequest - 91, // 212: openshell.v1.OpenShell.ListProviders:input_type -> openshell.v1.ListProvidersRequest - 96, // 213: openshell.v1.OpenShell.ListProviderProfiles:input_type -> openshell.v1.ListProviderProfilesRequest - 97, // 214: openshell.v1.OpenShell.GetProviderProfile:input_type -> openshell.v1.GetProviderProfileRequest - 123, // 215: openshell.v1.OpenShell.ImportProviderProfiles:input_type -> openshell.v1.ImportProviderProfilesRequest - 125, // 216: openshell.v1.OpenShell.UpdateProviderProfiles:input_type -> openshell.v1.UpdateProviderProfilesRequest - 127, // 217: openshell.v1.OpenShell.LintProviderProfiles:input_type -> openshell.v1.LintProviderProfilesRequest - 92, // 218: openshell.v1.OpenShell.UpdateProvider:input_type -> openshell.v1.UpdateProviderRequest - 111, // 219: openshell.v1.OpenShell.GetProviderRefreshStatus:input_type -> openshell.v1.GetProviderRefreshStatusRequest - 113, // 220: openshell.v1.OpenShell.ConfigureProviderRefresh:input_type -> openshell.v1.ConfigureProviderRefreshRequest - 115, // 221: openshell.v1.OpenShell.RotateProviderCredential:input_type -> openshell.v1.RotateProviderCredentialRequest - 117, // 222: openshell.v1.OpenShell.DeleteProviderRefresh:input_type -> openshell.v1.DeleteProviderRefreshRequest - 93, // 223: openshell.v1.OpenShell.DeleteProvider:input_type -> openshell.v1.DeleteProviderRequest - 130, // 224: openshell.v1.OpenShell.DeleteProviderProfile:input_type -> openshell.v1.DeleteProviderProfileRequest - 261, // 225: openshell.v1.OpenShell.GetSandboxConfig:input_type -> openshell.sandbox.v1.GetSandboxConfigRequest - 262, // 226: openshell.v1.OpenShell.GetGatewayConfig:input_type -> openshell.sandbox.v1.GetGatewayConfigRequest - 138, // 227: openshell.v1.OpenShell.UpdateConfig:input_type -> openshell.v1.UpdateConfigRequest - 147, // 228: openshell.v1.OpenShell.GetSandboxPolicyStatus:input_type -> openshell.v1.GetSandboxPolicyStatusRequest - 149, // 229: openshell.v1.OpenShell.ListSandboxPolicies:input_type -> openshell.v1.ListSandboxPoliciesRequest - 151, // 230: openshell.v1.OpenShell.ReportPolicyStatus:input_type -> openshell.v1.ReportPolicyStatusRequest - 132, // 231: openshell.v1.OpenShell.GetSandboxProviderEnvironment:input_type -> openshell.v1.GetSandboxProviderEnvironmentRequest - 136, // 232: openshell.v1.OpenShell.ExchangeProviderSubjectToken:input_type -> openshell.v1.ExchangeProviderSubjectTokenRequest - 154, // 233: openshell.v1.OpenShell.GetSandboxLogs:input_type -> openshell.v1.GetSandboxLogsRequest - 155, // 234: openshell.v1.OpenShell.PushSandboxLogs:input_type -> openshell.v1.PushSandboxLogsRequest - 158, // 235: openshell.v1.OpenShell.ConnectSupervisor:input_type -> openshell.v1.SupervisorMessage - 165, // 236: openshell.v1.OpenShell.ReportMainProcessExit:input_type -> openshell.v1.ReportMainProcessExitRequest - 167, // 237: openshell.v1.OpenShell.FinalizeMainProcessExit:input_type -> openshell.v1.FinalizeMainProcessExitRequest - 173, // 238: openshell.v1.OpenShell.RelayStream:input_type -> openshell.v1.RelayFrame - 85, // 239: openshell.v1.OpenShell.WatchSandbox:input_type -> openshell.v1.WatchSandboxRequest - 182, // 240: openshell.v1.OpenShell.SubmitPolicyAnalysis:input_type -> openshell.v1.SubmitPolicyAnalysisRequest - 184, // 241: openshell.v1.OpenShell.GetDraftPolicy:input_type -> openshell.v1.GetDraftPolicyRequest - 186, // 242: openshell.v1.OpenShell.ApproveDraftChunk:input_type -> openshell.v1.ApproveDraftChunkRequest - 188, // 243: openshell.v1.OpenShell.RejectDraftChunk:input_type -> openshell.v1.RejectDraftChunkRequest - 191, // 244: openshell.v1.OpenShell.ApproveAllDraftChunks:input_type -> openshell.v1.ApproveAllDraftChunksRequest - 193, // 245: openshell.v1.OpenShell.EditDraftChunk:input_type -> openshell.v1.EditDraftChunkRequest - 195, // 246: openshell.v1.OpenShell.UndoDraftChunk:input_type -> openshell.v1.UndoDraftChunkRequest - 197, // 247: openshell.v1.OpenShell.ClearDraftChunks:input_type -> openshell.v1.ClearDraftChunksRequest - 199, // 248: openshell.v1.OpenShell.GetDraftHistory:input_type -> openshell.v1.GetDraftHistoryRequest - 8, // 249: openshell.v1.OpenShell.IssueSandboxToken:input_type -> openshell.v1.IssueSandboxTokenRequest - 10, // 250: openshell.v1.OpenShell.RefreshSandboxToken:input_type -> openshell.v1.RefreshSandboxTokenRequest - 206, // 251: openshell.v1.OpenShell.CreateWorkspace:input_type -> openshell.v1.CreateWorkspaceRequest - 208, // 252: openshell.v1.OpenShell.GetWorkspace:input_type -> openshell.v1.GetWorkspaceRequest - 210, // 253: openshell.v1.OpenShell.ListWorkspaces:input_type -> openshell.v1.ListWorkspacesRequest - 212, // 254: openshell.v1.OpenShell.DeleteWorkspace:input_type -> openshell.v1.DeleteWorkspaceRequest - 215, // 255: openshell.v1.OpenShell.AddWorkspaceMember:input_type -> openshell.v1.AddWorkspaceMemberRequest - 217, // 256: openshell.v1.OpenShell.RemoveWorkspaceMember:input_type -> openshell.v1.RemoveWorkspaceMemberRequest - 219, // 257: openshell.v1.OpenShell.ListWorkspaceMembers:input_type -> openshell.v1.ListWorkspaceMembersRequest - 13, // 258: openshell.v1.OpenShell.Health:output_type -> openshell.v1.HealthResponse - 15, // 259: openshell.v1.OpenShell.GetCurrentUser:output_type -> openshell.v1.GetCurrentUserResponse - 17, // 260: openshell.v1.OpenShell.GetGatewayInfo:output_type -> openshell.v1.GetGatewayInfoResponse - 57, // 261: openshell.v1.OpenShell.CreateSandbox:output_type -> openshell.v1.SandboxResponse - 48, // 262: openshell.v1.OpenShell.BeginRootfsTarStaging:output_type -> openshell.v1.BeginRootfsTarStagingResponse - 57, // 263: openshell.v1.OpenShell.GetSandbox:output_type -> openshell.v1.SandboxResponse - 58, // 264: openshell.v1.OpenShell.ListSandboxes:output_type -> openshell.v1.ListSandboxesResponse - 44, // 265: openshell.v1.OpenShell.CreateSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse - 44, // 266: openshell.v1.OpenShell.GetSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse - 45, // 267: openshell.v1.OpenShell.ListSandboxTemplates:output_type -> openshell.v1.ListSandboxTemplatesResponse - 46, // 268: openshell.v1.OpenShell.DeleteSandboxTemplate:output_type -> openshell.v1.DeleteSandboxTemplateResponse - 59, // 269: openshell.v1.OpenShell.ListSandboxProviders:output_type -> openshell.v1.ListSandboxProvidersResponse - 60, // 270: openshell.v1.OpenShell.AttachSandboxProvider:output_type -> openshell.v1.AttachSandboxProviderResponse - 61, // 271: openshell.v1.OpenShell.DetachSandboxProvider:output_type -> openshell.v1.DetachSandboxProviderResponse - 62, // 272: openshell.v1.OpenShell.DeleteSandbox:output_type -> openshell.v1.DeleteSandboxResponse - 57, // 273: openshell.v1.OpenShell.StopSandbox:output_type -> openshell.v1.SandboxResponse - 57, // 274: openshell.v1.OpenShell.StartSandbox:output_type -> openshell.v1.SandboxResponse - 64, // 275: openshell.v1.OpenShell.CreateSshSession:output_type -> openshell.v1.CreateSshSessionResponse - 72, // 276: openshell.v1.OpenShell.ExposeService:output_type -> openshell.v1.ServiceEndpointResponse - 72, // 277: openshell.v1.OpenShell.GetService:output_type -> openshell.v1.ServiceEndpointResponse - 68, // 278: openshell.v1.OpenShell.ListServices:output_type -> openshell.v1.ListServicesResponse - 70, // 279: openshell.v1.OpenShell.DeleteService:output_type -> openshell.v1.DeleteServiceResponse - 74, // 280: openshell.v1.OpenShell.RevokeSshSession:output_type -> openshell.v1.RevokeSshSessionResponse - 79, // 281: openshell.v1.OpenShell.ExecSandbox:output_type -> openshell.v1.ExecSandboxEvent - 81, // 282: openshell.v1.OpenShell.ForwardTcp:output_type -> openshell.v1.TcpForwardFrame - 79, // 283: openshell.v1.OpenShell.ExecSandboxInteractive:output_type -> openshell.v1.ExecSandboxEvent - 94, // 284: openshell.v1.OpenShell.CreateProvider:output_type -> openshell.v1.ProviderResponse - 94, // 285: openshell.v1.OpenShell.GetProvider:output_type -> openshell.v1.ProviderResponse - 95, // 286: openshell.v1.OpenShell.ListProviders:output_type -> openshell.v1.ListProvidersResponse - 122, // 287: openshell.v1.OpenShell.ListProviderProfiles:output_type -> openshell.v1.ListProviderProfilesResponse - 121, // 288: openshell.v1.OpenShell.GetProviderProfile:output_type -> openshell.v1.ProviderProfileResponse - 124, // 289: openshell.v1.OpenShell.ImportProviderProfiles:output_type -> openshell.v1.ImportProviderProfilesResponse - 126, // 290: openshell.v1.OpenShell.UpdateProviderProfiles:output_type -> openshell.v1.UpdateProviderProfilesResponse - 128, // 291: openshell.v1.OpenShell.LintProviderProfiles:output_type -> openshell.v1.LintProviderProfilesResponse - 94, // 292: openshell.v1.OpenShell.UpdateProvider:output_type -> openshell.v1.ProviderResponse - 112, // 293: openshell.v1.OpenShell.GetProviderRefreshStatus:output_type -> openshell.v1.GetProviderRefreshStatusResponse - 114, // 294: openshell.v1.OpenShell.ConfigureProviderRefresh:output_type -> openshell.v1.ConfigureProviderRefreshResponse - 116, // 295: openshell.v1.OpenShell.RotateProviderCredential:output_type -> openshell.v1.RotateProviderCredentialResponse - 118, // 296: openshell.v1.OpenShell.DeleteProviderRefresh:output_type -> openshell.v1.DeleteProviderRefreshResponse - 129, // 297: openshell.v1.OpenShell.DeleteProvider:output_type -> openshell.v1.DeleteProviderResponse - 131, // 298: openshell.v1.OpenShell.DeleteProviderProfile:output_type -> openshell.v1.DeleteProviderProfileResponse - 263, // 299: openshell.v1.OpenShell.GetSandboxConfig:output_type -> openshell.sandbox.v1.GetSandboxConfigResponse - 264, // 300: openshell.v1.OpenShell.GetGatewayConfig:output_type -> openshell.sandbox.v1.GetGatewayConfigResponse - 146, // 301: openshell.v1.OpenShell.UpdateConfig:output_type -> openshell.v1.UpdateConfigResponse - 148, // 302: openshell.v1.OpenShell.GetSandboxPolicyStatus:output_type -> openshell.v1.GetSandboxPolicyStatusResponse - 150, // 303: openshell.v1.OpenShell.ListSandboxPolicies:output_type -> openshell.v1.ListSandboxPoliciesResponse - 152, // 304: openshell.v1.OpenShell.ReportPolicyStatus:output_type -> openshell.v1.ReportPolicyStatusResponse - 135, // 305: openshell.v1.OpenShell.GetSandboxProviderEnvironment:output_type -> openshell.v1.GetSandboxProviderEnvironmentResponse - 137, // 306: openshell.v1.OpenShell.ExchangeProviderSubjectToken:output_type -> openshell.v1.ExchangeProviderSubjectTokenResponse - 157, // 307: openshell.v1.OpenShell.GetSandboxLogs:output_type -> openshell.v1.GetSandboxLogsResponse - 156, // 308: openshell.v1.OpenShell.PushSandboxLogs:output_type -> openshell.v1.PushSandboxLogsResponse - 159, // 309: openshell.v1.OpenShell.ConnectSupervisor:output_type -> openshell.v1.GatewayMessage - 166, // 310: openshell.v1.OpenShell.ReportMainProcessExit:output_type -> openshell.v1.ReportMainProcessExitResponse - 168, // 311: openshell.v1.OpenShell.FinalizeMainProcessExit:output_type -> openshell.v1.FinalizeMainProcessExitResponse - 173, // 312: openshell.v1.OpenShell.RelayStream:output_type -> openshell.v1.RelayFrame - 86, // 313: openshell.v1.OpenShell.WatchSandbox:output_type -> openshell.v1.SandboxStreamEvent - 183, // 314: openshell.v1.OpenShell.SubmitPolicyAnalysis:output_type -> openshell.v1.SubmitPolicyAnalysisResponse - 185, // 315: openshell.v1.OpenShell.GetDraftPolicy:output_type -> openshell.v1.GetDraftPolicyResponse - 187, // 316: openshell.v1.OpenShell.ApproveDraftChunk:output_type -> openshell.v1.ApproveDraftChunkResponse - 189, // 317: openshell.v1.OpenShell.RejectDraftChunk:output_type -> openshell.v1.RejectDraftChunkResponse - 192, // 318: openshell.v1.OpenShell.ApproveAllDraftChunks:output_type -> openshell.v1.ApproveAllDraftChunksResponse - 194, // 319: openshell.v1.OpenShell.EditDraftChunk:output_type -> openshell.v1.EditDraftChunkResponse - 196, // 320: openshell.v1.OpenShell.UndoDraftChunk:output_type -> openshell.v1.UndoDraftChunkResponse - 198, // 321: openshell.v1.OpenShell.ClearDraftChunks:output_type -> openshell.v1.ClearDraftChunksResponse - 201, // 322: openshell.v1.OpenShell.GetDraftHistory:output_type -> openshell.v1.GetDraftHistoryResponse - 9, // 323: openshell.v1.OpenShell.IssueSandboxToken:output_type -> openshell.v1.IssueSandboxTokenResponse - 11, // 324: openshell.v1.OpenShell.RefreshSandboxToken:output_type -> openshell.v1.RefreshSandboxTokenResponse - 207, // 325: openshell.v1.OpenShell.CreateWorkspace:output_type -> openshell.v1.CreateWorkspaceResponse - 209, // 326: openshell.v1.OpenShell.GetWorkspace:output_type -> openshell.v1.GetWorkspaceResponse - 211, // 327: openshell.v1.OpenShell.ListWorkspaces:output_type -> openshell.v1.ListWorkspacesResponse - 213, // 328: openshell.v1.OpenShell.DeleteWorkspace:output_type -> openshell.v1.DeleteWorkspaceResponse - 216, // 329: openshell.v1.OpenShell.AddWorkspaceMember:output_type -> openshell.v1.AddWorkspaceMemberResponse - 218, // 330: openshell.v1.OpenShell.RemoveWorkspaceMember:output_type -> openshell.v1.RemoveWorkspaceMemberResponse - 220, // 331: openshell.v1.OpenShell.ListWorkspaceMembers:output_type -> openshell.v1.ListWorkspaceMembersResponse - 258, // [258:332] is the sub-list for method output_type - 184, // [184:258] is the sub-list for method input_type - 184, // [184:184] is the sub-list for extension type_name - 184, // [184:184] is the sub-list for extension extendee - 0, // [0:184] is the sub-list for field type_name + 106, // 96: openshell.v1.ProviderProfile.credentials:type_name -> openshell.v1.ProviderProfileCredential + 268, // 97: openshell.v1.ProviderProfile.endpoints:type_name -> openshell.sandbox.v1.NetworkEndpoint + 269, // 98: openshell.v1.ProviderProfile.binaries:type_name -> openshell.sandbox.v1.NetworkBinary + 111, // 99: openshell.v1.ProviderProfile.discovery:type_name -> openshell.v1.ProviderProfileDiscovery + 250, // 100: openshell.v1.ProviderProfile.annotations:type_name -> openshell.v1.ProviderProfile.AnnotationsEntry + 262, // 101: openshell.v1.StoredProviderProfile.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 122, // 102: openshell.v1.StoredProviderProfile.profile:type_name -> openshell.v1.ProviderProfile + 122, // 103: openshell.v1.ProviderProfileResponse.profile:type_name -> openshell.v1.ProviderProfile + 122, // 104: openshell.v1.ListProviderProfilesResponse.profiles:type_name -> openshell.v1.ProviderProfile + 101, // 105: openshell.v1.ImportProviderProfilesRequest.profiles:type_name -> openshell.v1.ProviderProfileImportItem + 102, // 106: openshell.v1.ImportProviderProfilesResponse.diagnostics:type_name -> openshell.v1.ProviderProfileDiagnostic + 122, // 107: openshell.v1.ImportProviderProfilesResponse.profiles:type_name -> openshell.v1.ProviderProfile + 101, // 108: openshell.v1.UpdateProviderProfilesRequest.profile:type_name -> openshell.v1.ProviderProfileImportItem + 102, // 109: openshell.v1.UpdateProviderProfilesResponse.diagnostics:type_name -> openshell.v1.ProviderProfileDiagnostic + 122, // 110: openshell.v1.UpdateProviderProfilesResponse.profile:type_name -> openshell.v1.ProviderProfile + 101, // 111: openshell.v1.LintProviderProfilesRequest.profiles:type_name -> openshell.v1.ProviderProfileImportItem + 102, // 112: openshell.v1.LintProviderProfilesResponse.diagnostics:type_name -> openshell.v1.ProviderProfileDiagnostic + 136, // 113: openshell.v1.StaticCredentialBinding.endpoints:type_name -> openshell.v1.StaticCredentialEndpointBinding + 251, // 114: openshell.v1.GetSandboxProviderEnvironmentResponse.environment:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.EnvironmentEntry + 252, // 115: openshell.v1.GetSandboxProviderEnvironmentResponse.credential_expires_at_ms:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpiresAtMsEntry + 253, // 116: openshell.v1.GetSandboxProviderEnvironmentResponse.dynamic_credentials:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry + 254, // 117: openshell.v1.GetSandboxProviderEnvironmentResponse.static_credential_bindings:type_name -> openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry + 4, // 118: openshell.v1.ProviderEnvironmentValue.classification:type_name -> openshell.v1.ProviderEnvironmentValueClassification + 137, // 119: openshell.v1.ProviderEnvironmentValue.static_credential_binding:type_name -> openshell.v1.StaticCredentialBinding + 139, // 120: openshell.v1.ProviderEnvironmentSnapshot.values:type_name -> openshell.v1.ProviderEnvironmentValue + 255, // 121: openshell.v1.ProviderEnvironmentSnapshot.dynamic_credentials:type_name -> openshell.v1.ProviderEnvironmentSnapshot.DynamicCredentialsEntry + 263, // 122: openshell.v1.UpdateConfigRequest.policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 270, // 123: openshell.v1.UpdateConfigRequest.setting_value:type_name -> openshell.sandbox.v1.SettingValue + 144, // 124: openshell.v1.UpdateConfigRequest.merge_operations:type_name -> openshell.v1.PolicyMergeOperation + 256, // 125: openshell.v1.UpdateConfigRequest.annotations:type_name -> openshell.v1.UpdateConfigRequest.AnnotationsEntry + 145, // 126: openshell.v1.PolicyMergeOperation.add_rule:type_name -> openshell.v1.AddNetworkRule + 146, // 127: openshell.v1.PolicyMergeOperation.remove_endpoint:type_name -> openshell.v1.RemoveNetworkEndpoint + 147, // 128: openshell.v1.PolicyMergeOperation.remove_rule:type_name -> openshell.v1.RemoveNetworkRule + 148, // 129: openshell.v1.PolicyMergeOperation.add_deny_rules:type_name -> openshell.v1.AddDenyRules + 149, // 130: openshell.v1.PolicyMergeOperation.add_allow_rules:type_name -> openshell.v1.AddAllowRules + 150, // 131: openshell.v1.PolicyMergeOperation.remove_binary:type_name -> openshell.v1.RemoveNetworkBinary + 271, // 132: openshell.v1.AddNetworkRule.rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule + 272, // 133: openshell.v1.AddDenyRules.deny_rules:type_name -> openshell.sandbox.v1.L7DenyRule + 273, // 134: openshell.v1.AddAllowRules.rules:type_name -> openshell.sandbox.v1.L7Rule + 257, // 135: openshell.v1.UpdateConfigResponse.annotations:type_name -> openshell.v1.UpdateConfigResponse.AnnotationsEntry + 158, // 136: openshell.v1.GetSandboxPolicyStatusResponse.revision:type_name -> openshell.v1.SandboxPolicyRevision + 158, // 137: openshell.v1.ListSandboxPoliciesResponse.revisions:type_name -> openshell.v1.SandboxPolicyRevision + 5, // 138: openshell.v1.ReportPolicyStatusRequest.status:type_name -> openshell.v1.PolicyStatus + 5, // 139: openshell.v1.SandboxPolicyRevision.status:type_name -> openshell.v1.PolicyStatus + 263, // 140: openshell.v1.SandboxPolicyRevision.policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 258, // 141: openshell.v1.SandboxPolicyRevision.provenance:type_name -> openshell.v1.SandboxPolicyRevision.ProvenanceEntry + 90, // 142: openshell.v1.PushSandboxLogsRequest.logs:type_name -> openshell.v1.SandboxLogLine + 90, // 143: openshell.v1.GetSandboxLogsResponse.logs:type_name -> openshell.v1.SandboxLogLine + 165, // 144: openshell.v1.SupervisorMessage.hello:type_name -> openshell.v1.SupervisorHello + 176, // 145: openshell.v1.SupervisorMessage.heartbeat:type_name -> openshell.v1.SupervisorHeartbeat + 187, // 146: openshell.v1.SupervisorMessage.relay_open_result:type_name -> openshell.v1.RelayOpenResult + 188, // 147: openshell.v1.SupervisorMessage.relay_close:type_name -> openshell.v1.RelayClose + 173, // 148: openshell.v1.SupervisorMessage.config_update_result:type_name -> openshell.v1.ConfigUpdateResult + 174, // 149: openshell.v1.SupervisorMessage.config_bootstrap_result:type_name -> openshell.v1.ConfigBootstrapResult + 166, // 150: openshell.v1.GatewayMessage.session_accepted:type_name -> openshell.v1.SessionAccepted + 175, // 151: openshell.v1.GatewayMessage.session_rejected:type_name -> openshell.v1.SessionRejected + 177, // 152: openshell.v1.GatewayMessage.heartbeat:type_name -> openshell.v1.GatewayHeartbeat + 182, // 153: openshell.v1.GatewayMessage.relay_open:type_name -> openshell.v1.RelayOpen + 188, // 154: openshell.v1.GatewayMessage.relay_close:type_name -> openshell.v1.RelayClose + 168, // 155: openshell.v1.GatewayMessage.config_update:type_name -> openshell.v1.ConfigUpdate + 167, // 156: openshell.v1.SessionAccepted.bootstrap:type_name -> openshell.v1.ConfigBootstrap + 274, // 157: openshell.v1.ConfigBootstrap.sandbox_config:type_name -> openshell.sandbox.v1.SandboxConfigSnapshot + 140, // 158: openshell.v1.ConfigBootstrap.provider_environment:type_name -> openshell.v1.ProviderEnvironmentSnapshot + 274, // 159: openshell.v1.ConfigUpdate.sandbox_config:type_name -> openshell.sandbox.v1.SandboxConfigSnapshot + 140, // 160: openshell.v1.ConfigUpdate.provider_environment:type_name -> openshell.v1.ProviderEnvironmentSnapshot + 170, // 161: openshell.v1.ConfigSnapshotRevision.sandbox_config:type_name -> openshell.v1.SandboxConfigRevision + 275, // 162: openshell.v1.SandboxConfigRevision.policy_source:type_name -> openshell.sandbox.v1.PolicySource + 6, // 163: openshell.v1.ConfigComponentApplyResult.component:type_name -> openshell.v1.ConfigComponent + 169, // 164: openshell.v1.ConfigComponentApplyResult.requested_revision:type_name -> openshell.v1.ConfigSnapshotRevision + 169, // 165: openshell.v1.ConfigComponentApplyResult.applied_revision:type_name -> openshell.v1.ConfigSnapshotRevision + 7, // 166: openshell.v1.ConfigComponentApplyResult.outcome:type_name -> openshell.v1.ConfigApplyOutcome + 171, // 167: openshell.v1.ConfigComponentApplyResult.failure:type_name -> openshell.v1.ConfigApplyFailure + 172, // 168: openshell.v1.ConfigUpdateResult.result:type_name -> openshell.v1.ConfigComponentApplyResult + 172, // 169: openshell.v1.ConfigBootstrapResult.results:type_name -> openshell.v1.ConfigComponentApplyResult + 183, // 170: openshell.v1.RelayOpen.ssh:type_name -> openshell.v1.SshRelayTarget + 184, // 171: openshell.v1.RelayOpen.tcp:type_name -> openshell.v1.TcpRelayTarget + 185, // 172: openshell.v1.RelayFrame.init:type_name -> openshell.v1.RelayInit + 189, // 173: openshell.v1.DenialSummary.l7_request_samples:type_name -> openshell.v1.L7RequestSample + 191, // 174: openshell.v1.NetworkActivitySummary.denials_by_group:type_name -> openshell.v1.DenialGroupCount + 271, // 175: openshell.v1.PolicyChunk.proposed_rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule + 263, // 176: openshell.v1.PolicyChunk.current_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 263, // 177: openshell.v1.PolicyChunk.candidate_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 190, // 178: openshell.v1.SubmitPolicyAnalysisRequest.summaries:type_name -> openshell.v1.DenialSummary + 193, // 179: openshell.v1.SubmitPolicyAnalysisRequest.proposed_chunks:type_name -> openshell.v1.PolicyChunk + 192, // 180: openshell.v1.SubmitPolicyAnalysisRequest.network_activity_summaries:type_name -> openshell.v1.NetworkActivitySummary + 193, // 181: openshell.v1.GetDraftPolicyResponse.chunks:type_name -> openshell.v1.PolicyChunk + 203, // 182: openshell.v1.ApproveAllDraftChunksRequest.approvals:type_name -> openshell.v1.DraftChunkApproval + 271, // 183: openshell.v1.EditDraftChunkRequest.proposed_rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule + 213, // 184: openshell.v1.GetDraftHistoryResponse.entries:type_name -> openshell.v1.DraftHistoryEntry + 263, // 185: openshell.v1.PolicyRevisionPayload.policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 259, // 186: openshell.v1.PolicyRevisionPayload.provenance:type_name -> openshell.v1.PolicyRevisionPayload.ProvenanceEntry + 271, // 187: openshell.v1.DraftChunkPayload.proposed_rule:type_name -> openshell.sandbox.v1.NetworkPolicyRule + 263, // 188: openshell.v1.DraftChunkPayload.current_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 263, // 189: openshell.v1.DraftChunkPayload.candidate_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 260, // 190: openshell.v1.StoredPolicyRevision.provenance:type_name -> openshell.v1.StoredPolicyRevision.ProvenanceEntry + 263, // 191: openshell.v1.StoredDraftChunk.current_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 263, // 192: openshell.v1.StoredDraftChunk.candidate_effective_policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 261, // 193: openshell.v1.CreateWorkspaceRequest.labels:type_name -> openshell.v1.CreateWorkspaceRequest.LabelsEntry + 276, // 194: openshell.v1.CreateWorkspaceResponse.workspace:type_name -> openshell.datamodel.v1.Workspace + 276, // 195: openshell.v1.GetWorkspaceResponse.workspace:type_name -> openshell.datamodel.v1.Workspace + 276, // 196: openshell.v1.ListWorkspacesResponse.workspaces:type_name -> openshell.datamodel.v1.Workspace + 262, // 197: openshell.v1.WorkspaceMember.metadata:type_name -> openshell.datamodel.v1.ObjectMeta + 9, // 198: openshell.v1.WorkspaceMember.role:type_name -> openshell.v1.WorkspaceRole + 9, // 199: openshell.v1.AddWorkspaceMemberRequest.role:type_name -> openshell.v1.WorkspaceRole + 227, // 200: openshell.v1.AddWorkspaceMemberResponse.member:type_name -> openshell.v1.WorkspaceMember + 227, // 201: openshell.v1.ListWorkspaceMembersResponse.members:type_name -> openshell.v1.WorkspaceMember + 267, // 202: openshell.v1.StoredProviderCredentialRefreshState.SecretMaterialHandlesEntry.value:type_name -> openshell.datamodel.v1.CredentialHandle + 106, // 203: openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry.value:type_name -> openshell.v1.ProviderProfileCredential + 137, // 204: openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry.value:type_name -> openshell.v1.StaticCredentialBinding + 106, // 205: openshell.v1.ProviderEnvironmentSnapshot.DynamicCredentialsEntry.value:type_name -> openshell.v1.ProviderProfileCredential + 15, // 206: openshell.v1.OpenShell.Health:input_type -> openshell.v1.HealthRequest + 17, // 207: openshell.v1.OpenShell.GetCurrentUser:input_type -> openshell.v1.GetCurrentUserRequest + 19, // 208: openshell.v1.OpenShell.GetGatewayInfo:input_type -> openshell.v1.GetGatewayInfoRequest + 42, // 209: openshell.v1.OpenShell.CreateSandbox:input_type -> openshell.v1.CreateSandboxRequest + 50, // 210: openshell.v1.OpenShell.BeginRootfsTarStaging:input_type -> openshell.v1.BeginRootfsTarStagingRequest + 52, // 211: openshell.v1.OpenShell.GetSandbox:input_type -> openshell.v1.GetSandboxRequest + 53, // 212: openshell.v1.OpenShell.ListSandboxes:input_type -> openshell.v1.ListSandboxesRequest + 43, // 213: openshell.v1.OpenShell.CreateSandboxTemplate:input_type -> openshell.v1.CreateSandboxTemplateRequest + 44, // 214: openshell.v1.OpenShell.GetSandboxTemplate:input_type -> openshell.v1.GetSandboxTemplateRequest + 45, // 215: openshell.v1.OpenShell.ListSandboxTemplates:input_type -> openshell.v1.ListSandboxTemplatesRequest + 46, // 216: openshell.v1.OpenShell.DeleteSandboxTemplate:input_type -> openshell.v1.DeleteSandboxTemplateRequest + 54, // 217: openshell.v1.OpenShell.ListSandboxProviders:input_type -> openshell.v1.ListSandboxProvidersRequest + 55, // 218: openshell.v1.OpenShell.AttachSandboxProvider:input_type -> openshell.v1.AttachSandboxProviderRequest + 56, // 219: openshell.v1.OpenShell.DetachSandboxProvider:input_type -> openshell.v1.DetachSandboxProviderRequest + 57, // 220: openshell.v1.OpenShell.DeleteSandbox:input_type -> openshell.v1.DeleteSandboxRequest + 58, // 221: openshell.v1.OpenShell.StopSandbox:input_type -> openshell.v1.StopSandboxRequest + 59, // 222: openshell.v1.OpenShell.StartSandbox:input_type -> openshell.v1.StartSandboxRequest + 66, // 223: openshell.v1.OpenShell.CreateSshSession:input_type -> openshell.v1.CreateSshSessionRequest + 68, // 224: openshell.v1.OpenShell.ExposeService:input_type -> openshell.v1.ExposeServiceRequest + 69, // 225: openshell.v1.OpenShell.GetService:input_type -> openshell.v1.GetServiceRequest + 70, // 226: openshell.v1.OpenShell.ListServices:input_type -> openshell.v1.ListServicesRequest + 72, // 227: openshell.v1.OpenShell.DeleteService:input_type -> openshell.v1.DeleteServiceRequest + 76, // 228: openshell.v1.OpenShell.RevokeSshSession:input_type -> openshell.v1.RevokeSshSessionRequest + 78, // 229: openshell.v1.OpenShell.ExecSandbox:input_type -> openshell.v1.ExecSandboxRequest + 84, // 230: openshell.v1.OpenShell.ForwardTcp:input_type -> openshell.v1.TcpForwardFrame + 85, // 231: openshell.v1.OpenShell.ExecSandboxInteractive:input_type -> openshell.v1.ExecSandboxInput + 92, // 232: openshell.v1.OpenShell.CreateProvider:input_type -> openshell.v1.CreateProviderRequest + 93, // 233: openshell.v1.OpenShell.GetProvider:input_type -> openshell.v1.GetProviderRequest + 94, // 234: openshell.v1.OpenShell.ListProviders:input_type -> openshell.v1.ListProvidersRequest + 99, // 235: openshell.v1.OpenShell.ListProviderProfiles:input_type -> openshell.v1.ListProviderProfilesRequest + 100, // 236: openshell.v1.OpenShell.GetProviderProfile:input_type -> openshell.v1.GetProviderProfileRequest + 126, // 237: openshell.v1.OpenShell.ImportProviderProfiles:input_type -> openshell.v1.ImportProviderProfilesRequest + 128, // 238: openshell.v1.OpenShell.UpdateProviderProfiles:input_type -> openshell.v1.UpdateProviderProfilesRequest + 130, // 239: openshell.v1.OpenShell.LintProviderProfiles:input_type -> openshell.v1.LintProviderProfilesRequest + 95, // 240: openshell.v1.OpenShell.UpdateProvider:input_type -> openshell.v1.UpdateProviderRequest + 114, // 241: openshell.v1.OpenShell.GetProviderRefreshStatus:input_type -> openshell.v1.GetProviderRefreshStatusRequest + 116, // 242: openshell.v1.OpenShell.ConfigureProviderRefresh:input_type -> openshell.v1.ConfigureProviderRefreshRequest + 118, // 243: openshell.v1.OpenShell.RotateProviderCredential:input_type -> openshell.v1.RotateProviderCredentialRequest + 120, // 244: openshell.v1.OpenShell.DeleteProviderRefresh:input_type -> openshell.v1.DeleteProviderRefreshRequest + 96, // 245: openshell.v1.OpenShell.DeleteProvider:input_type -> openshell.v1.DeleteProviderRequest + 133, // 246: openshell.v1.OpenShell.DeleteProviderProfile:input_type -> openshell.v1.DeleteProviderProfileRequest + 277, // 247: openshell.v1.OpenShell.GetSandboxConfig:input_type -> openshell.sandbox.v1.GetSandboxConfigRequest + 278, // 248: openshell.v1.OpenShell.GetGatewayConfig:input_type -> openshell.sandbox.v1.GetGatewayConfigRequest + 143, // 249: openshell.v1.OpenShell.UpdateConfig:input_type -> openshell.v1.UpdateConfigRequest + 152, // 250: openshell.v1.OpenShell.GetSandboxPolicyStatus:input_type -> openshell.v1.GetSandboxPolicyStatusRequest + 154, // 251: openshell.v1.OpenShell.ListSandboxPolicies:input_type -> openshell.v1.ListSandboxPoliciesRequest + 156, // 252: openshell.v1.OpenShell.ReportPolicyStatus:input_type -> openshell.v1.ReportPolicyStatusRequest + 135, // 253: openshell.v1.OpenShell.GetSandboxProviderEnvironment:input_type -> openshell.v1.GetSandboxProviderEnvironmentRequest + 141, // 254: openshell.v1.OpenShell.ExchangeProviderSubjectToken:input_type -> openshell.v1.ExchangeProviderSubjectTokenRequest + 159, // 255: openshell.v1.OpenShell.GetSandboxLogs:input_type -> openshell.v1.GetSandboxLogsRequest + 160, // 256: openshell.v1.OpenShell.PushSandboxLogs:input_type -> openshell.v1.PushSandboxLogsRequest + 163, // 257: openshell.v1.OpenShell.ConnectSupervisor:input_type -> openshell.v1.SupervisorMessage + 178, // 258: openshell.v1.OpenShell.ReportMainProcessExit:input_type -> openshell.v1.ReportMainProcessExitRequest + 180, // 259: openshell.v1.OpenShell.FinalizeMainProcessExit:input_type -> openshell.v1.FinalizeMainProcessExitRequest + 186, // 260: openshell.v1.OpenShell.RelayStream:input_type -> openshell.v1.RelayFrame + 88, // 261: openshell.v1.OpenShell.WatchSandbox:input_type -> openshell.v1.WatchSandboxRequest + 195, // 262: openshell.v1.OpenShell.SubmitPolicyAnalysis:input_type -> openshell.v1.SubmitPolicyAnalysisRequest + 197, // 263: openshell.v1.OpenShell.GetDraftPolicy:input_type -> openshell.v1.GetDraftPolicyRequest + 199, // 264: openshell.v1.OpenShell.ApproveDraftChunk:input_type -> openshell.v1.ApproveDraftChunkRequest + 201, // 265: openshell.v1.OpenShell.RejectDraftChunk:input_type -> openshell.v1.RejectDraftChunkRequest + 204, // 266: openshell.v1.OpenShell.ApproveAllDraftChunks:input_type -> openshell.v1.ApproveAllDraftChunksRequest + 206, // 267: openshell.v1.OpenShell.EditDraftChunk:input_type -> openshell.v1.EditDraftChunkRequest + 208, // 268: openshell.v1.OpenShell.UndoDraftChunk:input_type -> openshell.v1.UndoDraftChunkRequest + 210, // 269: openshell.v1.OpenShell.ClearDraftChunks:input_type -> openshell.v1.ClearDraftChunksRequest + 212, // 270: openshell.v1.OpenShell.GetDraftHistory:input_type -> openshell.v1.GetDraftHistoryRequest + 11, // 271: openshell.v1.OpenShell.IssueSandboxToken:input_type -> openshell.v1.IssueSandboxTokenRequest + 13, // 272: openshell.v1.OpenShell.RefreshSandboxToken:input_type -> openshell.v1.RefreshSandboxTokenRequest + 219, // 273: openshell.v1.OpenShell.CreateWorkspace:input_type -> openshell.v1.CreateWorkspaceRequest + 221, // 274: openshell.v1.OpenShell.GetWorkspace:input_type -> openshell.v1.GetWorkspaceRequest + 223, // 275: openshell.v1.OpenShell.ListWorkspaces:input_type -> openshell.v1.ListWorkspacesRequest + 225, // 276: openshell.v1.OpenShell.DeleteWorkspace:input_type -> openshell.v1.DeleteWorkspaceRequest + 228, // 277: openshell.v1.OpenShell.AddWorkspaceMember:input_type -> openshell.v1.AddWorkspaceMemberRequest + 230, // 278: openshell.v1.OpenShell.RemoveWorkspaceMember:input_type -> openshell.v1.RemoveWorkspaceMemberRequest + 232, // 279: openshell.v1.OpenShell.ListWorkspaceMembers:input_type -> openshell.v1.ListWorkspaceMembersRequest + 16, // 280: openshell.v1.OpenShell.Health:output_type -> openshell.v1.HealthResponse + 18, // 281: openshell.v1.OpenShell.GetCurrentUser:output_type -> openshell.v1.GetCurrentUserResponse + 20, // 282: openshell.v1.OpenShell.GetGatewayInfo:output_type -> openshell.v1.GetGatewayInfoResponse + 60, // 283: openshell.v1.OpenShell.CreateSandbox:output_type -> openshell.v1.SandboxResponse + 51, // 284: openshell.v1.OpenShell.BeginRootfsTarStaging:output_type -> openshell.v1.BeginRootfsTarStagingResponse + 60, // 285: openshell.v1.OpenShell.GetSandbox:output_type -> openshell.v1.SandboxResponse + 61, // 286: openshell.v1.OpenShell.ListSandboxes:output_type -> openshell.v1.ListSandboxesResponse + 47, // 287: openshell.v1.OpenShell.CreateSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse + 47, // 288: openshell.v1.OpenShell.GetSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse + 48, // 289: openshell.v1.OpenShell.ListSandboxTemplates:output_type -> openshell.v1.ListSandboxTemplatesResponse + 49, // 290: openshell.v1.OpenShell.DeleteSandboxTemplate:output_type -> openshell.v1.DeleteSandboxTemplateResponse + 62, // 291: openshell.v1.OpenShell.ListSandboxProviders:output_type -> openshell.v1.ListSandboxProvidersResponse + 63, // 292: openshell.v1.OpenShell.AttachSandboxProvider:output_type -> openshell.v1.AttachSandboxProviderResponse + 64, // 293: openshell.v1.OpenShell.DetachSandboxProvider:output_type -> openshell.v1.DetachSandboxProviderResponse + 65, // 294: openshell.v1.OpenShell.DeleteSandbox:output_type -> openshell.v1.DeleteSandboxResponse + 60, // 295: openshell.v1.OpenShell.StopSandbox:output_type -> openshell.v1.SandboxResponse + 60, // 296: openshell.v1.OpenShell.StartSandbox:output_type -> openshell.v1.SandboxResponse + 67, // 297: openshell.v1.OpenShell.CreateSshSession:output_type -> openshell.v1.CreateSshSessionResponse + 75, // 298: openshell.v1.OpenShell.ExposeService:output_type -> openshell.v1.ServiceEndpointResponse + 75, // 299: openshell.v1.OpenShell.GetService:output_type -> openshell.v1.ServiceEndpointResponse + 71, // 300: openshell.v1.OpenShell.ListServices:output_type -> openshell.v1.ListServicesResponse + 73, // 301: openshell.v1.OpenShell.DeleteService:output_type -> openshell.v1.DeleteServiceResponse + 77, // 302: openshell.v1.OpenShell.RevokeSshSession:output_type -> openshell.v1.RevokeSshSessionResponse + 82, // 303: openshell.v1.OpenShell.ExecSandbox:output_type -> openshell.v1.ExecSandboxEvent + 84, // 304: openshell.v1.OpenShell.ForwardTcp:output_type -> openshell.v1.TcpForwardFrame + 82, // 305: openshell.v1.OpenShell.ExecSandboxInteractive:output_type -> openshell.v1.ExecSandboxEvent + 97, // 306: openshell.v1.OpenShell.CreateProvider:output_type -> openshell.v1.ProviderResponse + 97, // 307: openshell.v1.OpenShell.GetProvider:output_type -> openshell.v1.ProviderResponse + 98, // 308: openshell.v1.OpenShell.ListProviders:output_type -> openshell.v1.ListProvidersResponse + 125, // 309: openshell.v1.OpenShell.ListProviderProfiles:output_type -> openshell.v1.ListProviderProfilesResponse + 124, // 310: openshell.v1.OpenShell.GetProviderProfile:output_type -> openshell.v1.ProviderProfileResponse + 127, // 311: openshell.v1.OpenShell.ImportProviderProfiles:output_type -> openshell.v1.ImportProviderProfilesResponse + 129, // 312: openshell.v1.OpenShell.UpdateProviderProfiles:output_type -> openshell.v1.UpdateProviderProfilesResponse + 131, // 313: openshell.v1.OpenShell.LintProviderProfiles:output_type -> openshell.v1.LintProviderProfilesResponse + 97, // 314: openshell.v1.OpenShell.UpdateProvider:output_type -> openshell.v1.ProviderResponse + 115, // 315: openshell.v1.OpenShell.GetProviderRefreshStatus:output_type -> openshell.v1.GetProviderRefreshStatusResponse + 117, // 316: openshell.v1.OpenShell.ConfigureProviderRefresh:output_type -> openshell.v1.ConfigureProviderRefreshResponse + 119, // 317: openshell.v1.OpenShell.RotateProviderCredential:output_type -> openshell.v1.RotateProviderCredentialResponse + 121, // 318: openshell.v1.OpenShell.DeleteProviderRefresh:output_type -> openshell.v1.DeleteProviderRefreshResponse + 132, // 319: openshell.v1.OpenShell.DeleteProvider:output_type -> openshell.v1.DeleteProviderResponse + 134, // 320: openshell.v1.OpenShell.DeleteProviderProfile:output_type -> openshell.v1.DeleteProviderProfileResponse + 279, // 321: openshell.v1.OpenShell.GetSandboxConfig:output_type -> openshell.sandbox.v1.GetSandboxConfigResponse + 280, // 322: openshell.v1.OpenShell.GetGatewayConfig:output_type -> openshell.sandbox.v1.GetGatewayConfigResponse + 151, // 323: openshell.v1.OpenShell.UpdateConfig:output_type -> openshell.v1.UpdateConfigResponse + 153, // 324: openshell.v1.OpenShell.GetSandboxPolicyStatus:output_type -> openshell.v1.GetSandboxPolicyStatusResponse + 155, // 325: openshell.v1.OpenShell.ListSandboxPolicies:output_type -> openshell.v1.ListSandboxPoliciesResponse + 157, // 326: openshell.v1.OpenShell.ReportPolicyStatus:output_type -> openshell.v1.ReportPolicyStatusResponse + 138, // 327: openshell.v1.OpenShell.GetSandboxProviderEnvironment:output_type -> openshell.v1.GetSandboxProviderEnvironmentResponse + 142, // 328: openshell.v1.OpenShell.ExchangeProviderSubjectToken:output_type -> openshell.v1.ExchangeProviderSubjectTokenResponse + 162, // 329: openshell.v1.OpenShell.GetSandboxLogs:output_type -> openshell.v1.GetSandboxLogsResponse + 161, // 330: openshell.v1.OpenShell.PushSandboxLogs:output_type -> openshell.v1.PushSandboxLogsResponse + 164, // 331: openshell.v1.OpenShell.ConnectSupervisor:output_type -> openshell.v1.GatewayMessage + 179, // 332: openshell.v1.OpenShell.ReportMainProcessExit:output_type -> openshell.v1.ReportMainProcessExitResponse + 181, // 333: openshell.v1.OpenShell.FinalizeMainProcessExit:output_type -> openshell.v1.FinalizeMainProcessExitResponse + 186, // 334: openshell.v1.OpenShell.RelayStream:output_type -> openshell.v1.RelayFrame + 89, // 335: openshell.v1.OpenShell.WatchSandbox:output_type -> openshell.v1.SandboxStreamEvent + 196, // 336: openshell.v1.OpenShell.SubmitPolicyAnalysis:output_type -> openshell.v1.SubmitPolicyAnalysisResponse + 198, // 337: openshell.v1.OpenShell.GetDraftPolicy:output_type -> openshell.v1.GetDraftPolicyResponse + 200, // 338: openshell.v1.OpenShell.ApproveDraftChunk:output_type -> openshell.v1.ApproveDraftChunkResponse + 202, // 339: openshell.v1.OpenShell.RejectDraftChunk:output_type -> openshell.v1.RejectDraftChunkResponse + 205, // 340: openshell.v1.OpenShell.ApproveAllDraftChunks:output_type -> openshell.v1.ApproveAllDraftChunksResponse + 207, // 341: openshell.v1.OpenShell.EditDraftChunk:output_type -> openshell.v1.EditDraftChunkResponse + 209, // 342: openshell.v1.OpenShell.UndoDraftChunk:output_type -> openshell.v1.UndoDraftChunkResponse + 211, // 343: openshell.v1.OpenShell.ClearDraftChunks:output_type -> openshell.v1.ClearDraftChunksResponse + 214, // 344: openshell.v1.OpenShell.GetDraftHistory:output_type -> openshell.v1.GetDraftHistoryResponse + 12, // 345: openshell.v1.OpenShell.IssueSandboxToken:output_type -> openshell.v1.IssueSandboxTokenResponse + 14, // 346: openshell.v1.OpenShell.RefreshSandboxToken:output_type -> openshell.v1.RefreshSandboxTokenResponse + 220, // 347: openshell.v1.OpenShell.CreateWorkspace:output_type -> openshell.v1.CreateWorkspaceResponse + 222, // 348: openshell.v1.OpenShell.GetWorkspace:output_type -> openshell.v1.GetWorkspaceResponse + 224, // 349: openshell.v1.OpenShell.ListWorkspaces:output_type -> openshell.v1.ListWorkspacesResponse + 226, // 350: openshell.v1.OpenShell.DeleteWorkspace:output_type -> openshell.v1.DeleteWorkspaceResponse + 229, // 351: openshell.v1.OpenShell.AddWorkspaceMember:output_type -> openshell.v1.AddWorkspaceMemberResponse + 231, // 352: openshell.v1.OpenShell.RemoveWorkspaceMember:output_type -> openshell.v1.RemoveWorkspaceMemberResponse + 233, // 353: openshell.v1.OpenShell.ListWorkspaceMembers:output_type -> openshell.v1.ListWorkspaceMembersResponse + 280, // [280:354] is the sub-list for method output_type + 206, // [206:280] is the sub-list for method input_type + 206, // [206:206] is the sub-list for extension type_name + 206, // [206:206] is the sub-list for extension extendee + 0, // [0:206] is the sub-list for field type_name } func init() { file_openshell_proto_init() } @@ -17251,7 +18300,8 @@ func file_openshell_proto_init() { (*SandboxStreamEvent_DraftPolicyUpdate)(nil), } file_openshell_proto_msgTypes[105].OneofWrappers = []any{} - file_openshell_proto_msgTypes[131].OneofWrappers = []any{ + file_openshell_proto_msgTypes[128].OneofWrappers = []any{} + file_openshell_proto_msgTypes[133].OneofWrappers = []any{ (*PolicyMergeOperation_AddRule)(nil), (*PolicyMergeOperation_RemoveEndpoint)(nil), (*PolicyMergeOperation_RemoveRule)(nil), @@ -17259,36 +18309,47 @@ func file_openshell_proto_init() { (*PolicyMergeOperation_AddAllowRules)(nil), (*PolicyMergeOperation_RemoveBinary)(nil), } - file_openshell_proto_msgTypes[150].OneofWrappers = []any{ + file_openshell_proto_msgTypes[152].OneofWrappers = []any{ (*SupervisorMessage_Hello)(nil), (*SupervisorMessage_Heartbeat)(nil), (*SupervisorMessage_RelayOpenResult)(nil), (*SupervisorMessage_RelayClose)(nil), + (*SupervisorMessage_ConfigUpdateResult)(nil), + (*SupervisorMessage_ConfigBootstrapResult)(nil), } - file_openshell_proto_msgTypes[151].OneofWrappers = []any{ + file_openshell_proto_msgTypes[153].OneofWrappers = []any{ (*GatewayMessage_SessionAccepted)(nil), (*GatewayMessage_SessionRejected)(nil), (*GatewayMessage_Heartbeat)(nil), (*GatewayMessage_RelayOpen)(nil), (*GatewayMessage_RelayClose)(nil), + (*GatewayMessage_ConfigUpdate)(nil), + } + file_openshell_proto_msgTypes[157].OneofWrappers = []any{ + (*ConfigUpdate_SandboxConfig)(nil), + (*ConfigUpdate_ProviderEnvironment)(nil), + } + file_openshell_proto_msgTypes[158].OneofWrappers = []any{ + (*ConfigSnapshotRevision_SandboxConfig)(nil), + (*ConfigSnapshotRevision_ProviderEnvironment)(nil), } - file_openshell_proto_msgTypes[161].OneofWrappers = []any{ + file_openshell_proto_msgTypes[171].OneofWrappers = []any{ (*RelayOpen_Ssh)(nil), (*RelayOpen_Tcp)(nil), } - file_openshell_proto_msgTypes[165].OneofWrappers = []any{ + file_openshell_proto_msgTypes[175].OneofWrappers = []any{ (*RelayFrame_Init)(nil), (*RelayFrame_Data)(nil), } - file_openshell_proto_msgTypes[196].OneofWrappers = []any{} - file_openshell_proto_msgTypes[197].OneofWrappers = []any{} + file_openshell_proto_msgTypes[206].OneofWrappers = []any{} + file_openshell_proto_msgTypes[207].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_openshell_proto_rawDesc), len(file_openshell_proto_rawDesc)), - NumEnums: 8, - NumMessages: 240, + NumEnums: 11, + NumMessages: 251, NumExtensions: 0, NumServices: 1, }, diff --git a/sdk/go/proto/openshellv1/openshell_grpc.pb.go b/sdk/go/proto/openshellv1/openshell_grpc.pb.go index d8f3c91008..8d68c4bb82 100644 --- a/sdk/go/proto/openshellv1/openshell_grpc.pb.go +++ b/sdk/go/proto/openshellv1/openshell_grpc.pb.go @@ -234,9 +234,10 @@ type OpenShellClient interface { // // 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. Peers must report the same exact protocol_revision during the + // handshake. Raw service bytes flow over RelayStream calls (separate HTTP/2 + // streams on the same connection), not over this stream. ConnectSupervisor(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[SupervisorMessage, GatewayMessage], error) // Persist the canonical main process result before the supervisor exits. ReportMainProcessExit(ctx context.Context, in *ReportMainProcessExitRequest, opts ...grpc.CallOption) (*ReportMainProcessExitResponse, error) @@ -1224,9 +1225,10 @@ type OpenShellServer interface { // // 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. Peers must report the same exact protocol_revision during the + // handshake. Raw service bytes flow over RelayStream calls (separate HTTP/2 + // streams on the same connection), not over this stream. ConnectSupervisor(grpc.BidiStreamingServer[SupervisorMessage, GatewayMessage]) error // Persist the canonical main process result before the supervisor exits. ReportMainProcessExit(context.Context, *ReportMainProcessExitRequest) (*ReportMainProcessExitResponse, error) diff --git a/sdk/go/proto/sandboxv1/sandbox.pb.go b/sdk/go/proto/sandboxv1/sandbox.pb.go index 989589002b..386f7b4cfd 100644 --- a/sdk/go/proto/sandboxv1/sandbox.pb.go +++ b/sdk/go/proto/sandboxv1/sandbox.pb.go @@ -75,7 +75,7 @@ func (SettingScope) EnumDescriptor() ([]byte, []int) { return file_sandbox_proto_rawDescGZIP(), []int{0} } -// Source used for the policy payload in GetSandboxConfigResponse. +// Source used for a sandbox configuration payload. type PolicySource int32 const ( @@ -1801,6 +1801,139 @@ func (x *EffectiveSetting) GetScope() SettingScope { return SettingScope_SETTING_SCOPE_UNSPECIFIED } +// Complete effective sandbox configuration delivered to a supervisor. +type SandboxConfigSnapshot struct { + state protoimpl.MessageState `protogen:"open.v1"` + Policy *SandboxPolicy `protobuf:"bytes,1,opt,name=policy,proto3" json:"policy,omitempty"` + Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` + PolicyHash string `protobuf:"bytes,3,opt,name=policy_hash,json=policyHash,proto3" json:"policy_hash,omitempty"` + Settings map[string]*EffectiveSetting `protobuf:"bytes,4,rep,name=settings,proto3" json:"settings,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + ConfigRevision uint64 `protobuf:"varint,5,opt,name=config_revision,json=configRevision,proto3" json:"config_revision,omitempty"` + PolicySource PolicySource `protobuf:"varint,6,opt,name=policy_source,json=policySource,proto3,enum=openshell.sandbox.v1.PolicySource" json:"policy_source,omitempty"` + GlobalPolicyVersion uint32 `protobuf:"varint,7,opt,name=global_policy_version,json=globalPolicyVersion,proto3" json:"global_policy_version,omitempty"` + ProviderEnvRevision uint64 `protobuf:"varint,8,opt,name=provider_env_revision,json=providerEnvRevision,proto3" json:"provider_env_revision,omitempty"` + SupervisorMiddlewareServices []*SupervisorMiddlewareService `protobuf:"bytes,9,rep,name=supervisor_middleware_services,json=supervisorMiddlewareServices,proto3" json:"supervisor_middleware_services,omitempty"` + Workspace string `protobuf:"bytes,10,opt,name=workspace,proto3" json:"workspace,omitempty"` + PolicyValidationFailureMode string `protobuf:"bytes,11,opt,name=policy_validation_failure_mode,json=policyValidationFailureMode,proto3" json:"policy_validation_failure_mode,omitempty"` + ExtensionAuthenticationEnabled bool `protobuf:"varint,12,opt,name=extension_authentication_enabled,json=extensionAuthenticationEnabled,proto3" json:"extension_authentication_enabled,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SandboxConfigSnapshot) Reset() { + *x = SandboxConfigSnapshot{} + mi := &file_sandbox_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SandboxConfigSnapshot) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SandboxConfigSnapshot) ProtoMessage() {} + +func (x *SandboxConfigSnapshot) ProtoReflect() protoreflect.Message { + mi := &file_sandbox_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SandboxConfigSnapshot.ProtoReflect.Descriptor instead. +func (*SandboxConfigSnapshot) Descriptor() ([]byte, []int) { + return file_sandbox_proto_rawDescGZIP(), []int{21} +} + +func (x *SandboxConfigSnapshot) GetPolicy() *SandboxPolicy { + if x != nil { + return x.Policy + } + return nil +} + +func (x *SandboxConfigSnapshot) GetVersion() uint32 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *SandboxConfigSnapshot) GetPolicyHash() string { + if x != nil { + return x.PolicyHash + } + return "" +} + +func (x *SandboxConfigSnapshot) GetSettings() map[string]*EffectiveSetting { + if x != nil { + return x.Settings + } + return nil +} + +func (x *SandboxConfigSnapshot) GetConfigRevision() uint64 { + if x != nil { + return x.ConfigRevision + } + return 0 +} + +func (x *SandboxConfigSnapshot) GetPolicySource() PolicySource { + if x != nil { + return x.PolicySource + } + return PolicySource_POLICY_SOURCE_UNSPECIFIED +} + +func (x *SandboxConfigSnapshot) GetGlobalPolicyVersion() uint32 { + if x != nil { + return x.GlobalPolicyVersion + } + return 0 +} + +func (x *SandboxConfigSnapshot) GetProviderEnvRevision() uint64 { + if x != nil { + return x.ProviderEnvRevision + } + return 0 +} + +func (x *SandboxConfigSnapshot) GetSupervisorMiddlewareServices() []*SupervisorMiddlewareService { + if x != nil { + return x.SupervisorMiddlewareServices + } + return nil +} + +func (x *SandboxConfigSnapshot) GetWorkspace() string { + if x != nil { + return x.Workspace + } + return "" +} + +func (x *SandboxConfigSnapshot) GetPolicyValidationFailureMode() string { + if x != nil { + return x.PolicyValidationFailureMode + } + return "" +} + +func (x *SandboxConfigSnapshot) GetExtensionAuthenticationEnabled() bool { + if x != nil { + return x.ExtensionAuthenticationEnabled + } + return false +} + // Response containing effective sandbox settings and policy. type GetSandboxConfigResponse struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1843,7 +1976,7 @@ type GetSandboxConfigResponse struct { func (x *GetSandboxConfigResponse) Reset() { *x = GetSandboxConfigResponse{} - mi := &file_sandbox_proto_msgTypes[21] + mi := &file_sandbox_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1855,7 +1988,7 @@ func (x *GetSandboxConfigResponse) String() string { func (*GetSandboxConfigResponse) ProtoMessage() {} func (x *GetSandboxConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_sandbox_proto_msgTypes[21] + mi := &file_sandbox_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1868,7 +2001,7 @@ func (x *GetSandboxConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSandboxConfigResponse.ProtoReflect.Descriptor instead. func (*GetSandboxConfigResponse) Descriptor() ([]byte, []int) { - return file_sandbox_proto_rawDescGZIP(), []int{21} + return file_sandbox_proto_rawDescGZIP(), []int{22} } func (x *GetSandboxConfigResponse) GetPolicy() *SandboxPolicy { @@ -1988,7 +2121,7 @@ type SupervisorMiddlewareService struct { func (x *SupervisorMiddlewareService) Reset() { *x = SupervisorMiddlewareService{} - mi := &file_sandbox_proto_msgTypes[22] + mi := &file_sandbox_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2000,7 +2133,7 @@ func (x *SupervisorMiddlewareService) String() string { func (*SupervisorMiddlewareService) ProtoMessage() {} func (x *SupervisorMiddlewareService) ProtoReflect() protoreflect.Message { - mi := &file_sandbox_proto_msgTypes[22] + mi := &file_sandbox_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2013,7 +2146,7 @@ func (x *SupervisorMiddlewareService) ProtoReflect() protoreflect.Message { // Deprecated: Use SupervisorMiddlewareService.ProtoReflect.Descriptor instead. func (*SupervisorMiddlewareService) Descriptor() ([]byte, []int) { - return file_sandbox_proto_rawDescGZIP(), []int{22} + return file_sandbox_proto_rawDescGZIP(), []int{23} } func (x *SupervisorMiddlewareService) GetName() string { @@ -2220,7 +2353,25 @@ const file_sandbox_proto_rawDesc = "" + "\x05value\"\x86\x01\n" + "\x10EffectiveSetting\x128\n" + "\x05value\x18\x01 \x01(\v2\".openshell.sandbox.v1.SettingValueR\x05value\x128\n" + - "\x05scope\x18\x02 \x01(\x0e2\".openshell.sandbox.v1.SettingScopeR\x05scope\"\xd1\x06\n" + + "\x05scope\x18\x02 \x01(\x0e2\".openshell.sandbox.v1.SettingScopeR\x05scope\"\xcb\x06\n" + + "\x15SandboxConfigSnapshot\x12;\n" + + "\x06policy\x18\x01 \x01(\v2#.openshell.sandbox.v1.SandboxPolicyR\x06policy\x12\x18\n" + + "\aversion\x18\x02 \x01(\rR\aversion\x12\x1f\n" + + "\vpolicy_hash\x18\x03 \x01(\tR\n" + + "policyHash\x12U\n" + + "\bsettings\x18\x04 \x03(\v29.openshell.sandbox.v1.SandboxConfigSnapshot.SettingsEntryR\bsettings\x12'\n" + + "\x0fconfig_revision\x18\x05 \x01(\x04R\x0econfigRevision\x12G\n" + + "\rpolicy_source\x18\x06 \x01(\x0e2\".openshell.sandbox.v1.PolicySourceR\fpolicySource\x122\n" + + "\x15global_policy_version\x18\a \x01(\rR\x13globalPolicyVersion\x122\n" + + "\x15provider_env_revision\x18\b \x01(\x04R\x13providerEnvRevision\x12w\n" + + "\x1esupervisor_middleware_services\x18\t \x03(\v21.openshell.sandbox.v1.SupervisorMiddlewareServiceR\x1csupervisorMiddlewareServices\x12\x1c\n" + + "\tworkspace\x18\n" + + " \x01(\tR\tworkspace\x12C\n" + + "\x1epolicy_validation_failure_mode\x18\v \x01(\tR\x1bpolicyValidationFailureMode\x12H\n" + + " extension_authentication_enabled\x18\f \x01(\bR\x1eextensionAuthenticationEnabled\x1ac\n" + + "\rSettingsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12<\n" + + "\x05value\x18\x02 \x01(\v2&.openshell.sandbox.v1.EffectiveSettingR\x05value:\x028\x01\"\xd1\x06\n" + "\x18GetSandboxConfigResponse\x12;\n" + "\x06policy\x18\x01 \x01(\v2#.openshell.sandbox.v1.SandboxPolicyR\x06policy\x12\x18\n" + "\aversion\x18\x02 \x01(\rR\aversion\x12\x1f\n" + @@ -2269,7 +2420,7 @@ func file_sandbox_proto_rawDescGZIP() []byte { } var file_sandbox_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_sandbox_proto_msgTypes = make([]protoimpl.MessageInfo, 32) +var file_sandbox_proto_msgTypes = make([]protoimpl.MessageInfo, 34) var file_sandbox_proto_goTypes = []any{ (SettingScope)(0), // 0: openshell.sandbox.v1.SettingScope (PolicySource)(0), // 1: openshell.sandbox.v1.PolicySource @@ -2294,60 +2445,67 @@ var file_sandbox_proto_goTypes = []any{ (*GetGatewayConfigResponse)(nil), // 20: openshell.sandbox.v1.GetGatewayConfigResponse (*SettingValue)(nil), // 21: openshell.sandbox.v1.SettingValue (*EffectiveSetting)(nil), // 22: openshell.sandbox.v1.EffectiveSetting - (*GetSandboxConfigResponse)(nil), // 23: openshell.sandbox.v1.GetSandboxConfigResponse - (*SupervisorMiddlewareService)(nil), // 24: openshell.sandbox.v1.SupervisorMiddlewareService - nil, // 25: openshell.sandbox.v1.SandboxPolicy.NetworkPoliciesEntry - nil, // 26: openshell.sandbox.v1.SandboxPolicy.NetworkMiddlewaresEntry - nil, // 27: openshell.sandbox.v1.NetworkEndpoint.GraphqlPersistedQueriesEntry - nil, // 28: openshell.sandbox.v1.L7DenyRule.QueryEntry - nil, // 29: openshell.sandbox.v1.L7DenyRule.ParamsEntry - nil, // 30: openshell.sandbox.v1.L7Allow.QueryEntry - nil, // 31: openshell.sandbox.v1.L7Allow.ParamsEntry - nil, // 32: openshell.sandbox.v1.GetGatewayConfigResponse.SettingsEntry - nil, // 33: openshell.sandbox.v1.GetSandboxConfigResponse.SettingsEntry - (*structpb.Struct)(nil), // 34: google.protobuf.Struct + (*SandboxConfigSnapshot)(nil), // 23: openshell.sandbox.v1.SandboxConfigSnapshot + (*GetSandboxConfigResponse)(nil), // 24: openshell.sandbox.v1.GetSandboxConfigResponse + (*SupervisorMiddlewareService)(nil), // 25: openshell.sandbox.v1.SupervisorMiddlewareService + nil, // 26: openshell.sandbox.v1.SandboxPolicy.NetworkPoliciesEntry + nil, // 27: openshell.sandbox.v1.SandboxPolicy.NetworkMiddlewaresEntry + nil, // 28: openshell.sandbox.v1.NetworkEndpoint.GraphqlPersistedQueriesEntry + nil, // 29: openshell.sandbox.v1.L7DenyRule.QueryEntry + nil, // 30: openshell.sandbox.v1.L7DenyRule.ParamsEntry + nil, // 31: openshell.sandbox.v1.L7Allow.QueryEntry + nil, // 32: openshell.sandbox.v1.L7Allow.ParamsEntry + nil, // 33: openshell.sandbox.v1.GetGatewayConfigResponse.SettingsEntry + nil, // 34: openshell.sandbox.v1.SandboxConfigSnapshot.SettingsEntry + nil, // 35: openshell.sandbox.v1.GetSandboxConfigResponse.SettingsEntry + (*structpb.Struct)(nil), // 36: google.protobuf.Struct } var file_sandbox_proto_depIdxs = []int32{ 3, // 0: openshell.sandbox.v1.SandboxPolicy.filesystem:type_name -> openshell.sandbox.v1.FilesystemPolicy 4, // 1: openshell.sandbox.v1.SandboxPolicy.landlock:type_name -> openshell.sandbox.v1.LandlockPolicy 5, // 2: openshell.sandbox.v1.SandboxPolicy.process:type_name -> openshell.sandbox.v1.ProcessPolicy - 25, // 3: openshell.sandbox.v1.SandboxPolicy.network_policies:type_name -> openshell.sandbox.v1.SandboxPolicy.NetworkPoliciesEntry - 26, // 4: openshell.sandbox.v1.SandboxPolicy.network_middlewares:type_name -> openshell.sandbox.v1.SandboxPolicy.NetworkMiddlewaresEntry + 26, // 3: openshell.sandbox.v1.SandboxPolicy.network_policies:type_name -> openshell.sandbox.v1.SandboxPolicy.NetworkPoliciesEntry + 27, // 4: openshell.sandbox.v1.SandboxPolicy.network_middlewares:type_name -> openshell.sandbox.v1.SandboxPolicy.NetworkMiddlewaresEntry 10, // 5: openshell.sandbox.v1.NetworkPolicyRule.endpoints:type_name -> openshell.sandbox.v1.NetworkEndpoint 17, // 6: openshell.sandbox.v1.NetworkPolicyRule.binaries:type_name -> openshell.sandbox.v1.NetworkBinary - 34, // 7: openshell.sandbox.v1.NetworkMiddlewareConfig.config:type_name -> google.protobuf.Struct + 36, // 7: openshell.sandbox.v1.NetworkMiddlewareConfig.config:type_name -> google.protobuf.Struct 8, // 8: openshell.sandbox.v1.NetworkMiddlewareConfig.endpoints:type_name -> openshell.sandbox.v1.MiddlewareEndpointSelector 14, // 9: openshell.sandbox.v1.NetworkEndpoint.rules:type_name -> openshell.sandbox.v1.L7Rule 13, // 10: openshell.sandbox.v1.NetworkEndpoint.deny_rules:type_name -> openshell.sandbox.v1.L7DenyRule - 27, // 11: openshell.sandbox.v1.NetworkEndpoint.graphql_persisted_queries:type_name -> openshell.sandbox.v1.NetworkEndpoint.GraphqlPersistedQueriesEntry + 28, // 11: openshell.sandbox.v1.NetworkEndpoint.graphql_persisted_queries:type_name -> openshell.sandbox.v1.NetworkEndpoint.GraphqlPersistedQueriesEntry 11, // 12: openshell.sandbox.v1.NetworkEndpoint.mcp:type_name -> openshell.sandbox.v1.McpOptions 9, // 13: openshell.sandbox.v1.NetworkEndpoint.credential_binding:type_name -> openshell.sandbox.v1.NetworkCredentialBinding - 28, // 14: openshell.sandbox.v1.L7DenyRule.query:type_name -> openshell.sandbox.v1.L7DenyRule.QueryEntry - 29, // 15: openshell.sandbox.v1.L7DenyRule.params:type_name -> openshell.sandbox.v1.L7DenyRule.ParamsEntry + 29, // 14: openshell.sandbox.v1.L7DenyRule.query:type_name -> openshell.sandbox.v1.L7DenyRule.QueryEntry + 30, // 15: openshell.sandbox.v1.L7DenyRule.params:type_name -> openshell.sandbox.v1.L7DenyRule.ParamsEntry 15, // 16: openshell.sandbox.v1.L7Rule.allow:type_name -> openshell.sandbox.v1.L7Allow - 30, // 17: openshell.sandbox.v1.L7Allow.query:type_name -> openshell.sandbox.v1.L7Allow.QueryEntry - 31, // 18: openshell.sandbox.v1.L7Allow.params:type_name -> openshell.sandbox.v1.L7Allow.ParamsEntry - 32, // 19: openshell.sandbox.v1.GetGatewayConfigResponse.settings:type_name -> openshell.sandbox.v1.GetGatewayConfigResponse.SettingsEntry + 31, // 17: openshell.sandbox.v1.L7Allow.query:type_name -> openshell.sandbox.v1.L7Allow.QueryEntry + 32, // 18: openshell.sandbox.v1.L7Allow.params:type_name -> openshell.sandbox.v1.L7Allow.ParamsEntry + 33, // 19: openshell.sandbox.v1.GetGatewayConfigResponse.settings:type_name -> openshell.sandbox.v1.GetGatewayConfigResponse.SettingsEntry 21, // 20: openshell.sandbox.v1.EffectiveSetting.value:type_name -> openshell.sandbox.v1.SettingValue 0, // 21: openshell.sandbox.v1.EffectiveSetting.scope:type_name -> openshell.sandbox.v1.SettingScope - 2, // 22: openshell.sandbox.v1.GetSandboxConfigResponse.policy:type_name -> openshell.sandbox.v1.SandboxPolicy - 33, // 23: openshell.sandbox.v1.GetSandboxConfigResponse.settings:type_name -> openshell.sandbox.v1.GetSandboxConfigResponse.SettingsEntry - 1, // 24: openshell.sandbox.v1.GetSandboxConfigResponse.policy_source:type_name -> openshell.sandbox.v1.PolicySource - 24, // 25: openshell.sandbox.v1.GetSandboxConfigResponse.supervisor_middleware_services:type_name -> openshell.sandbox.v1.SupervisorMiddlewareService - 6, // 26: openshell.sandbox.v1.SandboxPolicy.NetworkPoliciesEntry.value:type_name -> openshell.sandbox.v1.NetworkPolicyRule - 7, // 27: openshell.sandbox.v1.SandboxPolicy.NetworkMiddlewaresEntry.value:type_name -> openshell.sandbox.v1.NetworkMiddlewareConfig - 12, // 28: openshell.sandbox.v1.NetworkEndpoint.GraphqlPersistedQueriesEntry.value:type_name -> openshell.sandbox.v1.GraphqlOperation - 16, // 29: openshell.sandbox.v1.L7DenyRule.QueryEntry.value:type_name -> openshell.sandbox.v1.L7QueryMatcher - 16, // 30: openshell.sandbox.v1.L7DenyRule.ParamsEntry.value:type_name -> openshell.sandbox.v1.L7QueryMatcher - 16, // 31: openshell.sandbox.v1.L7Allow.QueryEntry.value:type_name -> openshell.sandbox.v1.L7QueryMatcher - 16, // 32: openshell.sandbox.v1.L7Allow.ParamsEntry.value:type_name -> openshell.sandbox.v1.L7QueryMatcher - 21, // 33: openshell.sandbox.v1.GetGatewayConfigResponse.SettingsEntry.value:type_name -> openshell.sandbox.v1.SettingValue - 22, // 34: openshell.sandbox.v1.GetSandboxConfigResponse.SettingsEntry.value:type_name -> openshell.sandbox.v1.EffectiveSetting - 35, // [35:35] is the sub-list for method output_type - 35, // [35:35] is the sub-list for method input_type - 35, // [35:35] is the sub-list for extension type_name - 35, // [35:35] is the sub-list for extension extendee - 0, // [0:35] is the sub-list for field type_name + 2, // 22: openshell.sandbox.v1.SandboxConfigSnapshot.policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 34, // 23: openshell.sandbox.v1.SandboxConfigSnapshot.settings:type_name -> openshell.sandbox.v1.SandboxConfigSnapshot.SettingsEntry + 1, // 24: openshell.sandbox.v1.SandboxConfigSnapshot.policy_source:type_name -> openshell.sandbox.v1.PolicySource + 25, // 25: openshell.sandbox.v1.SandboxConfigSnapshot.supervisor_middleware_services:type_name -> openshell.sandbox.v1.SupervisorMiddlewareService + 2, // 26: openshell.sandbox.v1.GetSandboxConfigResponse.policy:type_name -> openshell.sandbox.v1.SandboxPolicy + 35, // 27: openshell.sandbox.v1.GetSandboxConfigResponse.settings:type_name -> openshell.sandbox.v1.GetSandboxConfigResponse.SettingsEntry + 1, // 28: openshell.sandbox.v1.GetSandboxConfigResponse.policy_source:type_name -> openshell.sandbox.v1.PolicySource + 25, // 29: openshell.sandbox.v1.GetSandboxConfigResponse.supervisor_middleware_services:type_name -> openshell.sandbox.v1.SupervisorMiddlewareService + 6, // 30: openshell.sandbox.v1.SandboxPolicy.NetworkPoliciesEntry.value:type_name -> openshell.sandbox.v1.NetworkPolicyRule + 7, // 31: openshell.sandbox.v1.SandboxPolicy.NetworkMiddlewaresEntry.value:type_name -> openshell.sandbox.v1.NetworkMiddlewareConfig + 12, // 32: openshell.sandbox.v1.NetworkEndpoint.GraphqlPersistedQueriesEntry.value:type_name -> openshell.sandbox.v1.GraphqlOperation + 16, // 33: openshell.sandbox.v1.L7DenyRule.QueryEntry.value:type_name -> openshell.sandbox.v1.L7QueryMatcher + 16, // 34: openshell.sandbox.v1.L7DenyRule.ParamsEntry.value:type_name -> openshell.sandbox.v1.L7QueryMatcher + 16, // 35: openshell.sandbox.v1.L7Allow.QueryEntry.value:type_name -> openshell.sandbox.v1.L7QueryMatcher + 16, // 36: openshell.sandbox.v1.L7Allow.ParamsEntry.value:type_name -> openshell.sandbox.v1.L7QueryMatcher + 21, // 37: openshell.sandbox.v1.GetGatewayConfigResponse.SettingsEntry.value:type_name -> openshell.sandbox.v1.SettingValue + 22, // 38: openshell.sandbox.v1.SandboxConfigSnapshot.SettingsEntry.value:type_name -> openshell.sandbox.v1.EffectiveSetting + 22, // 39: openshell.sandbox.v1.GetSandboxConfigResponse.SettingsEntry.value:type_name -> openshell.sandbox.v1.EffectiveSetting + 40, // [40:40] is the sub-list for method output_type + 40, // [40:40] is the sub-list for method input_type + 40, // [40:40] is the sub-list for extension type_name + 40, // [40:40] is the sub-list for extension extendee + 0, // [0:40] is the sub-list for field type_name } func init() { file_sandbox_proto_init() } @@ -2368,7 +2526,7 @@ func file_sandbox_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_sandbox_proto_rawDesc), len(file_sandbox_proto_rawDesc)), NumEnums: 2, - NumMessages: 32, + NumMessages: 34, NumExtensions: 0, NumServices: 0, }, diff --git a/sdk/typescript/src/raw.ts b/sdk/typescript/src/raw.ts index b0be2cd9bf..42b9530643 100644 --- a/sdk/typescript/src/raw.ts +++ b/sdk/typescript/src/raw.ts @@ -7,7 +7,7 @@ export * from './gen/datamodel_pb.js'; // OpenShellClient / SandboxClient (`.raw` and `.transport`). These are the // uncurated wire types; import them from '@nvidia/openshell-sdk/raw'. The // curated entry point stays free of generated types so its surface does not -// shift when the proto regenerates. The four generated modules export disjoint +// shift when the proto regenerates. The generated modules export disjoint // symbol names, so a flat re-export is unambiguous. export * from './gen/openshell_pb.js'; export * from './gen/options_pb.js'; diff --git a/skills/debug-openshell-cluster/SKILL.md b/skills/debug-openshell-cluster/SKILL.md index 7d47b18065..9e8d30875e 100644 --- a/skills/debug-openshell-cluster/SKILL.md +++ b/skills/debug-openshell-cluster/SKILL.md @@ -16,6 +16,8 @@ The target deployment flow is: 1. Operator starts or deploys the gateway with system packages, systemd, or Helm. The CLI does not start, stop, or destroy gateway services. 2. Operator configures the compute driver. 3. Operator provides the CLI and supervisor authentication material required by the deployment mode: edge or OIDC user auth, optional CLI mTLS, and gateway-minted sandbox JWTs. + +If supervisor sessions fail with a protocol revision mismatch, check that custom supervisor images match the gateway release. Gateway and supervisor require the same internal protocol revision; authentication success does not make mismatched versions compatible. See the published [gateway configuration reference](https://docs.nvidia.com/openshell/latest/reference/gateway-config). 4. The CLI registers a reachable gateway endpoint with `openshell gateway add`. 5. The gateway creates sandboxes through the selected compute driver. From adf8fd7b4227b0f2e7d550568a3b77dfd29c2c61 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Wed, 9 Sep 2026 14:27:20 -0700 Subject: [PATCH 2/5] fix(server): skip invalid stored policies during policy history repair The startup repair that creates version-one policy history for legacy sandboxes propagated validation failures, so a single stored policy that no longer passes current validation rules prevented the gateway from starting. Skip such sandboxes with a warning and a completion summary so they keep the pre-repair behavior where only their own configuration reads report the failure. Store errors remain fatal. Signed-off-by: Piotr Mlocek --- crates/openshell-server/src/grpc/policy.rs | 125 ++++++++++++++++++--- 1 file changed, 110 insertions(+), 15 deletions(-) diff --git a/crates/openshell-server/src/grpc/policy.rs b/crates/openshell-server/src/grpc/policy.rs index 1fbbfd369f..da869908cd 100644 --- a/crates/openshell-server/src/grpc/policy.rs +++ b/crates/openshell-server/src/grpc/policy.rs @@ -79,7 +79,7 @@ use sha2::{Digest, Sha256}; use std::collections::{BTreeMap, HashMap, HashSet}; use std::net::{IpAddr, Ipv4Addr}; use std::sync::Arc; -use tonic::{Request, Response, Status}; +use tonic::{Code, Request, Response, Status}; use tracing::{debug, info, warn}; use super::validation::{ @@ -2344,7 +2344,7 @@ async fn resolve_sandbox_by_name_for_principal( }; crate::auth::guard::ensure_sandbox_scope(principal, sandbox.object_id()).map_err( |status| { - if status.code() == tonic::Code::PermissionDenied { + if status.code() == Code::PermissionDenied { Status::permission_denied("sandbox not found or not owned by caller") } else { status @@ -2614,13 +2614,16 @@ impl InitialPolicyHistoryStatus { /// Insert the version-one policy baseline if this sandbox still has no policy /// history. This never modifies an existing revision or apply result. +/// +/// Returns `true` when a baseline was written. Stored policies that fail the +/// current validation rules are rejected with `FailedPrecondition`. pub async fn initialize_policy_history( store: &Store, sandbox: &Sandbox, status: InitialPolicyHistoryStatus, -) -> Result<(), Status> { +) -> Result { let Some(policy) = sandbox.spec.as_ref().and_then(|spec| spec.policy.as_ref()) else { - return Ok(()); + return Ok(false); }; if store .get_latest_policy(sandbox.object_id()) @@ -2628,7 +2631,7 @@ pub async fn initialize_policy_history( .map_err(|error| Status::internal(format!("read policy history failed: {error}")))? .is_some() { - return Ok(()); + return Ok(false); } let policy = validate_and_canonicalize_stored_policy(policy.clone(), STORED_POLICY_SOURCE_SPEC)?; @@ -2649,15 +2652,22 @@ pub async fn initialize_policy_history( sandbox.object_workspace(), ) .await - .map_err(|error| Status::internal(format!("initialize policy history failed: {error}"))) + .map_err(|error| Status::internal(format!("initialize policy history failed: {error}")))?; + Ok(true) } /// Create policy-history baselines for sandboxes written by older gateways. /// -/// Snapshot reads stay pure once this startup repair has completed. +/// Snapshot reads stay pure once this startup repair has completed. A stored +/// policy that no longer passes validation is skipped rather than blocking +/// gateway startup; that sandbox keeps the pre-repair behavior where its own +/// configuration reads report the validation failure. Store errors remain +/// fatal. pub async fn backfill_legacy_policy_history(state: &Arc) -> Result<(), Status> { const PAGE_SIZE: u32 = 1000; let mut offset = 0; + let mut repaired = 0_usize; + let mut skipped = 0_usize; loop { let sandboxes = state .store @@ -2666,23 +2676,38 @@ pub async fn backfill_legacy_policy_history(state: &Arc) -> Result< .map_err(|error| { Status::internal(format!("list sandboxes for policy repair failed: {error}")) })?; - if sandboxes.is_empty() { - return Ok(()); - } let count = u32::try_from(sandboxes.len()).unwrap_or(PAGE_SIZE); for sandbox in sandboxes { - initialize_policy_history( + match initialize_policy_history( state.store.as_ref(), &sandbox, InitialPolicyHistoryStatus::Loaded, ) - .await?; + .await + { + Ok(true) => repaired += 1, + Ok(false) => {} + Err(status) if status.code() == Code::FailedPrecondition => { + skipped += 1; + warn!( + sandbox_id = %sandbox.object_id(), + workspace = %sandbox.object_workspace(), + error = %status.message(), + "skipping policy history repair for invalid stored policy" + ); + } + Err(status) => return Err(status), + } } if count < PAGE_SIZE { - return Ok(()); + break; } offset = offset.saturating_add(count); } + if repaired > 0 || skipped > 0 { + info!(repaired, skipped, "legacy policy history repair complete"); + } + Ok(()) } #[cfg(test)] @@ -5320,7 +5345,7 @@ async fn handle_approve_all_draft_chunks_inner( .await { Ok(evaluation) => evaluation, - Err(status) if status.code() == tonic::Code::FailedPrecondition => { + Err(status) if status.code() == Code::FailedPrecondition => { info!( sandbox_id = %sandbox_id, chunk_id = %chunk.id, @@ -7299,7 +7324,6 @@ mod tests { use std::collections::HashMap; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; - use tonic::Code; /// Wrap a request with a user `Principal` so handler scope guards treat /// the test caller as a CLI user. Most handler tests exercise @@ -11045,6 +11069,77 @@ mod tests { ); } + #[tokio::test] + async fn legacy_policy_history_repair_skips_invalid_stored_policy() { + use openshell_core::proto::LandlockPolicy; + + let state = test_server_state().await; + let valid_policy = test_policy_with_rule("valid", "valid.example.com"); + state + .store + .put_message(&test_sandbox( + "sb-valid-legacy", + "valid-legacy", + valid_policy.clone(), + Vec::new(), + )) + .await + .unwrap(); + let mut invalid_policy = test_policy_with_rule("invalid", "invalid.example.com"); + invalid_policy.landlock = Some(LandlockPolicy { + compatibility: "best-effort".to_string(), + }); + state + .store + .put_message(&test_sandbox( + "sb-invalid-legacy", + "invalid-legacy", + invalid_policy, + Vec::new(), + )) + .await + .unwrap(); + + backfill_legacy_policy_history(&state) + .await + .expect("one invalid stored policy must not block startup repair"); + + let repaired = state + .store + .get_latest_policy("sb-valid-legacy") + .await + .unwrap() + .expect("valid legacy sandbox gets a baseline"); + assert_eq!(repaired.version, 1); + assert_eq!(repaired.status, "loaded"); + assert_eq!( + repaired.policy_hash, + deterministic_policy_hash(&valid_policy) + ); + assert!( + state + .store + .get_latest_policy("sb-invalid-legacy") + .await + .unwrap() + .is_none(), + "invalid stored policy must not be persisted as history" + ); + + let error = handle_get_sandbox_config( + &state, + with_sandbox( + Request::new(GetSandboxConfigRequest { + sandbox_id: "sb-invalid-legacy".to_string(), + }), + "sb-invalid-legacy", + ), + ) + .await + .expect_err("invalid stored policy still fails only its own config read"); + assert_eq!(error.code(), Code::FailedPrecondition); + } + #[tokio::test] async fn legacy_policy_history_repair_is_idempotent() { let state = test_server_state().await; From 8a89bc23936e17041cfac8ed6f73f8983723e4a4 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Wed, 9 Sep 2026 16:28:53 -0700 Subject: [PATCH 3/5] fix(server): bound concurrent supervisor snapshot builds Fleet-wide configuration changes spawned one snapshot build per connected sandbox and component with no concurrency limit, so a global setting or provider change issued every store query and credential-driver call at once. Gate builds behind a semaphore sized from the database pool and start the build deadline only once a permit is held. Signed-off-by: Piotr Mlocek --- architecture/sandbox.md | 15 +- crates/openshell-server/Cargo.toml | 1 + .../openshell-server/src/config_delivery.rs | 166 ++++++++++++++++-- crates/openshell-server/src/lib.rs | 4 +- .../openshell-server/src/persistence/mod.rs | 8 + .../src/persistence/postgres.rs | 4 + .../src/persistence/sqlite.rs | 4 + 7 files changed, 184 insertions(+), 18 deletions(-) diff --git a/architecture/sandbox.md b/architecture/sandbox.md index 5447c1c93c..1c151b9c75 100644 --- a/architecture/sandbox.md +++ b/architecture/sandbox.md @@ -502,12 +502,15 @@ Polling remains the only path that changes runtime state and repairs dropped or unavailable delivery. The gateway serializes construction per sandbox and component, and coalesces repeated mutations into the latest full snapshot. An enqueue result means only that the local stream queue accepted the message. A -bounded scope fanout scheduler coalesces repeated workspace and global changes. -Snapshot construction has a deadline, and the gateway rejects encoded stream -messages that approach the transport decoder limit. A -later migration will apply these payloads directly and acknowledge their exact -revisions before removing supervisor polling. At that point, the gateway will -require a valid bootstrap before marking a session ready. +bounded scope fanout scheduler coalesces repeated workspace and global changes, +and a semaphore sized from the database pool bounds how many snapshots build +at once so a fleet-wide change cannot saturate the store or credential +backends. Snapshot construction has a deadline that starts once a build holds a +permit, and the gateway rejects encoded stream messages that approach the +transport decoder limit. A later migration will apply these payloads directly +and acknowledge their exact revisions before removing supervisor polling. At +that point, the gateway will require a valid bootstrap before marking a session +ready. ## Policy Revision Acknowledgement diff --git a/crates/openshell-server/Cargo.toml b/crates/openshell-server/Cargo.toml index 6304a2ecae..f77537c952 100644 --- a/crates/openshell-server/Cargo.toml +++ b/crates/openshell-server/Cargo.toml @@ -122,6 +122,7 @@ test-support = [] [dev-dependencies] base64 = { workspace = true } +tokio = { workspace = true, features = ["test-util"] } hyper-rustls = { version = "0.27", default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "aws-lc-rs"] } rcgen = { workspace = true } rsa = { version = "0.9", features = ["pem"] } diff --git a/crates/openshell-server/src/config_delivery.rs b/crates/openshell-server/src/config_delivery.rs index 99470ef7bc..e70bd4d8b8 100644 --- a/crates/openshell-server/src/config_delivery.rs +++ b/crates/openshell-server/src/config_delivery.rs @@ -13,6 +13,7 @@ use metrics::counter; use openshell_core::proto::{ ConfigBootstrap, ProviderEnvironmentSnapshot, Sandbox, SandboxConfigSnapshot, }; +use tokio::sync::Semaphore; use tonic::{Code, Status}; use tracing::warn; @@ -26,6 +27,11 @@ use crate::supervisor_session::SupervisorSessionRegistry; pub const MAX_SUPERVISOR_CONFIG_MESSAGE_BYTES: usize = 3 * 1024 * 1024; const CONFIG_SNAPSHOT_BUILD_TIMEOUT: Duration = Duration::from_secs(45); const MAX_ACTIVE_FANOUT_WORKERS: usize = 64; +/// Concurrent snapshot builds allowed per pooled database connection. Builds +/// are short bursts of small queries, so a little oversubscription keeps the +/// pool busy without stacking every waiter on the acquire timeout. +const SNAPSHOT_BUILDS_PER_DB_CONNECTION: usize = 2; +const MIN_CONCURRENT_SNAPSHOT_BUILDS: usize = 4; /// One complete configuration component awaiting delivery to a supervisor. #[derive(Clone)] @@ -181,13 +187,65 @@ struct FanoutKey { /// The map entry is also the worker lease. Its boolean is set when another /// mutation arrives during a build or route operation. The worker then rebuilds /// the current full snapshot once, regardless of how many mutations arrived. -#[derive(Debug, Default)] +/// +/// Workers are spawned eagerly so coalescing stays exact, but snapshot +/// construction itself is bounded by `build_permits`. A fleet-wide change +/// therefore queues on the semaphore instead of saturating the database pool +/// and credential backends all at once. +#[derive(Debug)] pub struct ConfigDeliveryQueue { pending: Mutex>, fanout_pending: Mutex>, + build_permits: Semaphore, +} + +impl Default for ConfigDeliveryQueue { + fn default() -> Self { + Self::new(MIN_CONCURRENT_SNAPSHOT_BUILDS) + } } impl ConfigDeliveryQueue { + #[must_use] + pub fn new(max_concurrent_builds: usize) -> Self { + Self { + pending: Mutex::default(), + fanout_pending: Mutex::default(), + build_permits: Semaphore::new(max_concurrent_builds.max(1)), + } + } + + /// Size the build bound from the persistence pool that every build reads. + #[must_use] + pub fn for_db_connections(max_connections: u32) -> Self { + let max_connections = usize::try_from(max_connections).unwrap_or(usize::MAX); + Self::new( + max_connections + .saturating_mul(SNAPSHOT_BUILDS_PER_DB_CONNECTION) + .max(MIN_CONCURRENT_SNAPSHOT_BUILDS), + ) + } + + #[cfg(test)] + fn max_concurrent_builds(&self) -> usize { + self.build_permits.available_permits() + } + + /// Run one snapshot build under the concurrency bound. The deadline starts + /// only once a permit is held so queued builds do not spend their budget + /// waiting. + async fn run_bounded_build( + &self, + build: impl Future, + ) -> Result { + let _permit = self + .build_permits + .acquire() + .await + .expect("snapshot build semaphore is never closed"); + tokio::time::timeout(CONFIG_SNAPSHOT_BUILD_TIMEOUT, build).await + } + fn enqueue(&self, key: DeliveryKey) -> bool { let mut pending = self.pending.lock().unwrap(); match pending.entry(key) { @@ -337,16 +395,16 @@ fn enqueue_sandbox(state: &Arc, sandbox_id: &str, components: Confi } async fn publish_sandbox_component_now(state: &Arc, key: &DeliveryKey) { - let sandbox = match state.store.get_message::(&key.sandbox_id).await { - Ok(Some(sandbox)) => sandbox, - Ok(None) => return, - Err(_) => { - record_build_failure(&key.sandbox_id, "sandbox", Code::Internal); - return; - } - }; let component = key.component.name(); let build = async { + let sandbox = state + .store + .get_message::(&key.sandbox_id) + .await + .map_err(|error| Status::internal(format!("fetch sandbox failed: {error}")))?; + let Some(sandbox) = sandbox else { + return Ok(None); + }; match key.component { ConfigComponentKind::SandboxConfig => build_sandbox_config_snapshot(state, &sandbox) .await @@ -357,9 +415,11 @@ async fn publish_sandbox_component_now(state: &Arc, key: &DeliveryK .map(SupervisorConfigMessage::ProviderEnvironment) } } + .map(Some) }; - match tokio::time::timeout(CONFIG_SNAPSHOT_BUILD_TIMEOUT, build).await { - Ok(Ok(message)) => { + match state.config_delivery_queue.run_bounded_build(build).await { + Ok(Ok(None)) => {} + Ok(Ok(Some(message))) => { let disposition = state .supervisor_config_router() .deliver(&key.sandbox_id, message) @@ -478,6 +538,8 @@ fn record_build_failure(sandbox_id: &str, component: &'static str, error_code: C #[cfg(test)] mod tests { + use std::sync::atomic::{AtomicUsize, Ordering}; + use super::*; use crate::grpc::{OpenShellService, test_support::test_server_state}; use openshell_core::proto::{ @@ -508,6 +570,88 @@ mod tests { assert!(!queue.finish_pass(&key)); } + #[test] + fn build_bound_is_sized_from_the_database_pool() { + assert_eq!( + ConfigDeliveryQueue::for_db_connections(10).max_concurrent_builds(), + 20 + ); + assert_eq!( + ConfigDeliveryQueue::for_db_connections(1).max_concurrent_builds(), + MIN_CONCURRENT_SNAPSHOT_BUILDS + ); + assert_eq!(ConfigDeliveryQueue::new(0).max_concurrent_builds(), 1); + } + + #[tokio::test(start_paused = true)] + async fn bounded_builds_never_exceed_the_permit_count() { + const PERMITS: usize = 4; + const BUILDS: usize = 40; + let queue = Arc::new(ConfigDeliveryQueue::new(PERMITS)); + let active = Arc::new(AtomicUsize::new(0)); + let peak = Arc::new(AtomicUsize::new(0)); + + let workers = (0..BUILDS) + .map(|_| { + let queue = Arc::clone(&queue); + let active = Arc::clone(&active); + let peak = Arc::clone(&peak); + tokio::spawn(async move { + queue + .run_bounded_build(async { + let now = active.fetch_add(1, Ordering::SeqCst) + 1; + peak.fetch_max(now, Ordering::SeqCst); + tokio::time::sleep(Duration::from_millis(50)).await; + active.fetch_sub(1, Ordering::SeqCst); + }) + .await + .expect("build must not time out"); + }) + }) + .collect::>(); + for worker in workers { + worker.await.unwrap(); + } + + assert_eq!(peak.load(Ordering::SeqCst), PERMITS); + assert_eq!(active.load(Ordering::SeqCst), 0); + assert_eq!(queue.max_concurrent_builds(), PERMITS); + } + + #[tokio::test(start_paused = true)] + async fn build_deadline_starts_after_a_permit_is_held() { + let queue = Arc::new(ConfigDeliveryQueue::new(1)); + let almost_deadline = CONFIG_SNAPSHOT_BUILD_TIMEOUT + .checked_sub(Duration::from_secs(1)) + .unwrap(); + let first = { + let queue = Arc::clone(&queue); + tokio::spawn(async move { + queue + .run_bounded_build(tokio::time::sleep(almost_deadline)) + .await + }) + }; + tokio::task::yield_now().await; + let second = queue.run_bounded_build(tokio::time::sleep(almost_deadline)); + + let (first, second) = tokio::join!(first, second); + assert!(first.unwrap().is_ok()); + assert!( + second.is_ok(), + "waiting for a permit must not consume the build deadline" + ); + + assert!( + queue + .run_bounded_build(tokio::time::sleep( + CONFIG_SNAPSHOT_BUILD_TIMEOUT + Duration::from_secs(1), + )) + .await + .is_err() + ); + } + #[test] fn queue_runs_components_and_sandboxes_independently() { let queue = ConfigDeliveryQueue::default(); diff --git a/crates/openshell-server/src/lib.rs b/crates/openshell-server/src/lib.rs index c22457e732..edd9921c6b 100644 --- a/crates/openshell-server/src/lib.rs +++ b/crates/openshell-server/src/lib.rs @@ -417,6 +417,8 @@ impl ServerState { let supervisor_config_router: Arc = Arc::new( config_delivery::LocalSupervisorConfigRouter::new(Arc::clone(&supervisor_sessions)), ); + let config_delivery_queue = + config_delivery::ConfigDeliveryQueue::for_db_connections(store.max_connections()); Self { config, store, @@ -431,7 +433,7 @@ impl ServerState { settings_mutex: tokio::sync::Mutex::new(()), supervisor_sessions, gateway_shutting_down: AtomicBool::new(false), - config_delivery_queue: config_delivery::ConfigDeliveryQueue::default(), + config_delivery_queue, supervisor_config_router, extension_mint_limiter: auth::extension_mint_limit::ExtensionMintLimiter::default(), middleware_registry: Arc::new(MiddlewareRegistry::default()), diff --git a/crates/openshell-server/src/persistence/mod.rs b/crates/openshell-server/src/persistence/mod.rs index 716f26dad9..0b754226e2 100644 --- a/crates/openshell-server/src/persistence/mod.rs +++ b/crates/openshell-server/src/persistence/mod.rs @@ -231,6 +231,14 @@ impl Store { matches!(self, Self::Sqlite(_)) } + /// Maximum number of pooled database connections for this backend. + pub fn max_connections(&self) -> u32 { + match self { + Self::Postgres(store) => store.max_connections(), + Self::Sqlite(store) => store.max_connections(), + } + } + /// Connect to a persistence store based on the database URL. pub async fn connect(url: &str) -> CoreResult { if url.starts_with("postgres://") || url.starts_with("postgresql://") { diff --git a/crates/openshell-server/src/persistence/postgres.rs b/crates/openshell-server/src/persistence/postgres.rs index 209a5a8eff..42ea3d46fd 100644 --- a/crates/openshell-server/src/persistence/postgres.rs +++ b/crates/openshell-server/src/persistence/postgres.rs @@ -44,6 +44,10 @@ impl PostgresStore { Ok(Self { pool }) } + pub fn max_connections(&self) -> u32 { + self.pool.options().get_max_connections() + } + pub async fn migrate(&self) -> PersistenceResult<()> { POSTGRES_MIGRATOR .run(&self.pool) diff --git a/crates/openshell-server/src/persistence/sqlite.rs b/crates/openshell-server/src/persistence/sqlite.rs index 806e4a18fb..b06fb03162 100644 --- a/crates/openshell-server/src/persistence/sqlite.rs +++ b/crates/openshell-server/src/persistence/sqlite.rs @@ -55,6 +55,10 @@ impl SqliteStore { self.close().await; } + pub fn max_connections(&self) -> u32 { + self.pool.options().get_max_connections() + } + pub async fn connect(url: &str) -> PersistenceResult { let is_in_memory = url.contains(":memory:") || url.contains("mode=memory"); let max_connections = if is_in_memory { 1 } else { 5 }; From 0334c31f671f33b490d971b6e710a6881fef1c46 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Wed, 9 Sep 2026 14:11:00 -0700 Subject: [PATCH 4/5] fix(supervisor): accept legacy supervisors without a protocol revision Sandboxes keep their supervisor binary until they are recreated, so a gateway upgrade meets supervisors that predate the handshake and report revision zero. Rejecting them severs every running sandbox with no automatic recovery. Accept revision zero for one release, log a warning per session, and count them in openshell_supervisor_protocol_legacy_sessions_total. The supervisor mirrors the allowance for gateways that predate the handshake. Add a shared ConnectSupervisor test harness and handler-level tests for legacy acceptance and unknown-revision rejection. Move the skill troubleshooting paragraph out of the numbered deployment list so the list renders. Signed-off-by: Piotr Mlocek --- architecture/sandbox.md | 4 +- crates/openshell-core/src/proto/mod.rs | 8 ++ .../openshell-server/src/config_delivery.rs | 47 ++------- crates/openshell-server/src/grpc/mod.rs | 66 +++++++++++++ .../src/supervisor_session.rs | 99 ++++++++++++++++--- .../src/supervisor_session.rs | 26 +++-- docs/reference/gateway-config.mdx | 2 + proto/openshell.proto | 1 + skills/debug-openshell-cluster/SKILL.md | 4 +- 9 files changed, 196 insertions(+), 61 deletions(-) diff --git a/architecture/sandbox.md b/architecture/sandbox.md index 1c151b9c75..b103ebcbd0 100644 --- a/architecture/sandbox.md +++ b/architecture/sandbox.md @@ -474,7 +474,9 @@ quickly. ## Supervisor Configuration Delivery The gateway and supervisor must implement the same internal supervisor protocol -revision. The gateway includes a configuration bootstrap when it accepts a +revision. Peers built before the handshake existed report revision zero and are +accepted for one release with a warning and a counter, because sandboxes keep +their supervisor binary until they are recreated. The gateway includes a configuration bootstrap when it accepts a `ConnectSupervisor` session and can send complete component replacements on the same stream after policy, settings, or provider state changes. Bootstrap construction does not gate the session while polling remains diff --git a/crates/openshell-core/src/proto/mod.rs b/crates/openshell-core/src/proto/mod.rs index c458294f9b..43b4bab36d 100644 --- a/crates/openshell-core/src/proto/mod.rs +++ b/crates/openshell-core/src/proto/mod.rs @@ -80,3 +80,11 @@ pub use test::ObjectForTest; /// Bump this when either peer can no longer honor the previous stream /// semantics. pub const SUPERVISOR_PROTOCOL_REVISION: u32 = 1; + +/// Revision implied by peers built before the handshake existed. Proto3 leaves +/// the field unset, so such peers report zero. +/// +/// Sandboxes keep their supervisor binary until they are recreated, so a +/// gateway upgrade must keep serving them for one release. Remove this +/// allowance once every supported release sends an explicit revision. +pub const LEGACY_SUPERVISOR_PROTOCOL_REVISION: u32 = 0; diff --git a/crates/openshell-server/src/config_delivery.rs b/crates/openshell-server/src/config_delivery.rs index e70bd4d8b8..b9c7495277 100644 --- a/crates/openshell-server/src/config_delivery.rs +++ b/crates/openshell-server/src/config_delivery.rs @@ -541,14 +541,8 @@ mod tests { use std::sync::atomic::{AtomicUsize, Ordering}; use super::*; - use crate::grpc::{OpenShellService, test_support::test_server_state}; - use openshell_core::proto::{ - GatewayMessage, ObjectMeta, SandboxSpec, SupervisorHello, SupervisorMessage, - gateway_message, open_shell_client::OpenShellClient, open_shell_server::OpenShellServer, - supervisor_message, - }; - use tokio::sync::mpsc; - use tokio_stream::wrappers::{ReceiverStream, TcpListenerStream}; + use crate::grpc::test_support::{connect_supervisor_stream, test_server_state}; + use openshell_core::proto::{GatewayMessage, ObjectMeta, SandboxSpec, gateway_message}; fn key(sandbox_id: &str, component: ConfigComponentKind) -> DeliveryKey { DeliveryKey { @@ -727,35 +721,15 @@ mod tests { .await .unwrap(); - let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); - let address = listener.local_addr().unwrap(); - let server = tokio::spawn( - tonic::transport::Server::builder() - .add_service(OpenShellServer::new(OpenShellService::new(Arc::clone( - &state, - )))) - .serve_with_incoming(TcpListenerStream::new(listener)), - ); - let mut client = OpenShellClient::connect(format!("http://{address}")) - .await - .unwrap(); - let (tx, rx) = mpsc::channel(4); - tx.send(SupervisorMessage { - payload: Some(supervisor_message::Payload::Hello(SupervisorHello { - sandbox_id: "sandbox".into(), - instance_id: "instance".into(), - protocol_revision: openshell_core::proto::SUPERVISOR_PROTOCOL_REVISION, - })), - }) + let mut harness = connect_supervisor_stream( + &state, + "sandbox", + openshell_core::proto::SUPERVISOR_PROTOCOL_REVISION, + ) .await .unwrap(); - let mut stream = client - .connect_supervisor(ReceiverStream::new(rx)) - .await - .unwrap() - .into_inner(); - let first = tokio::time::timeout(Duration::from_secs(5), stream.message()) + let first = tokio::time::timeout(Duration::from_secs(5), harness.inbound.message()) .await .unwrap() .unwrap() @@ -766,7 +740,7 @@ mod tests { )); publish_sandbox_components(&state, "sandbox", ConfigComponents::SANDBOX_CONFIG); - let update = tokio::time::timeout(Duration::from_secs(5), stream.message()) + let update = tokio::time::timeout(Duration::from_secs(5), harness.inbound.message()) .await .unwrap() .unwrap() @@ -777,9 +751,6 @@ mod tests { payload: Some(gateway_message::Payload::ConfigUpdate(_)) } )); - - drop(tx); - server.abort(); } #[test] diff --git a/crates/openshell-server/src/grpc/mod.rs b/crates/openshell-server/src/grpc/mod.rs index c5a12a15b5..db48762102 100644 --- a/crates/openshell-server/src/grpc/mod.rs +++ b/crates/openshell-server/src/grpc/mod.rs @@ -836,8 +836,74 @@ pub mod test_support { use crate::supervisor_session::SupervisorSessionRegistry; use crate::tracing_bus::TracingLogBus; use openshell_core::Config; + use openshell_core::proto::open_shell_client::OpenShellClient; + use openshell_core::proto::open_shell_server::OpenShellServer; + use openshell_core::proto::{ + GatewayMessage, SupervisorHello, SupervisorMessage, supervisor_message, + }; + use tokio::sync::mpsc; + use tokio_stream::wrappers::{ReceiverStream, TcpListenerStream}; use tonic::Request; + /// A live `ConnectSupervisor` stream against an in-process gateway. + pub struct SupervisorStreamHarness { + server: tokio::task::JoinHandle>, + /// Held so the supervisor side of the stream stays open. + _outbound: mpsc::Sender, + pub inbound: tonic::Streaming, + } + + impl Drop for SupervisorStreamHarness { + fn drop(&mut self) { + self.server.abort(); + } + } + + /// Serve `state` on loopback and open a supervisor stream whose hello + /// carries the given protocol revision. Returns the gRPC status when the + /// gateway rejects the stream before accepting it. + pub async fn connect_supervisor_stream( + state: &Arc, + sandbox_id: &str, + protocol_revision: u32, + ) -> Result { + let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); + let address = listener.local_addr().unwrap(); + let server = tokio::spawn( + tonic::transport::Server::builder() + .add_service(OpenShellServer::new(super::OpenShellService::new( + Arc::clone(state), + ))) + .serve_with_incoming(TcpListenerStream::new(listener)), + ); + let mut client = OpenShellClient::connect(format!("http://{address}")) + .await + .unwrap(); + let (outbound, rx) = mpsc::channel(4); + outbound + .send(SupervisorMessage { + payload: Some(supervisor_message::Payload::Hello(SupervisorHello { + sandbox_id: sandbox_id.into(), + instance_id: "instance".into(), + protocol_revision, + })), + }) + .await + .unwrap(); + let inbound = match client.connect_supervisor(ReceiverStream::new(rx)).await { + Ok(response) => response.into_inner(), + Err(status) => { + server.abort(); + return Err(status); + } + }; + Ok(SupervisorStreamHarness { + server, + _outbound: outbound, + inbound, + }) + } + /// Wrap a proto message in a `Request` with a dev principal injected. /// /// The dev principal matches the unauthenticated dev user: subject diff --git a/crates/openshell-server/src/supervisor_session.rs b/crates/openshell-server/src/supervisor_session.rs index c5668cc41e..5cb66ac16f 100644 --- a/crates/openshell-server/src/supervisor_session.rs +++ b/crates/openshell-server/src/supervisor_session.rs @@ -15,12 +15,12 @@ use tonic::{Request, Response, Status}; use tracing::{debug, info, warn}; use uuid::Uuid; -use openshell_core::proto::SUPERVISOR_PROTOCOL_REVISION; use openshell_core::proto::{ ConfigUpdate, GatewayMessage, RelayFrame, RelayInit, RelayOpen, ReportMainProcessExitRequest, ReportMainProcessExitResponse, Sandbox, SandboxPhase, SessionAccepted, SshRelayTarget, SupervisorMessage, config_update, gateway_message, relay_open, supervisor_message, }; +use openshell_core::proto::{LEGACY_SUPERVISOR_PROTOCOL_REVISION, SUPERVISOR_PROTOCOL_REVISION}; use openshell_core::transport_errors::is_expected_transport_close_status; use crate::ServerState; @@ -810,7 +810,7 @@ pub async fn handle_connect_supervisor( if sandbox_id.is_empty() { return Err(Status::invalid_argument("sandbox_id is required")); } - validate_protocol_revision(hello.protocol_revision)?; + validate_protocol_revision(&sandbox_id, hello.protocol_revision)?; if let Some(principal) = principal.as_ref() { crate::auth::guard::ensure_sandbox_principal_scope(principal, &sandbox_id)?; } @@ -960,13 +960,20 @@ pub async fn handle_connect_supervisor( Ok(Response::new(stream)) } -fn validate_protocol_revision(supervisor_revision: u32) -> Result<(), Status> { - if supervisor_revision == SUPERVISOR_PROTOCOL_REVISION { - Ok(()) - } else { - Err(Status::failed_precondition(format!( - "supervisor protocol revision mismatch: gateway requires {SUPERVISOR_PROTOCOL_REVISION}, supervisor offered {supervisor_revision}" - ))) +fn validate_protocol_revision(sandbox_id: &str, supervisor_revision: u32) -> Result<(), Status> { + match supervisor_revision { + SUPERVISOR_PROTOCOL_REVISION => Ok(()), + LEGACY_SUPERVISOR_PROTOCOL_REVISION => { + counter!("openshell_supervisor_protocol_legacy_sessions_total").increment(1); + warn!( + sandbox_id = %sandbox_id, + "supervisor session: supervisor predates the protocol handshake; recreate the sandbox before the next gateway upgrade" + ); + Ok(()) + } + other => Err(Status::failed_precondition(format!( + "supervisor protocol revision mismatch: gateway requires {SUPERVISOR_PROTOCOL_REVISION}, supervisor offered {other}" + ))), } } @@ -1246,9 +1253,77 @@ mod tests { } #[test] - fn supervisor_protocol_revision_must_match_exactly() { - assert!(validate_protocol_revision(SUPERVISOR_PROTOCOL_REVISION).is_ok()); - let error = validate_protocol_revision(SUPERVISOR_PROTOCOL_REVISION + 1).unwrap_err(); + fn supervisor_protocol_revision_accepts_current_and_legacy_peers() { + assert!(validate_protocol_revision("sb-1", SUPERVISOR_PROTOCOL_REVISION).is_ok()); + assert!(validate_protocol_revision("sb-1", LEGACY_SUPERVISOR_PROTOCOL_REVISION).is_ok()); + } + + async fn state_with_sandbox(sandbox_id: &str) -> Arc { + let state = crate::grpc::test_support::test_server_state().await; + state + .store + .put_message(&sandbox_record(sandbox_id, sandbox_id)) + .await + .unwrap(); + state + } + + async fn first_gateway_message( + harness: &mut crate::grpc::test_support::SupervisorStreamHarness, + ) -> GatewayMessage { + tokio::time::timeout(Duration::from_secs(5), harness.inbound.message()) + .await + .expect("gateway response before timeout") + .expect("stream open") + .expect("gateway message") + } + + #[tokio::test] + async fn legacy_supervisor_without_protocol_revision_is_accepted() { + let state = state_with_sandbox("sb-legacy").await; + let mut harness = crate::grpc::test_support::connect_supervisor_stream( + &state, + "sb-legacy", + LEGACY_SUPERVISOR_PROTOCOL_REVISION, + ) + .await + .expect("legacy supervisor must connect"); + + let Some(gateway_message::Payload::SessionAccepted(accepted)) = + first_gateway_message(&mut harness).await.payload + else { + panic!("expected SessionAccepted"); + }; + assert_eq!(accepted.protocol_revision, SUPERVISOR_PROTOCOL_REVISION); + assert!( + state + .supervisor_sessions + .is_current_session("sb-legacy", &accepted.session_id) + ); + } + + #[tokio::test] + async fn unknown_supervisor_protocol_revision_is_rejected() { + let state = state_with_sandbox("sb-future").await; + let Err(status) = crate::grpc::test_support::connect_supervisor_stream( + &state, + "sb-future", + SUPERVISOR_PROTOCOL_REVISION + 1, + ) + .await + else { + panic!("mismatched revision must be rejected"); + }; + + assert_eq!(status.code(), tonic::Code::FailedPrecondition); + assert!(status.message().contains("revision mismatch")); + assert!(state.supervisor_sessions.connected_sandbox_ids().is_empty()); + } + + #[test] + fn supervisor_protocol_revision_rejects_unknown_peers() { + let error = + validate_protocol_revision("sb-1", SUPERVISOR_PROTOCOL_REVISION + 1).unwrap_err(); assert_eq!(error.code(), tonic::Code::FailedPrecondition); assert!(error.message().contains("revision mismatch")); } diff --git a/crates/openshell-supervisor-process/src/supervisor_session.rs b/crates/openshell-supervisor-process/src/supervisor_session.rs index 2ee7fcfe95..aa070a06f2 100644 --- a/crates/openshell-supervisor-process/src/supervisor_session.rs +++ b/crates/openshell-supervisor-process/src/supervisor_session.rs @@ -17,13 +17,13 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; -use openshell_core::proto::SUPERVISOR_PROTOCOL_REVISION; use openshell_core::proto::open_shell_client::OpenShellClient; use openshell_core::proto::{ FinalizeMainProcessExitRequest, GatewayMessage, RelayFrame, RelayInit, RelayOpen, RelayOpenResult, ReportMainProcessExitRequest, SupervisorHeartbeat, SupervisorHello, SupervisorMessage, TcpRelayTarget, gateway_message, relay_open, supervisor_message, }; +use openshell_core::proto::{LEGACY_SUPERVISOR_PROTOCOL_REVISION, SUPERVISOR_PROTOCOL_REVISION}; use openshell_ocsf::{ ActivityId, ConnectionInfo, Endpoint, NetworkActivityBuilder, OcsfEvent, SandboxContext, SeverityId, StatusId, ocsf_emit, @@ -451,13 +451,18 @@ async fn run_single_session( fn validate_gateway_protocol_revision( gateway_revision: u32, ) -> Result<(), Box> { - if gateway_revision == SUPERVISOR_PROTOCOL_REVISION { - Ok(()) - } else { - Err(format!( - "supervisor protocol revision mismatch: supervisor requires {SUPERVISOR_PROTOCOL_REVISION}, gateway offered {gateway_revision}" + match gateway_revision { + SUPERVISOR_PROTOCOL_REVISION => Ok(()), + LEGACY_SUPERVISOR_PROTOCOL_REVISION => { + warn!( + "supervisor session: gateway predates the protocol handshake; upgrade the gateway before pinning newer supervisor images" + ); + Ok(()) + } + other => Err(format!( + "supervisor protocol revision mismatch: supervisor requires {SUPERVISOR_PROTOCOL_REVISION}, gateway offered {other}" ) - .into()) + .into()), } } @@ -867,8 +872,13 @@ mod target_tests { use super::*; #[test] - fn gateway_protocol_revision_must_match_exactly() { + fn gateway_protocol_revision_accepts_current_and_legacy_peers() { assert!(validate_gateway_protocol_revision(SUPERVISOR_PROTOCOL_REVISION).is_ok()); + assert!(validate_gateway_protocol_revision(LEGACY_SUPERVISOR_PROTOCOL_REVISION).is_ok()); + } + + #[test] + fn gateway_protocol_revision_rejects_unknown_peers() { let error = validate_gateway_protocol_revision(SUPERVISOR_PROTOCOL_REVISION + 1) .expect_err("version skew must be rejected"); assert!(error.to_string().contains("revision mismatch")); diff --git a/docs/reference/gateway-config.mdx b/docs/reference/gateway-config.mdx index 8aeb2281eb..6a0be10c8c 100644 --- a/docs/reference/gateway-config.mdx +++ b/docs/reference/gateway-config.mdx @@ -108,6 +108,8 @@ disable_tls = false default_image = "ghcr.io/nvidia/openshell-community/sandboxes/base:latest" # Defaults to the gateway version. Custom builds must match the gateway's # internal supervisor protocol revision; mismatched peers reject the session. +# Supervisors from releases before the handshake existed still connect, with +# a gateway warning, until the next release. # supervisor_image = "ghcr.io/nvidia/openshell/supervisor:" client_tls_secret_name = "openshell-client-tls" service_account_name = "openshell-sandbox" diff --git a/proto/openshell.proto b/proto/openshell.proto index 000e6023b0..6a0749a76f 100644 --- a/proto/openshell.proto +++ b/proto/openshell.proto @@ -2488,6 +2488,7 @@ message SupervisorHello { // Supervisor instance ID (e.g. boot id or process epoch). string instance_id = 2; // Exact internal stream protocol revision implemented by this supervisor. + // Zero identifies a supervisor built before the handshake existed. uint32 protocol_revision = 3; } diff --git a/skills/debug-openshell-cluster/SKILL.md b/skills/debug-openshell-cluster/SKILL.md index 9e8d30875e..c087d1948a 100644 --- a/skills/debug-openshell-cluster/SKILL.md +++ b/skills/debug-openshell-cluster/SKILL.md @@ -16,11 +16,11 @@ The target deployment flow is: 1. Operator starts or deploys the gateway with system packages, systemd, or Helm. The CLI does not start, stop, or destroy gateway services. 2. Operator configures the compute driver. 3. Operator provides the CLI and supervisor authentication material required by the deployment mode: edge or OIDC user auth, optional CLI mTLS, and gateway-minted sandbox JWTs. - -If supervisor sessions fail with a protocol revision mismatch, check that custom supervisor images match the gateway release. Gateway and supervisor require the same internal protocol revision; authentication success does not make mismatched versions compatible. See the published [gateway configuration reference](https://docs.nvidia.com/openshell/latest/reference/gateway-config). 4. The CLI registers a reachable gateway endpoint with `openshell gateway add`. 5. The gateway creates sandboxes through the selected compute driver. +If supervisor sessions fail with a protocol revision mismatch, check that custom supervisor images match the gateway release. Gateway and supervisor require the same internal protocol revision; authentication success does not make mismatched versions compatible. Supervisors that predate the handshake still connect for one release. The gateway logs a warning for each such session and counts them in the `openshell_supervisor_protocol_legacy_sessions_total` metric, so recreate those sandboxes before the next gateway upgrade. See the published [gateway configuration reference](https://docs.nvidia.com/openshell/latest/reference/gateway-config.md). + The `openshell-gateway` composition crate explicitly installs its compiled Docker, Podman, Kubernetes, and VM registrations at startup; `openshell-server` does not link compute-driver crates. With no configured driver, the From a9387c758db2b5031c3c19182b94f0190f342094 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Wed, 9 Sep 2026 16:54:24 -0700 Subject: [PATCH 5/5] chore(sdk): regenerate Go proto bindings for protocol revision comment Signed-off-by: Piotr Mlocek --- sdk/go/proto/openshellv1/openshell.pb.go | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/go/proto/openshellv1/openshell.pb.go b/sdk/go/proto/openshellv1/openshell.pb.go index 97ea45abf7..d4be736a95 100644 --- a/sdk/go/proto/openshellv1/openshell.pb.go +++ b/sdk/go/proto/openshellv1/openshell.pb.go @@ -11296,6 +11296,7 @@ type SupervisorHello struct { // Supervisor instance ID (e.g. boot id or process epoch). InstanceId string `protobuf:"bytes,2,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` // Exact internal stream protocol revision implemented by this supervisor. + // Zero identifies a supervisor built before the handshake existed. ProtocolRevision uint32 `protobuf:"varint,3,opt,name=protocol_revision,json=protocolRevision,proto3" json:"protocol_revision,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache