feat(server): separate image preparation and admission deadlines

Give sandbox image preparation its own deadline and start the admission
deadline after preparation finishes. Persist both phases across gateway
restarts and show recovery guidance for the phase that expired.

Preserve the current service authorization schema and regenerate the Go
bindings with the preparation timestamps.

Fixes #3952
Related to #3955

Signed-off-by: Shiju <shiju@nvidia.com>
This commit is contained in:
Shiju
2026-10-01 13:49:50 +05:30
parent 912a077bd6
commit 7bdeab3784
16 changed files with 989 additions and 256 deletions
+105 -4
View File
@@ -1230,14 +1230,15 @@ pub async fn sandbox_create(
SandboxPhase::Error => {
drop(stream);
drop(client);
let provisioning_timed_out = last_sandbox
let timed_out_provisioning = last_sandbox
.status
.as_ref()
.and_then(|status| status.provisioning.as_ref())
.is_some_and(|record| record.timeout_time.is_some());
let create_result = if provisioning_timed_out {
.filter(|record| record.timeout_time.is_some());
let create_result = if let Some(record) = timed_out_provisioning {
Err(miette::miette!(
"{last_error_reason}\nSandbox '{sandbox_name}' was retained. Inspect it with `openshell sandbox get {sandbox_name}`; repair its configuration, then run `openshell sandbox start {sandbox_name}` after cleanup completes."
"{}",
retained_sandbox_timeout_message(&sandbox_name, &last_error_reason, record)
))
} else if last_error_reason.is_empty() {
Err(miette::miette!(
@@ -1271,6 +1272,24 @@ pub async fn sandbox_create(
}
}
/// Use the persisted phase to select recovery guidance. Preparation may expire
/// before any policy is evaluated, so it must not tell the user to repair policy.
fn retained_sandbox_timeout_message(
sandbox_name: &str,
error_reason: &str,
record: &openshell_core::proto::SandboxProvisioning,
) -> String {
let recovery = if record.preparation_deadline.is_some() && record.admission_start_time.is_none()
{
"check image preparation and supervisor startup diagnostics and the gateway's `image_preparation_timeout_seconds` budget"
} else {
"repair its configuration"
};
format!(
"{error_reason}\nSandbox '{sandbox_name}' was retained. Inspect it with `openshell sandbox get {sandbox_name}`; {recovery}, then run `openshell sandbox start {sandbox_name}` after cleanup completes."
)
}
/// Resolved source for the `--from` flag on `sandbox create`.
#[derive(Debug)]
enum ResolvedSource {
@@ -2783,6 +2802,15 @@ fn sandbox_to_json(sandbox: &Sandbox) -> serde_json::Value {
"configuration_change_id": record.configuration_change_id,
"configuration_change_time": record.configuration_change_time.as_ref().map(ToString::to_string),
"first_rejection_time": record.first_rejection_time.as_ref().map(ToString::to_string),
"phase": if record.deadline.is_none() && record.timeout_time.is_none() {
"ready"
} else if record.preparation_deadline.is_some() && record.admission_start_time.is_none() {
"preparation"
} else {
"admission"
},
"preparation_deadline": record.preparation_deadline.as_ref().map(ToString::to_string),
"admission_start_time": record.admission_start_time.as_ref().map(ToString::to_string),
"deadline": record.deadline.as_ref().map(ToString::to_string),
"timeout_time": record.timeout_time.as_ref().map(ToString::to_string),
"cleanup_completed_time": record.cleanup_completed_time.as_ref().map(ToString::to_string),
@@ -7792,6 +7820,79 @@ mod tests {
);
}
#[test]
fn retained_sandbox_timeout_message_matches_expired_phase() {
let mut record = openshell_core::proto::SandboxProvisioning {
preparation_deadline: openshell_core::time::timestamp_from_millis(1_800_000).ok(),
timeout_time: openshell_core::time::timestamp_from_millis(1_800_000).ok(),
..Default::default()
};
let message = super::retained_sandbox_timeout_message(
"cold-image",
"ImagePreparationTimedOut: preparation expired",
&record,
);
assert!(message.starts_with("ImagePreparationTimedOut: preparation expired\n"));
assert!(message.contains("Sandbox 'cold-image' was retained"));
assert!(message.contains("image preparation and supervisor startup diagnostics"));
assert!(message.contains("image_preparation_timeout_seconds"));
assert!(!message.contains("repair its configuration"));
assert!(message.contains("openshell sandbox get cold-image"));
assert!(message.contains("openshell sandbox start cold-image` after cleanup completes"));
// An admission timeout retains preparation timestamps. Its completed
// transition must select configuration repair rather than a larger budget.
record.admission_start_time = openshell_core::time::timestamp_from_millis(600_000).ok();
let admission_without_preparation = openshell_core::proto::SandboxProvisioning {
timeout_time: record.timeout_time,
..Default::default()
};
for admission_record in [&record, &admission_without_preparation] {
let message = super::retained_sandbox_timeout_message(
"invalid-policy",
"ProvisioningTimedOut: repair window expired",
admission_record,
);
assert!(message.contains("repair its configuration"));
assert!(!message.contains("image_preparation_timeout_seconds"));
assert!(
message.contains("openshell sandbox start invalid-policy` after cleanup completes")
);
}
}
#[test]
fn provisioning_json_distinguishes_preparation_and_admission() {
let mut sandbox = Sandbox::default();
sandbox.set_phase(SandboxPhase::Provisioning.into());
let ceiling = openshell_core::time::timestamp_from_millis(1_800_000).ok();
sandbox.status.as_mut().unwrap().provisioning =
Some(openshell_core::proto::SandboxProvisioning {
preparation_deadline: ceiling,
deadline: ceiling,
..Default::default()
});
let json = super::sandbox_to_json(&sandbox);
assert_eq!(json["provisioning"]["phase"], "preparation");
assert_eq!(
json["provisioning"]["preparation_deadline"],
"1970-01-01T00:30:00Z"
);
assert!(json["provisioning"]["admission_start_time"].is_null());
sandbox
.status
.as_mut()
.unwrap()
.provisioning
.as_mut()
.unwrap()
.admission_start_time = openshell_core::time::timestamp_from_millis(600_000).ok();
assert_eq!(
super::sandbox_to_json(&sandbox)["provisioning"]["phase"],
"admission"
);
}
#[test]
fn sandbox_json_exposes_repair_diagnostic_and_accepted_generation() {
use openshell_core::proto::{ConfigurationAdmissionState, SandboxConfigurationAdmission};
+5
View File
@@ -240,6 +240,10 @@ pub struct Config {
/// TTL for SSH session tokens, in seconds. 0 disables expiry.
pub ssh_session_ttl_secs: u64,
/// Absolute image preparation and initial supervisor startup budget for new
/// sandbox attempts, in seconds. Must be between 1 and 86400, inclusive.
pub image_preparation_timeout_seconds: u32,
/// Maximum gRPC requests allowed per rate-limit window.
///
/// When paired with [`Self::grpc_rate_limit_window_secs`], positive values
@@ -865,6 +869,7 @@ impl Config {
credential_drivers: Vec::new(),
default_credential_driver: None,
ssh_session_ttl_secs: default_ssh_session_ttl_secs(),
image_preparation_timeout_seconds: 1800,
grpc_rate_limit_requests: None,
grpc_rate_limit_window_secs: None,
service_routing: ServiceRoutingConfig::default(),
+49
View File
@@ -560,6 +560,18 @@ fn prepare_server_config_with_drivers(
config.policy_validation_failure_mode = mode;
}
if let Some(seconds) = file
.as_ref()
.and_then(|f| f.openshell.gateway.image_preparation_timeout_seconds)
{
if !(1..=86_400).contains(&seconds) {
return Err(miette::miette!(
"image_preparation_timeout_seconds must be between 1 and 86400"
));
}
config.image_preparation_timeout_seconds = seconds;
}
if let Some(issuer) = args.oidc_issuer.clone() {
config = config.with_oidc(openshell_core::OidcConfig {
issuer,
@@ -3292,6 +3304,7 @@ version = 2
[openshell.gateway]
policy_validation_failure_mode = "retain_last_valid"
image_preparation_timeout_seconds = 2400
[openshell.drivers.docker]
unknown_docker_key = true
@@ -3317,6 +3330,7 @@ mem_mib = "not-a-number"
super::prepare_server_config(&mut args, &matches).expect("server config is prepared");
assert_eq!(prepared.config.compute_driver.as_deref(), Some("podman"));
assert_eq!(prepared.config.image_preparation_timeout_seconds, 2400);
assert_eq!(
prepared.config.policy_validation_failure_mode,
openshell_core::PolicyValidationFailureMode::RetainLastValid
@@ -3325,4 +3339,39 @@ mem_mib = "not-a-number"
assert!(file.openshell.drivers.contains_key("docker"));
assert!(file.openshell.drivers.contains_key("vm"));
}
#[test]
fn server_config_rejects_unbounded_image_preparation() {
let _lock = ENV_LOCK
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let state = tempfile::tempdir().unwrap();
let tls = tempfile::tempdir().unwrap();
let _state = EnvVarGuard::set("XDG_STATE_HOME", state.path().to_str().unwrap());
let _tls = EnvVarGuard::set("OPENSHELL_LOCAL_TLS_DIR", tls.path().to_str().unwrap());
let config_path = state.path().join("gateway.toml");
for seconds in [0, 86_401] {
std::fs::write(&config_path, format!(
"[openshell]\nversion = 2\n[openshell.gateway]\nimage_preparation_timeout_seconds = {seconds}\n"
)).unwrap();
let (mut args, matches) = parse_with_args(&[
"openshell-gateway",
"--config",
config_path.to_str().unwrap(),
"--db-url",
"sqlite::memory:",
"--compute-driver",
"podman",
"--disable-tls",
]);
let Err(error) = super::prepare_server_config(&mut args, &matches) else {
panic!("unbounded preparation must be rejected");
};
assert!(
error
.to_string()
.contains("image_preparation_timeout_seconds must be between 1 and 86400")
);
}
}
}
+218 -28
View File
@@ -644,6 +644,7 @@ pub struct ComputeRuntime {
telemetry_compute_driver: TelemetryComputeDriver,
driver_process: Option<Arc<ManagedDriverProcess>>,
default_image: String,
image_preparation_timeout_seconds: u32,
store: Arc<Store>,
sandbox_index: SandboxIndex,
sandbox_watch_bus: SandboxWatchBus,
@@ -745,6 +746,7 @@ impl ComputeRuntime {
telemetry_compute_driver: TelemetryComputeDriver::custom(),
driver_process,
default_image,
image_preparation_timeout_seconds: 1800,
store,
sandbox_index,
sandbox_watch_bus,
@@ -826,6 +828,16 @@ impl ComputeRuntime {
&self.default_image
}
/// Validate the budget once at startup. Persisted attempts keep their
/// original deadline even if the operator changes this value on restart.
pub(crate) fn with_image_preparation_timeout(mut self, seconds: u32) -> Result<Self, String> {
if !(1..=86_400).contains(&seconds) {
return Err("image_preparation_timeout_seconds must be between 1 and 86400".into());
}
self.image_preparation_timeout_seconds = seconds;
Ok(self)
}
#[must_use]
pub fn driver_info_snapshots(&self) -> &[ComputeDriverInfoSnapshot] {
std::slice::from_ref(&self.driver_info)
@@ -1618,6 +1630,7 @@ impl ComputeRuntime {
SandboxPhase::Starting,
"Starting",
"Sandbox start requested",
self.image_preparation_timeout_seconds,
);
},
)
@@ -1699,7 +1712,7 @@ impl ComputeRuntime {
.await.map_err(|error| Status::internal(error.to_string()))?
.ok_or_else(|| Status::not_found("sandbox removed during startup"))?;
if provisioning_deadline::timed_out(&current) {
return Err(Status::deadline_exceeded("provisioning repair window expired"));
return Err(Status::deadline_exceeded("provisioning deadline expired"));
}
}
}
@@ -2104,7 +2117,13 @@ impl ComputeRuntime {
&sandbox_id,
expected_resource_version,
move |sandbox| {
apply_lifecycle_phase(sandbox, phase, &reason, &message);
apply_lifecycle_phase(
sandbox,
phase,
&reason,
&message,
self.image_preparation_timeout_seconds,
);
},
)
.await
@@ -3311,22 +3330,27 @@ impl ComputeRuntime {
}
};
let expected_runtime_identity = sandbox_compute_runtime_identity(&sandbox);
// Recovery retains the original attempt and deadline. A
// stalled driver must release this lifecycle gate after
// expiry so the deadline worker can reclaim its compute.
if let Err(err) = self
.driver
.call(
openshell_otel::rpc::START_SANDBOX,
Some(&sandbox_id),
|driver| async move {
driver
.start_sandbox(Request::new(StartSandboxRequest {
sandbox_id: driver_sandbox_id,
name: sandbox_name,
launch_authentication: Vec::new(),
generation_id,
expected_runtime_identity,
}))
.await
},
.await_provisioning_operation(
&sandbox,
self.driver.call(
openshell_otel::rpc::START_SANDBOX,
Some(&sandbox_id),
|driver| async move {
driver
.start_sandbox(Request::new(StartSandboxRequest {
sandbox_id: driver_sandbox_id,
name: sandbox_name,
launch_authentication: Vec::new(),
generation_id,
expected_runtime_identity,
}))
.await
},
),
)
.await
{
@@ -6503,7 +6527,13 @@ fn is_recoverable_error_reason(sandbox: &Sandbox) -> bool {
.is_some_and(|c| c.reason == CONDITION_RUNTIME_RESTART || c.reason == CONDITION_STOPPED)
}
fn apply_lifecycle_phase(sandbox: &mut Sandbox, phase: SandboxPhase, reason: &str, message: &str) {
fn apply_lifecycle_phase(
sandbox: &mut Sandbox,
phase: SandboxPhase,
reason: &str,
message: &str,
image_preparation_timeout_seconds: u32,
) {
sandbox.set_phase(phase as i32);
if matches!(phase, SandboxPhase::Stopping | SandboxPhase::Starting) {
let status = sandbox.status.get_or_insert_with(Default::default);
@@ -6514,8 +6544,9 @@ fn apply_lifecycle_phase(sandbox: &mut Sandbox, phase: SandboxPhase, reason: &st
set_next_restart_at_ms(status, 0);
set_main_process_started_at_ms(status, 0);
if phase == SandboxPhase::Starting {
status.provisioning = Some(provisioning_deadline::new_record(
status.provisioning = Some(provisioning_deadline::new_preparation_record(
openshell_core::time::now_ms(),
image_preparation_timeout_seconds,
));
status.configuration_admission =
Some(openshell_core::proto::SandboxConfigurationAdmission {
@@ -6890,6 +6921,7 @@ pub fn new_test_runtime_with_driver(
telemetry_compute_driver: TelemetryComputeDriver::custom(),
driver_process: None,
default_image: "openshell/sandbox:test".to_string(),
image_preparation_timeout_seconds: 1800,
store,
sandbox_index: SandboxIndex::new(),
sandbox_watch_bus: SandboxWatchBus::new(),
@@ -7939,6 +7971,7 @@ mod tests {
telemetry_compute_driver: TelemetryComputeDriver::custom(),
driver_process: None,
default_image: "openshell/sandbox:test".to_string(),
image_preparation_timeout_seconds: 1800,
store,
sandbox_index: SandboxIndex::new(),
sandbox_watch_bus: SandboxWatchBus::new(),
@@ -10453,18 +10486,19 @@ mod tests {
assert!(!crate::policy_store::permits_initial_static_policy_repair(
&blocked
));
// Simulate the supervisor's successful exact-generation admission report.
// The supervisor report records the preparation-to-admission transition
// together with acceptance of the exact configuration generation.
runtime
.store
.update_message_cas::<Sandbox, _>(sandbox.object_id(), 0, |sandbox| {
sandbox
.status
.as_mut()
.unwrap()
.configuration_admission
.as_mut()
.unwrap()
.state = openshell_core::proto::ConfigurationAdmissionState::Accepted.into();
let status = sandbox.status.as_mut().unwrap();
provisioning_deadline::record_admission_start(
status.provisioning.as_mut().unwrap(),
openshell_core::time::now_ms(),
)
.unwrap();
status.configuration_admission.as_mut().unwrap().state =
openshell_core::proto::ConfigurationAdmissionState::Accepted.into();
})
.await
.unwrap();
@@ -15210,6 +15244,162 @@ mod tests {
.unwrap()
}
#[tokio::test]
async fn preparation_expiry_releases_stalled_start_recovery_for_cleanup() {
let driver = ControlledDriver::new();
driver.block_start();
let runtime = test_runtime(driver.clone()).await;
let now = openshell_core::time::now_ms();
let preparation = provisioning_deadline::new_preparation_record(now, 1800);
let mut sandbox = sandbox_record("sb-recovery-ttl", "recovery-ttl", SandboxPhase::Starting);
sandbox.status.as_mut().unwrap().provisioning = Some(preparation.clone());
runtime.store.put_message(&sandbox).await.unwrap();
let recovered_runtime = runtime.clone();
let mut recovery = tokio::spawn(async move {
recovered_runtime
.recover_persisted_lifecycle_transitions()
.await
});
tokio::time::timeout(Duration::from_secs(1), driver.start_started.notified())
.await
.unwrap();
runtime
.reconcile_provisioning_deadlines(now + 1_800_000)
.await
.unwrap();
let expired = runtime
.store
.get_message::<Sandbox>("sb-recovery-ttl")
.await
.unwrap()
.unwrap();
assert_eq!(expired.phase(), i32::from(SandboxPhase::Error));
let status = expired.status.as_ref().unwrap();
let record = status.provisioning.as_ref().unwrap();
assert_eq!(record.attempt_id, preparation.attempt_id);
assert_eq!(
record.preparation_deadline,
preparation.preparation_deadline
);
assert!(
status
.conditions
.iter()
.any(|condition| condition.reason == "ImagePreparationTimedOut")
);
// The recovery RPC never receives its semaphore permit. The persisted
// expiry must cancel its waiter and release the lifecycle gate itself.
if let Ok(result) = tokio::time::timeout(Duration::from_secs(3), &mut recovery).await {
result.unwrap().unwrap();
} else {
recovery.abort();
let _ = recovery.await;
panic!("expired recovery kept the lifecycle gate while the driver was blocked");
}
runtime
.reconcile_provisioning_deadlines(now + 1_800_001)
.await
.unwrap();
tokio::time::timeout(Duration::from_secs(1), async {
loop {
let sandbox = runtime
.store
.get_message::<Sandbox>("sb-recovery-ttl")
.await
.unwrap()
.unwrap();
let record = sandbox
.status
.as_ref()
.unwrap()
.provisioning
.as_ref()
.unwrap();
if record.cleanup_completed_time.is_some() {
assert_eq!(record.attempt_id, preparation.attempt_id);
break;
}
tokio::task::yield_now().await;
}
})
.await
.unwrap();
assert_eq!(driver.stop_calls(), 1);
}
#[tokio::test]
async fn preparation_timeout_retains_reason_and_uses_existing_cleanup() {
let driver = ControlledDriver::new();
let runtime = test_runtime(driver.clone()).await;
let mut sandbox = sandbox_record("sb-prepare", "prepare", SandboxPhase::Provisioning);
sandbox.status.as_mut().unwrap().provisioning =
Some(provisioning_deadline::new_preparation_record(0, 1800));
runtime.store.put_message(&sandbox).await.unwrap();
let sandbox = runtime
.store
.get_message::<Sandbox>("sb-prepare")
.await
.unwrap()
.unwrap();
let gate = runtime.lifecycle_gates.lock_for("sb-prepare").await;
let global = runtime.lock_global_for_lifecycle(&gate).await;
assert!(
runtime
.claim_provisioning_timeout(&sandbox, 600_000)
.await
.unwrap()
.is_none()
);
let expired = runtime
.claim_provisioning_timeout(&sandbox, 1_800_000)
.await
.unwrap()
.unwrap();
assert_eq!(expired.phase(), i32::from(SandboxPhase::Error));
assert!(
expired
.status
.as_ref()
.unwrap()
.conditions
.iter()
.any(|condition| { condition.reason == "ImagePreparationTimedOut" })
);
let record = expired
.status
.as_ref()
.unwrap()
.provisioning
.as_ref()
.unwrap();
assert!(record.admission_start_time.is_none());
assert!(record.preparation_deadline.is_some());
assert!(record.cleanup_completed_time.is_none());
drop(global);
runtime
.reclaim_provisioning_timeout(&expired, &gate)
.await
.unwrap();
let reclaimed = runtime
.store
.get_message::<Sandbox>("sb-prepare")
.await
.unwrap()
.unwrap();
assert!(
reclaimed
.status
.as_ref()
.unwrap()
.provisioning
.as_ref()
.unwrap()
.cleanup_completed_time
.is_some()
);
assert_eq!(driver.stop_calls(), 1);
}
#[tokio::test]
async fn provisioning_timeout_persists_error_before_cleanup_and_preserves_record() {
let driver = ControlledDriver::new();
@@ -1,11 +1,12 @@
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Gateway-owned provisioning repair-window transitions.
//! Gateway-owned image preparation and admission repair deadlines.
//!
//! Callers must persist each transition under the sandbox lifecycle fence. Times
//! are gateway-assigned Unix milliseconds, never supervisor-supplied values.
//! The timer remains armed after admission acceptance until compute becomes Ready.
//! Preparation has an absolute ceiling. The first authenticated supervisor
//! configuration report starts admission repair, which remains armed until Ready.
use openshell_core::proto::SandboxProvisioning;
use openshell_core::time::{timestamp_from_millis, timestamp_to_millis};
@@ -26,6 +27,8 @@ pub(super) struct ProvisioningDeadline {
attempt_id: String,
change: ConfigurationChange,
first_rejection_at_ms: Option<i64>,
preparation_deadline_at_ms: Option<i64>,
admission_start_at_ms: Option<i64>,
state: DeadlineState,
}
@@ -50,6 +53,21 @@ impl ProvisioningDeadline {
if record.deadline.is_some() && record.timeout_time.is_some() {
return Err("provisioning cannot be armed and expired".into());
}
let preparation_deadline_at_ms = record
.preparation_deadline
.as_ref()
.map(|value| millis(Some(value), "preparation deadline"))
.transpose()?;
let admission_start_at_ms = record
.admission_start_time
.as_ref()
.map(|value| millis(Some(value), "admission start time"))
.transpose()?;
if admission_start_at_ms.is_some_and(|started| {
preparation_deadline_at_ms.is_none_or(|ceiling| started >= ceiling)
}) {
return Err("admission must start before its preparation deadline".into());
}
let state = if record.timeout_time.is_some() {
DeadlineState::Expired {
expired_at_ms: millis(record.timeout_time.as_ref(), "timeout time")?,
@@ -61,6 +79,13 @@ impl ProvisioningDeadline {
} else {
DeadlineState::Ready
};
if let Some(ceiling) = preparation_deadline_at_ms
&& admission_start_at_ms.is_none()
&& !matches!(state, DeadlineState::Expired { .. })
&& !matches!(state, DeadlineState::Armed { deadline_at_ms } if deadline_at_ms == ceiling)
{
return Err("preparation must retain its absolute deadline until admission".into());
}
Ok(Self {
attempt_id: record.attempt_id.clone(),
change: ConfigurationChange {
@@ -72,6 +97,8 @@ impl ProvisioningDeadline {
.as_ref()
.map(|value| millis(Some(value), "rejection time"))
.transpose()?,
preparation_deadline_at_ms,
admission_start_at_ms,
state,
})
}
@@ -84,6 +111,12 @@ impl ProvisioningDeadline {
record.first_rejection_time = self
.first_rejection_at_ms
.and_then(|value| timestamp_from_millis(value).ok());
record.preparation_deadline = self
.preparation_deadline_at_ms
.and_then(|value| timestamp_from_millis(value).ok());
record.admission_start_time = self
.admission_start_at_ms
.and_then(|value| timestamp_from_millis(value).ok());
record.deadline = self
.deadline_at_ms()
.and_then(|value| timestamp_from_millis(value).ok());
@@ -98,12 +131,38 @@ impl ProvisioningDeadline {
attempt_id,
change,
first_rejection_at_ms: None,
preparation_deadline_at_ms: None,
admission_start_at_ms: None,
state: DeadlineState::Armed {
deadline_at_ms: now_ms.saturating_add(REPAIR_WINDOW_MS),
},
}
}
fn is_preparing(&self) -> bool {
self.preparation_deadline_at_ms.is_some() && self.admission_start_at_ms.is_none()
}
/// Only an authenticated report for the current supervisor may call this.
/// Persist it with the report: duplicate delivery or restart must not grant
/// another admission window, and a late registration cannot revive compute.
fn start_admission(&mut self, attempt_id: &str, now_ms: i64) -> bool {
if attempt_id != self.attempt_id
|| !self.is_preparing()
|| now_ms < self.change.committed_at_ms
|| self
.deadline_at_ms()
.is_none_or(|deadline| now_ms >= deadline)
{
return false;
}
self.admission_start_at_ms = Some(now_ms);
self.state = DeadlineState::Armed {
deadline_at_ms: now_ms.saturating_add(REPAIR_WINDOW_MS),
};
true
}
pub fn deadline_at_ms(&self) -> Option<i64> {
match self.state {
DeadlineState::Armed { deadline_at_ms } => Some(deadline_at_ms),
@@ -124,10 +183,12 @@ impl ProvisioningDeadline {
{
return false;
}
self.state = DeadlineState::Armed {
deadline_at_ms: deadline_at_ms
.max(change.committed_at_ms.saturating_add(REPAIR_WINDOW_MS)),
};
if !self.is_preparing() {
self.state = DeadlineState::Armed {
deadline_at_ms: deadline_at_ms
.max(change.committed_at_ms.saturating_add(REPAIR_WINDOW_MS)),
};
}
self.change = change;
self.first_rejection_at_ms = None;
true
@@ -140,6 +201,7 @@ impl ProvisioningDeadline {
return false;
};
if !self.matches(attempt_id, change_id)
|| self.is_preparing()
|| self.first_rejection_at_ms.is_some()
|| now_ms < self.change.committed_at_ms
|| now_ms >= deadline_at_ms
@@ -173,6 +235,7 @@ impl ProvisioningDeadline {
/// must not call this method. Late readiness requires an explicit retry.
pub fn ready(&mut self, attempt_id: &str, change_id: &str, now_ms: i64) -> bool {
if !self.matches(attempt_id, change_id)
|| self.is_preparing()
|| self
.deadline_at_ms()
.is_none_or(|deadline| now_ms >= deadline)
@@ -197,7 +260,8 @@ pub fn timed_out(sandbox: &openshell_core::proto::Sandbox) -> bool {
.is_some_and(|record| record.timeout_time.is_some())
}
/// Create an independent attempt. Supervisor reconnects must never call this.
/// Adopt an existing untimed attempt without granting it a new preparation phase.
/// New create/start operations use `new_preparation_record` instead.
pub fn new_record(now_ms: i64) -> SandboxProvisioning {
let mut record = SandboxProvisioning::default();
ProvisioningDeadline::new(
@@ -212,6 +276,26 @@ pub fn new_record(now_ms: i64) -> SandboxProvisioning {
record
}
/// Create an independent attempt with a fixed preparation budget. The gateway
/// validates the configured seconds before constructing the runtime. Reconnects
/// and driver progress must never call this function.
pub fn new_preparation_record(now_ms: i64, timeout_seconds: u32) -> SandboxProvisioning {
let mut record = new_record(now_ms);
let ceiling = now_ms.saturating_add(i64::from(timeout_seconds) * 1_000);
record.preparation_deadline = timestamp_from_millis(ceiling).ok();
record.deadline.clone_from(&record.preparation_deadline);
record
}
/// The caller has checked the report's authentication, instance fence and
/// configuration generation. Persist this transition in the same CAS as admission.
pub fn record_admission_start(record: &mut SandboxProvisioning, now_ms: i64) -> Result<(), String> {
let mut deadline = ProvisioningDeadline::from_record(record)?;
deadline.start_admission(&record.attempt_id, now_ms);
deadline.write_record(record);
Ok(())
}
/// Apply the first accepted rejection under the same CAS as admission evidence.
/// The report's generation and supervisor instance must already be validated.
pub fn record_rejection(record: &mut SandboxProvisioning, now_ms: i64) -> Result<(), String> {
@@ -250,6 +334,10 @@ pub(super) fn reconcile_readiness(sandbox: &mut openshell_core::proto::Sandbox,
if deadline.ready(&record.attempt_id, &record.configuration_change_id, now_ms) {
deadline.write_record(record);
} else {
let awaiting_registration = deadline.is_preparing()
&& deadline
.deadline_at_ms()
.is_some_and(|value| now_ms < value);
status.phase = SandboxPhase::Provisioning.into();
status
.conditions
@@ -257,8 +345,18 @@ pub(super) fn reconcile_readiness(sandbox: &mut openshell_core::proto::Sandbox,
status.conditions.push(SandboxCondition {
r#type: "Ready".into(),
status: "False".into(),
reason: "ProvisioningDeadlineElapsed".into(),
message: "Provisioning deadline elapsed; awaiting compute reclamation".into(),
reason: if awaiting_registration {
"ConfigurationPending"
} else {
"ProvisioningDeadlineElapsed"
}
.into(),
message: if awaiting_registration {
"Waiting for an authenticated supervisor configuration report"
} else {
"Provisioning deadline elapsed; awaiting compute reclamation"
}
.into(),
..Default::default()
});
}
@@ -442,6 +540,7 @@ impl super::ComputeRuntime {
return Ok(None);
};
let mut deadline = ProvisioningDeadline::from_record(record)?;
let preparation_expired = deadline.is_preparing();
if !deadline.expire(&record.attempt_id, &record.configuration_change_id, now_ms) {
return Ok(None);
}
@@ -463,7 +562,9 @@ impl super::ComputeRuntime {
.configuration_admission
.as_ref()
.map_or("", |admission| admission.error.as_str());
let message = if diagnostic.is_empty() {
let message = if preparation_expired {
"Image preparation or initial supervisor startup exceeded its absolute deadline".to_string()
} else if diagnostic.is_empty() {
"Provisioning repair window expired after 300 seconds".to_string()
} else {
format!(
@@ -476,7 +577,11 @@ impl super::ComputeRuntime {
status.conditions.push(SandboxCondition {
r#type: "Ready".into(),
status: "False".into(),
reason: "ProvisioningTimedOut".into(),
reason: if preparation_expired {
"ImagePreparationTimedOut"
} else {
"ProvisioningTimedOut"
}.into(),
message,
transition_time: timestamp_from_millis(now_ms).ok(),
});
@@ -488,7 +593,8 @@ impl super::ComputeRuntime {
self.sandbox_watch_bus.notify(current.object_id());
tracing::warn!(
sandbox_id = current.object_id(),
"Sandbox provisioning repair window expired"
preparation_expired,
"Sandbox provisioning deadline expired"
);
Ok(Some(updated))
}
@@ -654,6 +760,87 @@ impl super::ComputeRuntime {
mod tests {
use super::*;
#[test]
fn existing_wire_record_does_not_gain_preparation_time() {
use prost::Message;
// Encoded before preparation timestamps existed: attempt a, change c,
// configuration at epoch 0, and an admission deadline at 300 seconds.
let bytes = [0x0a, 1, b'a', 0x12, 1, b'c', 0x1a, 0, 0x2a, 3, 8, 0xac, 2];
let mut record = SandboxProvisioning::decode(bytes.as_slice()).unwrap();
let before = record.clone();
record_admission_start(&mut record, 299_999).unwrap();
assert_eq!(record, before);
assert!(record.preparation_deadline.is_none());
assert!(!allows_admission(&record, 300_000));
}
#[test]
fn preparation_over_five_minutes_gets_a_full_admission_repair_window() {
let record = new_preparation_record(0, 1800);
let mut timer = ProvisioningDeadline::from_record(&record).unwrap();
let attempt = record.attempt_id;
let change_id = record.configuration_change_id;
assert!(!timer.expire(&attempt, &change_id, 600_000));
assert!(!timer.ready(&attempt, &change_id, 600_000));
assert!(timer.start_admission(&attempt, 600_000));
assert_eq!(timer.deadline_at_ms(), Some(900_000));
assert!(timer.rejected(&attempt, &change_id, 601_000));
assert_eq!(timer.deadline_at_ms(), Some(901_000));
assert!(!timer.start_admission(&attempt, 800_000));
assert!(timer.configuration_changed(&attempt, change("updated", 800_000)));
assert_eq!(timer.deadline_at_ms(), Some(1_100_000));
assert_eq!(timer.admission_start_at_ms, Some(600_000));
assert_eq!(timer.preparation_deadline_at_ms, Some(1_800_000));
}
#[test]
fn preparation_config_changes_and_restart_preserve_the_absolute_ceiling() {
use prost::Message;
let mut record = new_preparation_record(0, 1800);
let mut timer = ProvisioningDeadline::from_record(&record).unwrap();
let attempt = record.attempt_id.clone();
assert!(timer.configuration_changed(&attempt, change("first", 600_000)));
assert!(timer.configuration_changed(&attempt, change("last", 1_799_000)));
assert!(!timer.configuration_changed(&attempt, change("last", 1_799_500)));
assert!(!timer.rejected(&attempt, "last", 1_799_500));
timer.write_record(&mut record);
let bytes = record.encode_to_vec();
let restored = SandboxProvisioning::decode(bytes.as_slice()).unwrap();
let mut timer = ProvisioningDeadline::from_record(&restored).unwrap();
assert_eq!(timer.deadline_at_ms(), Some(1_800_000));
assert!(!timer.start_admission("previous-attempt", 1_799_999));
assert!(!timer.start_admission(&attempt, 1_800_000));
assert!(timer.expire(&attempt, "last", 1_800_000));
assert!(!timer.start_admission(&attempt, 1_799_999));
assert!(!timer.ready(&attempt, "last", 1_799_999));
assert!(!timer.configuration_changed(&attempt, change("late", 1_799_999)));
}
#[test]
fn admission_registration_roundtrip_does_not_restart_repair() {
use prost::Message;
let mut record = new_preparation_record(0, 1800);
record_admission_start(&mut record, 600_000).unwrap();
let before = record.clone();
let bytes = record.encode_to_vec();
let mut restored = SandboxProvisioning::decode(bytes.as_slice()).unwrap();
record_admission_start(&mut restored, 899_999).unwrap();
assert_eq!(restored, before);
assert!(!allows_admission(&restored, 900_000));
}
#[test]
fn malformed_preparation_timing_cannot_grant_admission() {
let mut record = new_preparation_record(0, 1800);
record.deadline = timestamp_from_millis(1_800_001).ok();
assert!(ProvisioningDeadline::from_record(&record).is_err());
record.deadline = None;
assert!(ProvisioningDeadline::from_record(&record).is_err());
record.deadline = record.preparation_deadline;
record.admission_start_time = timestamp_from_millis(1_800_000).ok();
assert!(ProvisioningDeadline::from_record(&record).is_err());
}
#[test]
fn protobuf_roundtrip_retains_deadline_and_cleanup_progress() {
use prost::Message;
@@ -116,6 +116,9 @@ pub struct GatewayFileSection {
// ── Sandbox / SSH ────────────────────────────────────────────────────
#[serde(default)]
pub ssh_session_ttl_secs: Option<u64>,
/// Absolute preparation budget for new attempts; existing deadlines persist.
#[serde(default)]
pub image_preparation_timeout_seconds: Option<u32>,
#[serde(default)]
pub grpc_rate_limit_requests: Option<u64>,
#[serde(default)]
+142 -5
View File
@@ -4424,7 +4424,7 @@ pub(super) async fn handle_report_sandbox_configuration(
.map_err(Status::internal)?;
if crate::compute::provisioning_deadline::timed_out(&sandbox) {
return Err(Status::failed_precondition(
"provisioning repair window expired; explicitly start the sandbox after cleanup",
"provisioning deadline expired; explicitly start the sandbox after cleanup",
));
}
let current = sandbox
@@ -4510,10 +4510,10 @@ pub(super) async fn handle_report_sandbox_configuration(
.claim_provisioning_timeout(&sandbox, now_ms)
.await
.map_err(Status::internal)?;
return Err(Status::failed_precondition(
"provisioning repair window expired",
));
return Err(Status::failed_precondition("provisioning deadline expired"));
}
crate::compute::provisioning_deadline::record_admission_start(record, now_ms)
.map_err(Status::internal)?;
if reported == ConfigurationAdmissionState::Rejected {
crate::compute::provisioning_deadline::record_rejection(record, now_ms)
.map_err(Status::internal)?;
@@ -7718,6 +7718,143 @@ mod tests {
request
}
#[tokio::test]
async fn preparation_registration_starts_repair_once_after_a_cold_start() {
use crate::compute::provisioning_deadline::new_preparation_record;
use openshell_core::proto::{
ConfigurationAdmissionState, ReportSandboxConfigurationRequest,
SandboxConfigurationAdmission, SandboxPhase,
};
use openshell_core::time::timestamp_to_millis;
let state = test_server_state().await;
let sandbox_id = "sb-cold-registration";
let mut sandbox = test_sandbox(
sandbox_id,
"cold-registration",
openshell_policy::restrictive_default_policy(),
Vec::new(),
);
sandbox.set_phase(SandboxPhase::Provisioning.into());
let preparation = new_preparation_record(current_time_ms() - 600_000, 1800);
sandbox.status.as_mut().unwrap().provisioning = Some(preparation.clone());
state.store.put_message(&sandbox).await.unwrap();
let instance_id = uuid::Uuid::new_v4().to_string();
let request = || {
with_sandbox(
Request::new(ReportSandboxConfigurationRequest {
sandbox_id: sandbox_id.into(),
admission: Some(SandboxConfigurationAdmission {
instance_id: instance_id.clone(),
state: ConfigurationAdmissionState::Pending.into(),
..Default::default()
}),
..Default::default()
}),
sandbox_id,
)
};
// A duplicate report racing the initial registration must share one
// persisted transition; either may acquire the lifecycle fence first.
let (first, duplicate) = tokio::join!(
handle_report_sandbox_configuration(&state, request()),
handle_report_sandbox_configuration(&state, request()),
);
first.unwrap();
duplicate.unwrap();
let saved = state
.store
.get_message::<Sandbox>(sandbox_id)
.await
.unwrap()
.unwrap();
let record = saved
.status
.as_ref()
.unwrap()
.provisioning
.as_ref()
.unwrap();
assert_eq!(
record.preparation_deadline,
preparation.preparation_deadline
);
let start = timestamp_to_millis(record.admission_start_time.as_ref().unwrap()).unwrap();
let deadline = timestamp_to_millis(record.deadline.as_ref().unwrap()).unwrap();
assert_eq!(deadline - start, 300_000);
handle_report_sandbox_configuration(&state, request())
.await
.unwrap();
let repeated = state
.store
.get_message::<Sandbox>(sandbox_id)
.await
.unwrap()
.unwrap();
assert_eq!(
repeated
.status
.as_ref()
.unwrap()
.provisioning
.as_ref()
.unwrap(),
record
);
}
#[tokio::test]
async fn preparation_expiry_rejects_registration_before_the_scanner_runs() {
use crate::compute::provisioning_deadline::new_preparation_record;
use openshell_core::proto::{
ConfigurationAdmissionState, ReportSandboxConfigurationRequest,
SandboxConfigurationAdmission, SandboxPhase,
};
let state = test_server_state().await;
let sandbox_id = "sb-expired-preparation";
let mut sandbox = test_sandbox(
sandbox_id,
"expired-preparation",
openshell_policy::restrictive_default_policy(),
Vec::new(),
);
sandbox.set_phase(SandboxPhase::Provisioning.into());
sandbox.status.as_mut().unwrap().provisioning = Some(new_preparation_record(0, 1800));
state.store.put_message(&sandbox).await.unwrap();
let error = handle_report_sandbox_configuration(
&state,
with_sandbox(
Request::new(ReportSandboxConfigurationRequest {
sandbox_id: sandbox_id.into(),
admission: Some(SandboxConfigurationAdmission {
instance_id: uuid::Uuid::new_v4().to_string(),
state: ConfigurationAdmissionState::Pending.into(),
..Default::default()
}),
..Default::default()
}),
sandbox_id,
),
)
.await
.unwrap_err();
assert_eq!(error.code(), Code::FailedPrecondition);
let expired = state
.store
.get_message::<Sandbox>(sandbox_id)
.await
.unwrap()
.unwrap();
assert_eq!(expired.phase(), i32::from(SandboxPhase::Error));
let status = expired.status.unwrap();
assert!(status.provisioning.unwrap().admission_start_time.is_none());
assert!(
status
.conditions
.iter()
.any(|condition| condition.reason == "ImagePreparationTimedOut")
);
}
#[tokio::test]
async fn provisioning_timeout_rejects_supervisor_registration() {
use openshell_core::proto::{
@@ -7756,7 +7893,7 @@ mod tests {
.await
.unwrap_err();
assert_eq!(error.code(), Code::FailedPrecondition);
assert!(error.message().contains("repair window expired"));
assert!(error.message().contains("provisioning deadline expired"));
}
#[tokio::test]
+6 -1
View File
@@ -605,7 +605,12 @@ async fn handle_create_sandbox_inner(
.status
.as_mut()
.expect("status initialized")
.provisioning = Some(crate::compute::provisioning_deadline::new_record(now_ms));
.provisioning = Some(
crate::compute::provisioning_deadline::new_preparation_record(
now_ms,
state.config.image_preparation_timeout_seconds,
),
);
crate::compute::provisioning_deadline::refresh_configuration(
&state.store,
&mut sandbox,
+3
View File
@@ -1732,6 +1732,9 @@ async fn build_compute_runtime(
let runtime = runtime
.with_admission_policy(admission)
.and_then(|runtime| {
runtime.with_image_preparation_timeout(config.image_preparation_timeout_seconds)
})
.map_err(Error::config)?;
Ok(runtime.with_telemetry_compute_driver(telemetry_compute_driver))
}
+5 -2
View File
@@ -126,12 +126,15 @@ mod tests {
// inventories; the provider-environment file map is public-only. The
// request has no provider-file capability field: older supervisors ignore
// the additive file map while retaining the rest of the response.
// Preparation timing adds two optional timestamps to SandboxProvisioning.
// Existing rows decode with both absent and retain their active deadline;
// no stored attempt gains another phase or time budget on upgrade.
// Service authorization also extends both schemas additively. Legacy
// payloads retain the safe Strip default.
const PUBLIC_RPC_SCHEMA_SHA256: &str =
"2e156c6ad3c8eb51bcd30dc13b173fe339b38207a1b1f98f7be2e0cad8e3bd45";
"581125d215f2a1967eb73826c411c1e72a53fb3a30a20e85c51d96bbb518e078";
const DURABLE_SCHEMA_SHA256: &str =
"38165d9d76f49fcfe98a12f241e032838a2376c1d1a87ea2796fd33b9b1a3541";
"c1e49c80c52a5c7458952b333e7ca9da2dd24478b41756b710ba29a5217b67d7";
const PUBLIC_DURABLE_OVERLAP_SHA256: &str =
"761dea31a521b0650840fe2a823ad6e36a265ed323ba4506889781d630df0ee3";
// A persisted Sandbox without endpoint status retains its lifecycle fields;
+26 -1
View File
@@ -2720,7 +2720,12 @@ fn sandbox_notes_for_view(
} else {
"compute cleanup pending"
};
let mut notes = format!("Provisioning timed out; {cleanup}");
let mut notes =
if record.preparation_deadline.is_some() && record.admission_start_time.is_none() {
format!("Image preparation timed out; {cleanup}")
} else {
format!("Provisioning timed out; {cleanup}")
};
if !forwards.is_empty() {
notes.push_str("; ");
notes.push_str(&forwards);
@@ -3340,6 +3345,26 @@ mod sandbox_notes_tests {
);
}
#[test]
fn preparation_timeout_notes_identify_the_expired_phase() {
let sandbox = Sandbox {
status: Some(SandboxStatus {
provisioning: Some(openshell_core::proto::SandboxProvisioning {
preparation_deadline: openshell_core::time::timestamp_from_millis(1_800_000)
.ok(),
timeout_time: openshell_core::time::timestamp_from_millis(1_800_000).ok(),
..Default::default()
}),
..Default::default()
}),
..Default::default()
};
assert_eq!(
sandbox_notes(&sandbox, String::new()),
"Image preparation timed out; compute cleanup pending"
);
}
#[test]
fn configuration_rejection_precedes_forwards_and_clears_after_repair() {
let condition = SandboxCondition {
@@ -139,6 +139,10 @@ credential_drivers = ["kubernetes-secrets"]
ssh_session_ttl_secs = 3600
# Absolute image preparation and initial supervisor startup budget.
# Applies to new attempts only; allowed values are 1 through 86400 seconds.
image_preparation_timeout_seconds = 1800
# Reject invalid policy generations securely by default. Set
# "retain_last_valid" only when availability takes priority.
policy_validation_failure_mode = "fail_closed"
@@ -366,14 +366,11 @@ check the sandbox log for the specific error:
openshell sandbox get my-sandbox --output json
```
You have 300 seconds to fix the configuration. Replace the policy with
`openshell policy set`, or fix the provider configuration. Until the workload
first starts, you can also change filesystem, Landlock, and process settings.
Each change to the policy, providers, or settings restarts the 300 seconds.
You have 300 seconds to fix the configuration after the supervisor starts admission. Image preparation has its own deadline and does not consume that repair time. Replace the policy with `openshell policy set`, or fix the provider configuration. Until the workload first starts, you can also change filesystem, Landlock, and process settings. Each effective change to the policy, providers, or settings restarts the 300 seconds; writing an unchanged value does not.
If the time runs out, the sandbox moves to `Error` with the reason
`ProvisioningTimedOut`. Fixing the configuration does not restart it. After you
fix it, start the sandbox again, which begins a new 300-second window:
fix it, start the sandbox again. Admission gets a new 300-second window after preparation:
```shell
openshell sandbox start my-sandbox
+6 -16
View File
@@ -915,30 +915,20 @@ Management operations remain available while startup is blocked. After repair,
the supervisor completes startup without recreating the sandbox. Starting a
stopped sandbox repeats configuration admission before launching its workload.
The gateway enforces a 300-second provisioning repair window, independently of
the CLI wait timeout. An effective policy, settings, provider, profile, or
attachment change resets the window from its stored change time. The first
failed configuration load for that change grants another full window. Repeated
failures and reconnects do not extend it; reaching `Ready` clears it.
Image preparation and initial supervisor startup have an absolute deadline of 1800 seconds by default, independently of the CLI wait timeout. Operators can set `image_preparation_timeout_seconds` in `[openshell.gateway]` to any value from 1 through 86400. Each new create or explicit start stores its deadline. Progress events, configuration edits, and gateway or driver restarts cannot extend it. Changing the gateway setting affects new attempts only.
When the window expires, the sandbox enters `Error` with reason
`ProvisioningTimedOut`. The gateway stops its workload and supervisor compute,
retaining the sandbox record, diagnostic, and restartable storage. Cleanup can
remain pending if the backend is unavailable; the gateway retries it. Inspect
`provisioning` in JSON output for the deadline, timeout, and cleanup timestamps.
TUI NOTES distinguishes pending cleanup from reclaimed compute.
The first authenticated configuration report from the current supervisor ends preparation and starts a separate 300-second admission repair window. A slow image download therefore does not consume time reserved for fixing policy. During admission, an effective policy, settings, provider, profile, or attachment change resets the window from its stored change time. The first failed configuration load for that change grants another full window. Repeated failures, duplicate reports, and reconnects do not extend it; reaching `Ready` clears it.
Repair the configuration, wait for cleanup to complete, then explicitly restart:
Preparation expiry sets the sandbox to `Error` with reason `ImagePreparationTimedOut`; admission repair expiry uses `ProvisioningTimedOut`. The gateway stops its workload and supervisor compute, retaining the sandbox record, diagnostic, and restartable storage. Cleanup can remain pending if the backend is unavailable; the gateway retries it. Inspect `provisioning` in JSON output for the active `phase`, `deadline`, original `preparation_deadline`, `admission_start_time`, and cleanup timestamps. TUI NOTES identifies preparation timeout and distinguishes pending cleanup from reclaimed compute.
For `ImagePreparationTimedOut`, inspect image preparation and supervisor startup diagnostics and check whether the configured preparation budget is sufficient. For `ProvisioningTimedOut`, repair the rejected configuration. In either case, wait for cleanup to complete, then explicitly restart:
```shell
openshell sandbox get my-sandbox --output json
openshell sandbox start my-sandbox
```
Editing configuration after expiry does not restart compute. A retry gets a new
300-second window, while static-policy restrictions from any previous activation
remain in force. Timed-out records are retained even for ephemeral creates; use
`sandbox delete` when you no longer need the diagnostic or stored state.
Editing configuration after expiry does not restart compute. An explicit retry gets a new preparation deadline and a separate admission repair window, while static-policy restrictions from any previous activation remain in force. Attempts already active when the gateway is upgraded retain their stored deadline. Timed-out records are retained even for ephemeral creates; use `sandbox delete` when you no longer need the diagnostic or stored state.
| Phase | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+10 -2
View File
@@ -1184,7 +1184,7 @@ message SandboxStatus {
SandboxConfigurationAdmission configuration_admission = 11;
// Durable first-acceptance marker. Absent on legacy records; never reset by restart.
optional bool configuration_activated = 12;
// Gateway-owned repair window. Retained after timeout for inspection and retry.
// Gateway-owned provisioning deadlines, retained after timeout for inspection and retry.
SandboxProvisioning provisioning = 13;
// Consecutive policy-driven restart number in the current crash loop.
uint32 restart_count = 14;
@@ -3769,7 +3769,7 @@ message SandboxProvisioning {
string configuration_change_id = 2;
google.protobuf.Timestamp configuration_change_time = 3;
google.protobuf.Timestamp first_rejection_time = 4;
// Present only while the repair window is armed.
// Active preparation or admission-repair deadline. Absent after Ready/timeout.
google.protobuf.Timestamp deadline = 5;
google.protobuf.Timestamp timeout_time = 6;
// Set only after both supervisor and workload compute have been reclaimed.
@@ -3781,6 +3781,14 @@ message SandboxProvisioning {
// Attachment edits have their own durable clock; status writes do not change it.
string attachment_change_id = 10;
google.protobuf.Timestamp attachment_change_time = 11;
// Absolute ceiling for image preparation and initial supervisor startup.
// Set once per new attempt; progress, configuration writes, and restarts
// cannot extend it. Absent on attempts created before preparation timing.
google.protobuf.Timestamp preparation_deadline = 12;
// First authenticated supervisor configuration report for this attempt.
// Starts the admission repair window. Absent while preparing, including
// after a preparation timeout. Duplicate reports never change this value.
google.protobuf.Timestamp admission_start_time = 13;
}
// Create-time request to expose one loopback HTTP service in a sandbox.
+206 -180
View File
@@ -3118,7 +3118,7 @@ type SandboxStatus struct {
ConfigurationAdmission *SandboxConfigurationAdmission `protobuf:"bytes,11,opt,name=configuration_admission,json=configurationAdmission,proto3" json:"configuration_admission,omitempty"`
// Durable first-acceptance marker. Absent on legacy records; never reset by restart.
ConfigurationActivated *bool `protobuf:"varint,12,opt,name=configuration_activated,json=configurationActivated,proto3,oneof" json:"configuration_activated,omitempty"`
// Gateway-owned repair window. Retained after timeout for inspection and retry.
// Gateway-owned provisioning deadlines, retained after timeout for inspection and retry.
Provisioning *SandboxProvisioning `protobuf:"bytes,13,opt,name=provisioning,proto3" json:"provisioning,omitempty"`
// Consecutive policy-driven restart number in the current crash loop.
RestartCount uint32 `protobuf:"varint,14,opt,name=restart_count,json=restartCount,proto3" json:"restart_count,omitempty"`
@@ -17637,7 +17637,7 @@ type SandboxProvisioning struct {
ConfigurationChangeId string `protobuf:"bytes,2,opt,name=configuration_change_id,json=configurationChangeId,proto3" json:"configuration_change_id,omitempty"`
ConfigurationChangeTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=configuration_change_time,json=configurationChangeTime,proto3" json:"configuration_change_time,omitempty"`
FirstRejectionTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=first_rejection_time,json=firstRejectionTime,proto3" json:"first_rejection_time,omitempty"`
// Present only while the repair window is armed.
// Active preparation or admission-repair deadline. Absent after Ready/timeout.
Deadline *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=deadline,proto3" json:"deadline,omitempty"`
TimeoutTime *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=timeout_time,json=timeoutTime,proto3" json:"timeout_time,omitempty"`
// Set only after both supervisor and workload compute have been reclaimed.
@@ -17649,8 +17649,16 @@ type SandboxProvisioning struct {
// Attachment edits have their own durable clock; status writes do not change it.
AttachmentChangeId string `protobuf:"bytes,10,opt,name=attachment_change_id,json=attachmentChangeId,proto3" json:"attachment_change_id,omitempty"`
AttachmentChangeTime *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=attachment_change_time,json=attachmentChangeTime,proto3" json:"attachment_change_time,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
// Absolute ceiling for image preparation and initial supervisor startup.
// Set once per new attempt; progress, configuration writes, and restarts
// cannot extend it. Absent on attempts created before preparation timing.
PreparationDeadline *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=preparation_deadline,json=preparationDeadline,proto3" json:"preparation_deadline,omitempty"`
// First authenticated supervisor configuration report for this attempt.
// Starts the admission repair window. Absent while preparing, including
// after a preparation timeout. Duplicate reports never change this value.
AdmissionStartTime *timestamppb.Timestamp `protobuf:"bytes,13,opt,name=admission_start_time,json=admissionStartTime,proto3" json:"admission_start_time,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SandboxProvisioning) Reset() {
@@ -17760,6 +17768,20 @@ func (x *SandboxProvisioning) GetAttachmentChangeTime() *timestamppb.Timestamp {
return nil
}
func (x *SandboxProvisioning) GetPreparationDeadline() *timestamppb.Timestamp {
if x != nil {
return x.PreparationDeadline
}
return nil
}
func (x *SandboxProvisioning) GetAdmissionStartTime() *timestamppb.Timestamp {
if x != nil {
return x.AdmissionStartTime
}
return nil
}
// Create-time request to expose one loopback HTTP service in a sandbox.
type SandboxServiceExposure struct {
state protoimpl.MessageState `protogen:"open.v1"`
@@ -19141,7 +19163,7 @@ const file_openshell_proto_rawDesc = "" +
"\x04path\x18\x04 \x01(\tR\x04path\x12=\n" +
"\vlast_result\x18\x05 \x01(\x0e2\x1c.openshell.v1.EndpointResultR\n" +
"lastResult\x12H\n" +
"\x12last_reported_time\x18j \x01(\v2\x1a.google.protobuf.TimestampR\x10lastReportedTimeJ\x04\b\x06\x10\aR\x10last_reported_at\"\xce\x05\n" +
"\x12last_reported_time\x18j \x01(\v2\x1a.google.protobuf.TimestampR\x10lastReportedTimeJ\x04\b\x06\x10\aR\x10last_reported_at\"\xeb\x06\n" +
"\x13SandboxProvisioning\x12\x1d\n" +
"\n" +
"attempt_id\x18\x01 \x01(\tR\tattemptId\x126\n" +
@@ -19155,7 +19177,9 @@ const file_openshell_proto_rawDesc = "" +
"\x12cleanup_retry_time\x18\t \x01(\v2\x1a.google.protobuf.TimestampR\x10cleanupRetryTime\x120\n" +
"\x14attachment_change_id\x18\n" +
" \x01(\tR\x12attachmentChangeId\x12P\n" +
"\x16attachment_change_time\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\x14attachmentChangeTime\"\xaa\x01\n" +
"\x16attachment_change_time\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\x14attachmentChangeTime\x12M\n" +
"\x14preparation_deadline\x18\f \x01(\v2\x1a.google.protobuf.TimestampR\x13preparationDeadline\x12L\n" +
"\x14admission_start_time\x18\r \x01(\v2\x1a.google.protobuf.TimestampR\x12admissionStartTime\"\xaa\x01\n" +
"\x16SandboxServiceExposure\x12\x18\n" +
"\aservice\x18\x01 \x01(\tR\aservice\x12\x1f\n" +
"\vtarget_port\x18\x02 \x01(\rR\n" +
@@ -20108,180 +20132,182 @@ var file_openshell_proto_depIdxs = []int32{
275, // 316: openshell.v1.SandboxProvisioning.cleanup_completed_time:type_name -> google.protobuf.Timestamp
275, // 317: openshell.v1.SandboxProvisioning.cleanup_retry_time:type_name -> google.protobuf.Timestamp
275, // 318: openshell.v1.SandboxProvisioning.attachment_change_time:type_name -> google.protobuf.Timestamp
19, // 319: openshell.v1.SandboxServiceExposure.authorization_mode:type_name -> openshell.v1.ServiceAuthorizationMode
275, // 320: openshell.v1.UpdateProviderRequest.CredentialExpirationTimesEntry.value:type_name -> google.protobuf.Timestamp
275, // 321: openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpirationTimesEntry.value:type_name -> google.protobuf.Timestamp
127, // 322: openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry.value:type_name -> openshell.v1.ProviderProfileCredential
156, // 323: openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry.value:type_name -> openshell.v1.StaticCredentialBinding
24, // 324: openshell.v1.OpenShell.Health:input_type -> openshell.v1.HealthRequest
26, // 325: openshell.v1.OpenShell.GetCurrentUser:input_type -> openshell.v1.GetCurrentUserRequest
28, // 326: openshell.v1.OpenShell.GetGatewayInfo:input_type -> openshell.v1.GetGatewayInfoRequest
52, // 327: openshell.v1.OpenShell.CreateSandbox:input_type -> openshell.v1.CreateSandboxRequest
60, // 328: openshell.v1.OpenShell.BeginRootfsTarStaging:input_type -> openshell.v1.BeginRootfsTarStagingRequest
62, // 329: openshell.v1.OpenShell.GetSandbox:input_type -> openshell.v1.GetSandboxRequest
63, // 330: openshell.v1.OpenShell.ListSandboxes:input_type -> openshell.v1.ListSandboxesRequest
53, // 331: openshell.v1.OpenShell.CreateSandboxTemplate:input_type -> openshell.v1.CreateSandboxTemplateRequest
54, // 332: openshell.v1.OpenShell.GetSandboxTemplate:input_type -> openshell.v1.GetSandboxTemplateRequest
55, // 333: openshell.v1.OpenShell.ListSandboxTemplates:input_type -> openshell.v1.ListSandboxTemplatesRequest
56, // 334: openshell.v1.OpenShell.DeleteSandboxTemplate:input_type -> openshell.v1.DeleteSandboxTemplateRequest
64, // 335: openshell.v1.OpenShell.ListSandboxProviders:input_type -> openshell.v1.ListSandboxProvidersRequest
65, // 336: openshell.v1.OpenShell.AttachSandboxProvider:input_type -> openshell.v1.AttachSandboxProviderRequest
66, // 337: openshell.v1.OpenShell.DetachSandboxProvider:input_type -> openshell.v1.DetachSandboxProviderRequest
82, // 338: openshell.v1.OpenShell.GetSandboxProviderStatus:input_type -> openshell.v1.GetSandboxProviderStatusRequest
67, // 339: openshell.v1.OpenShell.DeleteSandbox:input_type -> openshell.v1.DeleteSandboxRequest
68, // 340: openshell.v1.OpenShell.StopSandbox:input_type -> openshell.v1.StopSandboxRequest
69, // 341: openshell.v1.OpenShell.StartSandbox:input_type -> openshell.v1.StartSandboxRequest
87, // 342: openshell.v1.OpenShell.CreateSshSession:input_type -> openshell.v1.CreateSshSessionRequest
89, // 343: openshell.v1.OpenShell.ExposeService:input_type -> openshell.v1.ExposeServiceRequest
90, // 344: openshell.v1.OpenShell.GetService:input_type -> openshell.v1.GetServiceRequest
91, // 345: openshell.v1.OpenShell.ListServices:input_type -> openshell.v1.ListServicesRequest
93, // 346: openshell.v1.OpenShell.DeleteService:input_type -> openshell.v1.DeleteServiceRequest
97, // 347: openshell.v1.OpenShell.RevokeSshSession:input_type -> openshell.v1.RevokeSshSessionRequest
99, // 348: openshell.v1.OpenShell.ExecSandbox:input_type -> openshell.v1.ExecSandboxRequest
105, // 349: openshell.v1.OpenShell.ForwardTcp:input_type -> openshell.v1.TcpForwardFrame
106, // 350: openshell.v1.OpenShell.ExecSandboxInteractive:input_type -> openshell.v1.ExecSandboxInput
113, // 351: openshell.v1.OpenShell.CreateProvider:input_type -> openshell.v1.CreateProviderRequest
114, // 352: openshell.v1.OpenShell.GetProvider:input_type -> openshell.v1.GetProviderRequest
115, // 353: openshell.v1.OpenShell.ListProviders:input_type -> openshell.v1.ListProvidersRequest
120, // 354: openshell.v1.OpenShell.ListProviderProfiles:input_type -> openshell.v1.ListProviderProfilesRequest
121, // 355: openshell.v1.OpenShell.GetProviderProfile:input_type -> openshell.v1.GetProviderProfileRequest
145, // 356: openshell.v1.OpenShell.ImportProviderProfiles:input_type -> openshell.v1.ImportProviderProfilesRequest
147, // 357: openshell.v1.OpenShell.UpdateProviderProfiles:input_type -> openshell.v1.UpdateProviderProfilesRequest
149, // 358: openshell.v1.OpenShell.LintProviderProfiles:input_type -> openshell.v1.LintProviderProfilesRequest
116, // 359: openshell.v1.OpenShell.UpdateProvider:input_type -> openshell.v1.UpdateProviderRequest
133, // 360: openshell.v1.OpenShell.GetProviderRefreshStatus:input_type -> openshell.v1.GetProviderRefreshStatusRequest
135, // 361: openshell.v1.OpenShell.ConfigureProviderRefresh:input_type -> openshell.v1.ConfigureProviderRefreshRequest
137, // 362: openshell.v1.OpenShell.RotateProviderCredential:input_type -> openshell.v1.RotateProviderCredentialRequest
139, // 363: openshell.v1.OpenShell.DeleteProviderRefresh:input_type -> openshell.v1.DeleteProviderRefreshRequest
117, // 364: openshell.v1.OpenShell.DeleteProvider:input_type -> openshell.v1.DeleteProviderRequest
152, // 365: openshell.v1.OpenShell.DeleteProviderProfile:input_type -> openshell.v1.DeleteProviderProfileRequest
290, // 366: openshell.v1.OpenShell.GetSandboxConfig:input_type -> openshell.sandbox.v1.GetSandboxConfigRequest
291, // 367: openshell.v1.OpenShell.GetGatewayConfig:input_type -> openshell.sandbox.v1.GetGatewayConfigRequest
160, // 368: openshell.v1.OpenShell.UpdateConfig:input_type -> openshell.v1.UpdateConfigRequest
170, // 369: openshell.v1.OpenShell.GetSandboxPolicyStatus:input_type -> openshell.v1.GetSandboxPolicyStatusRequest
172, // 370: openshell.v1.OpenShell.ListSandboxPolicies:input_type -> openshell.v1.ListSandboxPoliciesRequest
174, // 371: openshell.v1.OpenShell.ReportPolicyStatus:input_type -> openshell.v1.ReportPolicyStatusRequest
247, // 372: openshell.v1.OpenShell.ReportEndpointStatus:input_type -> openshell.v1.ReportEndpointStatusRequest
84, // 373: openshell.v1.OpenShell.ReportProviderReadiness:input_type -> openshell.v1.ReportProviderReadinessRequest
177, // 374: openshell.v1.OpenShell.ReportSandboxConfiguration:input_type -> openshell.v1.ReportSandboxConfigurationRequest
154, // 375: openshell.v1.OpenShell.GetSandboxProviderEnvironment:input_type -> openshell.v1.GetSandboxProviderEnvironmentRequest
158, // 376: openshell.v1.OpenShell.ExchangeProviderSubjectToken:input_type -> openshell.v1.ExchangeProviderSubjectTokenRequest
180, // 377: openshell.v1.OpenShell.GetSandboxLogs:input_type -> openshell.v1.GetSandboxLogsRequest
181, // 378: openshell.v1.OpenShell.PushSandboxLogs:input_type -> openshell.v1.PushSandboxLogsRequest
184, // 379: openshell.v1.OpenShell.ConnectSupervisor:input_type -> openshell.v1.SupervisorMessage
191, // 380: openshell.v1.OpenShell.ReportMainProcessExit:input_type -> openshell.v1.ReportMainProcessExitRequest
193, // 381: openshell.v1.OpenShell.FinalizeMainProcessExit:input_type -> openshell.v1.FinalizeMainProcessExitRequest
199, // 382: openshell.v1.OpenShell.RelayStream:input_type -> openshell.v1.RelayFrame
201, // 383: openshell.v1.OpenShell.PeerRelay:input_type -> openshell.v1.PeerRelayFrame
84, // 384: openshell.v1.OpenShell.PeerReportProviderReadiness:input_type -> openshell.v1.ReportProviderReadinessRequest
247, // 385: openshell.v1.OpenShell.PeerReportEndpointStatus:input_type -> openshell.v1.ReportEndpointStatusRequest
82, // 386: openshell.v1.OpenShell.PeerGetSandboxProviderStatus:input_type -> openshell.v1.GetSandboxProviderStatusRequest
109, // 387: openshell.v1.OpenShell.WatchSandbox:input_type -> openshell.v1.WatchSandboxRequest
210, // 388: openshell.v1.OpenShell.SubmitPolicyAnalysis:input_type -> openshell.v1.SubmitPolicyAnalysisRequest
212, // 389: openshell.v1.OpenShell.GetDraftPolicy:input_type -> openshell.v1.GetDraftPolicyRequest
214, // 390: openshell.v1.OpenShell.ApproveDraftChunk:input_type -> openshell.v1.ApproveDraftChunkRequest
216, // 391: openshell.v1.OpenShell.RejectDraftChunk:input_type -> openshell.v1.RejectDraftChunkRequest
219, // 392: openshell.v1.OpenShell.ApproveAllDraftChunks:input_type -> openshell.v1.ApproveAllDraftChunksRequest
221, // 393: openshell.v1.OpenShell.EditDraftChunk:input_type -> openshell.v1.EditDraftChunkRequest
223, // 394: openshell.v1.OpenShell.UndoDraftChunk:input_type -> openshell.v1.UndoDraftChunkRequest
225, // 395: openshell.v1.OpenShell.ClearDraftChunks:input_type -> openshell.v1.ClearDraftChunksRequest
227, // 396: openshell.v1.OpenShell.GetDraftHistory:input_type -> openshell.v1.GetDraftHistoryRequest
20, // 397: openshell.v1.OpenShell.IssueSandboxToken:input_type -> openshell.v1.IssueSandboxTokenRequest
22, // 398: openshell.v1.OpenShell.RefreshSandboxToken:input_type -> openshell.v1.RefreshSandboxTokenRequest
230, // 399: openshell.v1.OpenShell.CreateWorkspace:input_type -> openshell.v1.CreateWorkspaceRequest
232, // 400: openshell.v1.OpenShell.GetWorkspace:input_type -> openshell.v1.GetWorkspaceRequest
234, // 401: openshell.v1.OpenShell.ListWorkspaces:input_type -> openshell.v1.ListWorkspacesRequest
236, // 402: openshell.v1.OpenShell.DeleteWorkspace:input_type -> openshell.v1.DeleteWorkspaceRequest
239, // 403: openshell.v1.OpenShell.AddWorkspaceMember:input_type -> openshell.v1.AddWorkspaceMemberRequest
241, // 404: openshell.v1.OpenShell.RemoveWorkspaceMember:input_type -> openshell.v1.RemoveWorkspaceMemberRequest
243, // 405: openshell.v1.OpenShell.ListWorkspaceMembers:input_type -> openshell.v1.ListWorkspaceMembersRequest
25, // 406: openshell.v1.OpenShell.Health:output_type -> openshell.v1.HealthResponse
27, // 407: openshell.v1.OpenShell.GetCurrentUser:output_type -> openshell.v1.GetCurrentUserResponse
29, // 408: openshell.v1.OpenShell.GetGatewayInfo:output_type -> openshell.v1.GetGatewayInfoResponse
70, // 409: openshell.v1.OpenShell.CreateSandbox:output_type -> openshell.v1.SandboxResponse
61, // 410: openshell.v1.OpenShell.BeginRootfsTarStaging:output_type -> openshell.v1.BeginRootfsTarStagingResponse
70, // 411: openshell.v1.OpenShell.GetSandbox:output_type -> openshell.v1.SandboxResponse
71, // 412: openshell.v1.OpenShell.ListSandboxes:output_type -> openshell.v1.ListSandboxesResponse
57, // 413: openshell.v1.OpenShell.CreateSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse
57, // 414: openshell.v1.OpenShell.GetSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse
58, // 415: openshell.v1.OpenShell.ListSandboxTemplates:output_type -> openshell.v1.ListSandboxTemplatesResponse
59, // 416: openshell.v1.OpenShell.DeleteSandboxTemplate:output_type -> openshell.v1.DeleteSandboxTemplateResponse
72, // 417: openshell.v1.OpenShell.ListSandboxProviders:output_type -> openshell.v1.ListSandboxProvidersResponse
73, // 418: openshell.v1.OpenShell.AttachSandboxProvider:output_type -> openshell.v1.AttachSandboxProviderResponse
74, // 419: openshell.v1.OpenShell.DetachSandboxProvider:output_type -> openshell.v1.DetachSandboxProviderResponse
83, // 420: openshell.v1.OpenShell.GetSandboxProviderStatus:output_type -> openshell.v1.GetSandboxProviderStatusResponse
86, // 421: openshell.v1.OpenShell.DeleteSandbox:output_type -> openshell.v1.DeleteSandboxResponse
70, // 422: openshell.v1.OpenShell.StopSandbox:output_type -> openshell.v1.SandboxResponse
70, // 423: openshell.v1.OpenShell.StartSandbox:output_type -> openshell.v1.SandboxResponse
88, // 424: openshell.v1.OpenShell.CreateSshSession:output_type -> openshell.v1.CreateSshSessionResponse
96, // 425: openshell.v1.OpenShell.ExposeService:output_type -> openshell.v1.ServiceEndpointResponse
96, // 426: openshell.v1.OpenShell.GetService:output_type -> openshell.v1.ServiceEndpointResponse
92, // 427: openshell.v1.OpenShell.ListServices:output_type -> openshell.v1.ListServicesResponse
94, // 428: openshell.v1.OpenShell.DeleteService:output_type -> openshell.v1.DeleteServiceResponse
98, // 429: openshell.v1.OpenShell.RevokeSshSession:output_type -> openshell.v1.RevokeSshSessionResponse
103, // 430: openshell.v1.OpenShell.ExecSandbox:output_type -> openshell.v1.ExecSandboxEvent
105, // 431: openshell.v1.OpenShell.ForwardTcp:output_type -> openshell.v1.TcpForwardFrame
103, // 432: openshell.v1.OpenShell.ExecSandboxInteractive:output_type -> openshell.v1.ExecSandboxEvent
118, // 433: openshell.v1.OpenShell.CreateProvider:output_type -> openshell.v1.ProviderResponse
118, // 434: openshell.v1.OpenShell.GetProvider:output_type -> openshell.v1.ProviderResponse
119, // 435: openshell.v1.OpenShell.ListProviders:output_type -> openshell.v1.ListProvidersResponse
144, // 436: openshell.v1.OpenShell.ListProviderProfiles:output_type -> openshell.v1.ListProviderProfilesResponse
143, // 437: openshell.v1.OpenShell.GetProviderProfile:output_type -> openshell.v1.ProviderProfileResponse
146, // 438: openshell.v1.OpenShell.ImportProviderProfiles:output_type -> openshell.v1.ImportProviderProfilesResponse
148, // 439: openshell.v1.OpenShell.UpdateProviderProfiles:output_type -> openshell.v1.UpdateProviderProfilesResponse
150, // 440: openshell.v1.OpenShell.LintProviderProfiles:output_type -> openshell.v1.LintProviderProfilesResponse
118, // 441: openshell.v1.OpenShell.UpdateProvider:output_type -> openshell.v1.ProviderResponse
134, // 442: openshell.v1.OpenShell.GetProviderRefreshStatus:output_type -> openshell.v1.GetProviderRefreshStatusResponse
136, // 443: openshell.v1.OpenShell.ConfigureProviderRefresh:output_type -> openshell.v1.ConfigureProviderRefreshResponse
138, // 444: openshell.v1.OpenShell.RotateProviderCredential:output_type -> openshell.v1.RotateProviderCredentialResponse
140, // 445: openshell.v1.OpenShell.DeleteProviderRefresh:output_type -> openshell.v1.DeleteProviderRefreshResponse
151, // 446: openshell.v1.OpenShell.DeleteProvider:output_type -> openshell.v1.DeleteProviderResponse
153, // 447: openshell.v1.OpenShell.DeleteProviderProfile:output_type -> openshell.v1.DeleteProviderProfileResponse
292, // 448: openshell.v1.OpenShell.GetSandboxConfig:output_type -> openshell.sandbox.v1.GetSandboxConfigResponse
293, // 449: openshell.v1.OpenShell.GetGatewayConfig:output_type -> openshell.sandbox.v1.GetGatewayConfigResponse
169, // 450: openshell.v1.OpenShell.UpdateConfig:output_type -> openshell.v1.UpdateConfigResponse
171, // 451: openshell.v1.OpenShell.GetSandboxPolicyStatus:output_type -> openshell.v1.GetSandboxPolicyStatusResponse
173, // 452: openshell.v1.OpenShell.ListSandboxPolicies:output_type -> openshell.v1.ListSandboxPoliciesResponse
175, // 453: openshell.v1.OpenShell.ReportPolicyStatus:output_type -> openshell.v1.ReportPolicyStatusResponse
248, // 454: openshell.v1.OpenShell.ReportEndpointStatus:output_type -> openshell.v1.ReportEndpointStatusResponse
85, // 455: openshell.v1.OpenShell.ReportProviderReadiness:output_type -> openshell.v1.ReportProviderReadinessResponse
178, // 456: openshell.v1.OpenShell.ReportSandboxConfiguration:output_type -> openshell.v1.ReportSandboxConfigurationResponse
157, // 457: openshell.v1.OpenShell.GetSandboxProviderEnvironment:output_type -> openshell.v1.GetSandboxProviderEnvironmentResponse
159, // 458: openshell.v1.OpenShell.ExchangeProviderSubjectToken:output_type -> openshell.v1.ExchangeProviderSubjectTokenResponse
183, // 459: openshell.v1.OpenShell.GetSandboxLogs:output_type -> openshell.v1.GetSandboxLogsResponse
182, // 460: openshell.v1.OpenShell.PushSandboxLogs:output_type -> openshell.v1.PushSandboxLogsResponse
185, // 461: openshell.v1.OpenShell.ConnectSupervisor:output_type -> openshell.v1.GatewayMessage
192, // 462: openshell.v1.OpenShell.ReportMainProcessExit:output_type -> openshell.v1.ReportMainProcessExitResponse
194, // 463: openshell.v1.OpenShell.FinalizeMainProcessExit:output_type -> openshell.v1.FinalizeMainProcessExitResponse
199, // 464: openshell.v1.OpenShell.RelayStream:output_type -> openshell.v1.RelayFrame
201, // 465: openshell.v1.OpenShell.PeerRelay:output_type -> openshell.v1.PeerRelayFrame
85, // 466: openshell.v1.OpenShell.PeerReportProviderReadiness:output_type -> openshell.v1.ReportProviderReadinessResponse
248, // 467: openshell.v1.OpenShell.PeerReportEndpointStatus:output_type -> openshell.v1.ReportEndpointStatusResponse
83, // 468: openshell.v1.OpenShell.PeerGetSandboxProviderStatus:output_type -> openshell.v1.GetSandboxProviderStatusResponse
110, // 469: openshell.v1.OpenShell.WatchSandbox:output_type -> openshell.v1.SandboxStreamEvent
211, // 470: openshell.v1.OpenShell.SubmitPolicyAnalysis:output_type -> openshell.v1.SubmitPolicyAnalysisResponse
213, // 471: openshell.v1.OpenShell.GetDraftPolicy:output_type -> openshell.v1.GetDraftPolicyResponse
215, // 472: openshell.v1.OpenShell.ApproveDraftChunk:output_type -> openshell.v1.ApproveDraftChunkResponse
217, // 473: openshell.v1.OpenShell.RejectDraftChunk:output_type -> openshell.v1.RejectDraftChunkResponse
220, // 474: openshell.v1.OpenShell.ApproveAllDraftChunks:output_type -> openshell.v1.ApproveAllDraftChunksResponse
222, // 475: openshell.v1.OpenShell.EditDraftChunk:output_type -> openshell.v1.EditDraftChunkResponse
224, // 476: openshell.v1.OpenShell.UndoDraftChunk:output_type -> openshell.v1.UndoDraftChunkResponse
226, // 477: openshell.v1.OpenShell.ClearDraftChunks:output_type -> openshell.v1.ClearDraftChunksResponse
229, // 478: openshell.v1.OpenShell.GetDraftHistory:output_type -> openshell.v1.GetDraftHistoryResponse
21, // 479: openshell.v1.OpenShell.IssueSandboxToken:output_type -> openshell.v1.IssueSandboxTokenResponse
23, // 480: openshell.v1.OpenShell.RefreshSandboxToken:output_type -> openshell.v1.RefreshSandboxTokenResponse
231, // 481: openshell.v1.OpenShell.CreateWorkspace:output_type -> openshell.v1.CreateWorkspaceResponse
233, // 482: openshell.v1.OpenShell.GetWorkspace:output_type -> openshell.v1.GetWorkspaceResponse
235, // 483: openshell.v1.OpenShell.ListWorkspaces:output_type -> openshell.v1.ListWorkspacesResponse
237, // 484: openshell.v1.OpenShell.DeleteWorkspace:output_type -> openshell.v1.DeleteWorkspaceResponse
240, // 485: openshell.v1.OpenShell.AddWorkspaceMember:output_type -> openshell.v1.AddWorkspaceMemberResponse
242, // 486: openshell.v1.OpenShell.RemoveWorkspaceMember:output_type -> openshell.v1.RemoveWorkspaceMemberResponse
244, // 487: openshell.v1.OpenShell.ListWorkspaceMembers:output_type -> openshell.v1.ListWorkspaceMembersResponse
406, // [406:488] is the sub-list for method output_type
324, // [324:406] is the sub-list for method input_type
324, // [324:324] is the sub-list for extension type_name
324, // [324:324] is the sub-list for extension extendee
0, // [0:324] is the sub-list for field type_name
275, // 319: openshell.v1.SandboxProvisioning.preparation_deadline:type_name -> google.protobuf.Timestamp
275, // 320: openshell.v1.SandboxProvisioning.admission_start_time:type_name -> google.protobuf.Timestamp
19, // 321: openshell.v1.SandboxServiceExposure.authorization_mode:type_name -> openshell.v1.ServiceAuthorizationMode
275, // 322: openshell.v1.UpdateProviderRequest.CredentialExpirationTimesEntry.value:type_name -> google.protobuf.Timestamp
275, // 323: openshell.v1.GetSandboxProviderEnvironmentResponse.CredentialExpirationTimesEntry.value:type_name -> google.protobuf.Timestamp
127, // 324: openshell.v1.GetSandboxProviderEnvironmentResponse.DynamicCredentialsEntry.value:type_name -> openshell.v1.ProviderProfileCredential
156, // 325: openshell.v1.GetSandboxProviderEnvironmentResponse.StaticCredentialBindingsEntry.value:type_name -> openshell.v1.StaticCredentialBinding
24, // 326: openshell.v1.OpenShell.Health:input_type -> openshell.v1.HealthRequest
26, // 327: openshell.v1.OpenShell.GetCurrentUser:input_type -> openshell.v1.GetCurrentUserRequest
28, // 328: openshell.v1.OpenShell.GetGatewayInfo:input_type -> openshell.v1.GetGatewayInfoRequest
52, // 329: openshell.v1.OpenShell.CreateSandbox:input_type -> openshell.v1.CreateSandboxRequest
60, // 330: openshell.v1.OpenShell.BeginRootfsTarStaging:input_type -> openshell.v1.BeginRootfsTarStagingRequest
62, // 331: openshell.v1.OpenShell.GetSandbox:input_type -> openshell.v1.GetSandboxRequest
63, // 332: openshell.v1.OpenShell.ListSandboxes:input_type -> openshell.v1.ListSandboxesRequest
53, // 333: openshell.v1.OpenShell.CreateSandboxTemplate:input_type -> openshell.v1.CreateSandboxTemplateRequest
54, // 334: openshell.v1.OpenShell.GetSandboxTemplate:input_type -> openshell.v1.GetSandboxTemplateRequest
55, // 335: openshell.v1.OpenShell.ListSandboxTemplates:input_type -> openshell.v1.ListSandboxTemplatesRequest
56, // 336: openshell.v1.OpenShell.DeleteSandboxTemplate:input_type -> openshell.v1.DeleteSandboxTemplateRequest
64, // 337: openshell.v1.OpenShell.ListSandboxProviders:input_type -> openshell.v1.ListSandboxProvidersRequest
65, // 338: openshell.v1.OpenShell.AttachSandboxProvider:input_type -> openshell.v1.AttachSandboxProviderRequest
66, // 339: openshell.v1.OpenShell.DetachSandboxProvider:input_type -> openshell.v1.DetachSandboxProviderRequest
82, // 340: openshell.v1.OpenShell.GetSandboxProviderStatus:input_type -> openshell.v1.GetSandboxProviderStatusRequest
67, // 341: openshell.v1.OpenShell.DeleteSandbox:input_type -> openshell.v1.DeleteSandboxRequest
68, // 342: openshell.v1.OpenShell.StopSandbox:input_type -> openshell.v1.StopSandboxRequest
69, // 343: openshell.v1.OpenShell.StartSandbox:input_type -> openshell.v1.StartSandboxRequest
87, // 344: openshell.v1.OpenShell.CreateSshSession:input_type -> openshell.v1.CreateSshSessionRequest
89, // 345: openshell.v1.OpenShell.ExposeService:input_type -> openshell.v1.ExposeServiceRequest
90, // 346: openshell.v1.OpenShell.GetService:input_type -> openshell.v1.GetServiceRequest
91, // 347: openshell.v1.OpenShell.ListServices:input_type -> openshell.v1.ListServicesRequest
93, // 348: openshell.v1.OpenShell.DeleteService:input_type -> openshell.v1.DeleteServiceRequest
97, // 349: openshell.v1.OpenShell.RevokeSshSession:input_type -> openshell.v1.RevokeSshSessionRequest
99, // 350: openshell.v1.OpenShell.ExecSandbox:input_type -> openshell.v1.ExecSandboxRequest
105, // 351: openshell.v1.OpenShell.ForwardTcp:input_type -> openshell.v1.TcpForwardFrame
106, // 352: openshell.v1.OpenShell.ExecSandboxInteractive:input_type -> openshell.v1.ExecSandboxInput
113, // 353: openshell.v1.OpenShell.CreateProvider:input_type -> openshell.v1.CreateProviderRequest
114, // 354: openshell.v1.OpenShell.GetProvider:input_type -> openshell.v1.GetProviderRequest
115, // 355: openshell.v1.OpenShell.ListProviders:input_type -> openshell.v1.ListProvidersRequest
120, // 356: openshell.v1.OpenShell.ListProviderProfiles:input_type -> openshell.v1.ListProviderProfilesRequest
121, // 357: openshell.v1.OpenShell.GetProviderProfile:input_type -> openshell.v1.GetProviderProfileRequest
145, // 358: openshell.v1.OpenShell.ImportProviderProfiles:input_type -> openshell.v1.ImportProviderProfilesRequest
147, // 359: openshell.v1.OpenShell.UpdateProviderProfiles:input_type -> openshell.v1.UpdateProviderProfilesRequest
149, // 360: openshell.v1.OpenShell.LintProviderProfiles:input_type -> openshell.v1.LintProviderProfilesRequest
116, // 361: openshell.v1.OpenShell.UpdateProvider:input_type -> openshell.v1.UpdateProviderRequest
133, // 362: openshell.v1.OpenShell.GetProviderRefreshStatus:input_type -> openshell.v1.GetProviderRefreshStatusRequest
135, // 363: openshell.v1.OpenShell.ConfigureProviderRefresh:input_type -> openshell.v1.ConfigureProviderRefreshRequest
137, // 364: openshell.v1.OpenShell.RotateProviderCredential:input_type -> openshell.v1.RotateProviderCredentialRequest
139, // 365: openshell.v1.OpenShell.DeleteProviderRefresh:input_type -> openshell.v1.DeleteProviderRefreshRequest
117, // 366: openshell.v1.OpenShell.DeleteProvider:input_type -> openshell.v1.DeleteProviderRequest
152, // 367: openshell.v1.OpenShell.DeleteProviderProfile:input_type -> openshell.v1.DeleteProviderProfileRequest
290, // 368: openshell.v1.OpenShell.GetSandboxConfig:input_type -> openshell.sandbox.v1.GetSandboxConfigRequest
291, // 369: openshell.v1.OpenShell.GetGatewayConfig:input_type -> openshell.sandbox.v1.GetGatewayConfigRequest
160, // 370: openshell.v1.OpenShell.UpdateConfig:input_type -> openshell.v1.UpdateConfigRequest
170, // 371: openshell.v1.OpenShell.GetSandboxPolicyStatus:input_type -> openshell.v1.GetSandboxPolicyStatusRequest
172, // 372: openshell.v1.OpenShell.ListSandboxPolicies:input_type -> openshell.v1.ListSandboxPoliciesRequest
174, // 373: openshell.v1.OpenShell.ReportPolicyStatus:input_type -> openshell.v1.ReportPolicyStatusRequest
247, // 374: openshell.v1.OpenShell.ReportEndpointStatus:input_type -> openshell.v1.ReportEndpointStatusRequest
84, // 375: openshell.v1.OpenShell.ReportProviderReadiness:input_type -> openshell.v1.ReportProviderReadinessRequest
177, // 376: openshell.v1.OpenShell.ReportSandboxConfiguration:input_type -> openshell.v1.ReportSandboxConfigurationRequest
154, // 377: openshell.v1.OpenShell.GetSandboxProviderEnvironment:input_type -> openshell.v1.GetSandboxProviderEnvironmentRequest
158, // 378: openshell.v1.OpenShell.ExchangeProviderSubjectToken:input_type -> openshell.v1.ExchangeProviderSubjectTokenRequest
180, // 379: openshell.v1.OpenShell.GetSandboxLogs:input_type -> openshell.v1.GetSandboxLogsRequest
181, // 380: openshell.v1.OpenShell.PushSandboxLogs:input_type -> openshell.v1.PushSandboxLogsRequest
184, // 381: openshell.v1.OpenShell.ConnectSupervisor:input_type -> openshell.v1.SupervisorMessage
191, // 382: openshell.v1.OpenShell.ReportMainProcessExit:input_type -> openshell.v1.ReportMainProcessExitRequest
193, // 383: openshell.v1.OpenShell.FinalizeMainProcessExit:input_type -> openshell.v1.FinalizeMainProcessExitRequest
199, // 384: openshell.v1.OpenShell.RelayStream:input_type -> openshell.v1.RelayFrame
201, // 385: openshell.v1.OpenShell.PeerRelay:input_type -> openshell.v1.PeerRelayFrame
84, // 386: openshell.v1.OpenShell.PeerReportProviderReadiness:input_type -> openshell.v1.ReportProviderReadinessRequest
247, // 387: openshell.v1.OpenShell.PeerReportEndpointStatus:input_type -> openshell.v1.ReportEndpointStatusRequest
82, // 388: openshell.v1.OpenShell.PeerGetSandboxProviderStatus:input_type -> openshell.v1.GetSandboxProviderStatusRequest
109, // 389: openshell.v1.OpenShell.WatchSandbox:input_type -> openshell.v1.WatchSandboxRequest
210, // 390: openshell.v1.OpenShell.SubmitPolicyAnalysis:input_type -> openshell.v1.SubmitPolicyAnalysisRequest
212, // 391: openshell.v1.OpenShell.GetDraftPolicy:input_type -> openshell.v1.GetDraftPolicyRequest
214, // 392: openshell.v1.OpenShell.ApproveDraftChunk:input_type -> openshell.v1.ApproveDraftChunkRequest
216, // 393: openshell.v1.OpenShell.RejectDraftChunk:input_type -> openshell.v1.RejectDraftChunkRequest
219, // 394: openshell.v1.OpenShell.ApproveAllDraftChunks:input_type -> openshell.v1.ApproveAllDraftChunksRequest
221, // 395: openshell.v1.OpenShell.EditDraftChunk:input_type -> openshell.v1.EditDraftChunkRequest
223, // 396: openshell.v1.OpenShell.UndoDraftChunk:input_type -> openshell.v1.UndoDraftChunkRequest
225, // 397: openshell.v1.OpenShell.ClearDraftChunks:input_type -> openshell.v1.ClearDraftChunksRequest
227, // 398: openshell.v1.OpenShell.GetDraftHistory:input_type -> openshell.v1.GetDraftHistoryRequest
20, // 399: openshell.v1.OpenShell.IssueSandboxToken:input_type -> openshell.v1.IssueSandboxTokenRequest
22, // 400: openshell.v1.OpenShell.RefreshSandboxToken:input_type -> openshell.v1.RefreshSandboxTokenRequest
230, // 401: openshell.v1.OpenShell.CreateWorkspace:input_type -> openshell.v1.CreateWorkspaceRequest
232, // 402: openshell.v1.OpenShell.GetWorkspace:input_type -> openshell.v1.GetWorkspaceRequest
234, // 403: openshell.v1.OpenShell.ListWorkspaces:input_type -> openshell.v1.ListWorkspacesRequest
236, // 404: openshell.v1.OpenShell.DeleteWorkspace:input_type -> openshell.v1.DeleteWorkspaceRequest
239, // 405: openshell.v1.OpenShell.AddWorkspaceMember:input_type -> openshell.v1.AddWorkspaceMemberRequest
241, // 406: openshell.v1.OpenShell.RemoveWorkspaceMember:input_type -> openshell.v1.RemoveWorkspaceMemberRequest
243, // 407: openshell.v1.OpenShell.ListWorkspaceMembers:input_type -> openshell.v1.ListWorkspaceMembersRequest
25, // 408: openshell.v1.OpenShell.Health:output_type -> openshell.v1.HealthResponse
27, // 409: openshell.v1.OpenShell.GetCurrentUser:output_type -> openshell.v1.GetCurrentUserResponse
29, // 410: openshell.v1.OpenShell.GetGatewayInfo:output_type -> openshell.v1.GetGatewayInfoResponse
70, // 411: openshell.v1.OpenShell.CreateSandbox:output_type -> openshell.v1.SandboxResponse
61, // 412: openshell.v1.OpenShell.BeginRootfsTarStaging:output_type -> openshell.v1.BeginRootfsTarStagingResponse
70, // 413: openshell.v1.OpenShell.GetSandbox:output_type -> openshell.v1.SandboxResponse
71, // 414: openshell.v1.OpenShell.ListSandboxes:output_type -> openshell.v1.ListSandboxesResponse
57, // 415: openshell.v1.OpenShell.CreateSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse
57, // 416: openshell.v1.OpenShell.GetSandboxTemplate:output_type -> openshell.v1.SandboxTemplateResponse
58, // 417: openshell.v1.OpenShell.ListSandboxTemplates:output_type -> openshell.v1.ListSandboxTemplatesResponse
59, // 418: openshell.v1.OpenShell.DeleteSandboxTemplate:output_type -> openshell.v1.DeleteSandboxTemplateResponse
72, // 419: openshell.v1.OpenShell.ListSandboxProviders:output_type -> openshell.v1.ListSandboxProvidersResponse
73, // 420: openshell.v1.OpenShell.AttachSandboxProvider:output_type -> openshell.v1.AttachSandboxProviderResponse
74, // 421: openshell.v1.OpenShell.DetachSandboxProvider:output_type -> openshell.v1.DetachSandboxProviderResponse
83, // 422: openshell.v1.OpenShell.GetSandboxProviderStatus:output_type -> openshell.v1.GetSandboxProviderStatusResponse
86, // 423: openshell.v1.OpenShell.DeleteSandbox:output_type -> openshell.v1.DeleteSandboxResponse
70, // 424: openshell.v1.OpenShell.StopSandbox:output_type -> openshell.v1.SandboxResponse
70, // 425: openshell.v1.OpenShell.StartSandbox:output_type -> openshell.v1.SandboxResponse
88, // 426: openshell.v1.OpenShell.CreateSshSession:output_type -> openshell.v1.CreateSshSessionResponse
96, // 427: openshell.v1.OpenShell.ExposeService:output_type -> openshell.v1.ServiceEndpointResponse
96, // 428: openshell.v1.OpenShell.GetService:output_type -> openshell.v1.ServiceEndpointResponse
92, // 429: openshell.v1.OpenShell.ListServices:output_type -> openshell.v1.ListServicesResponse
94, // 430: openshell.v1.OpenShell.DeleteService:output_type -> openshell.v1.DeleteServiceResponse
98, // 431: openshell.v1.OpenShell.RevokeSshSession:output_type -> openshell.v1.RevokeSshSessionResponse
103, // 432: openshell.v1.OpenShell.ExecSandbox:output_type -> openshell.v1.ExecSandboxEvent
105, // 433: openshell.v1.OpenShell.ForwardTcp:output_type -> openshell.v1.TcpForwardFrame
103, // 434: openshell.v1.OpenShell.ExecSandboxInteractive:output_type -> openshell.v1.ExecSandboxEvent
118, // 435: openshell.v1.OpenShell.CreateProvider:output_type -> openshell.v1.ProviderResponse
118, // 436: openshell.v1.OpenShell.GetProvider:output_type -> openshell.v1.ProviderResponse
119, // 437: openshell.v1.OpenShell.ListProviders:output_type -> openshell.v1.ListProvidersResponse
144, // 438: openshell.v1.OpenShell.ListProviderProfiles:output_type -> openshell.v1.ListProviderProfilesResponse
143, // 439: openshell.v1.OpenShell.GetProviderProfile:output_type -> openshell.v1.ProviderProfileResponse
146, // 440: openshell.v1.OpenShell.ImportProviderProfiles:output_type -> openshell.v1.ImportProviderProfilesResponse
148, // 441: openshell.v1.OpenShell.UpdateProviderProfiles:output_type -> openshell.v1.UpdateProviderProfilesResponse
150, // 442: openshell.v1.OpenShell.LintProviderProfiles:output_type -> openshell.v1.LintProviderProfilesResponse
118, // 443: openshell.v1.OpenShell.UpdateProvider:output_type -> openshell.v1.ProviderResponse
134, // 444: openshell.v1.OpenShell.GetProviderRefreshStatus:output_type -> openshell.v1.GetProviderRefreshStatusResponse
136, // 445: openshell.v1.OpenShell.ConfigureProviderRefresh:output_type -> openshell.v1.ConfigureProviderRefreshResponse
138, // 446: openshell.v1.OpenShell.RotateProviderCredential:output_type -> openshell.v1.RotateProviderCredentialResponse
140, // 447: openshell.v1.OpenShell.DeleteProviderRefresh:output_type -> openshell.v1.DeleteProviderRefreshResponse
151, // 448: openshell.v1.OpenShell.DeleteProvider:output_type -> openshell.v1.DeleteProviderResponse
153, // 449: openshell.v1.OpenShell.DeleteProviderProfile:output_type -> openshell.v1.DeleteProviderProfileResponse
292, // 450: openshell.v1.OpenShell.GetSandboxConfig:output_type -> openshell.sandbox.v1.GetSandboxConfigResponse
293, // 451: openshell.v1.OpenShell.GetGatewayConfig:output_type -> openshell.sandbox.v1.GetGatewayConfigResponse
169, // 452: openshell.v1.OpenShell.UpdateConfig:output_type -> openshell.v1.UpdateConfigResponse
171, // 453: openshell.v1.OpenShell.GetSandboxPolicyStatus:output_type -> openshell.v1.GetSandboxPolicyStatusResponse
173, // 454: openshell.v1.OpenShell.ListSandboxPolicies:output_type -> openshell.v1.ListSandboxPoliciesResponse
175, // 455: openshell.v1.OpenShell.ReportPolicyStatus:output_type -> openshell.v1.ReportPolicyStatusResponse
248, // 456: openshell.v1.OpenShell.ReportEndpointStatus:output_type -> openshell.v1.ReportEndpointStatusResponse
85, // 457: openshell.v1.OpenShell.ReportProviderReadiness:output_type -> openshell.v1.ReportProviderReadinessResponse
178, // 458: openshell.v1.OpenShell.ReportSandboxConfiguration:output_type -> openshell.v1.ReportSandboxConfigurationResponse
157, // 459: openshell.v1.OpenShell.GetSandboxProviderEnvironment:output_type -> openshell.v1.GetSandboxProviderEnvironmentResponse
159, // 460: openshell.v1.OpenShell.ExchangeProviderSubjectToken:output_type -> openshell.v1.ExchangeProviderSubjectTokenResponse
183, // 461: openshell.v1.OpenShell.GetSandboxLogs:output_type -> openshell.v1.GetSandboxLogsResponse
182, // 462: openshell.v1.OpenShell.PushSandboxLogs:output_type -> openshell.v1.PushSandboxLogsResponse
185, // 463: openshell.v1.OpenShell.ConnectSupervisor:output_type -> openshell.v1.GatewayMessage
192, // 464: openshell.v1.OpenShell.ReportMainProcessExit:output_type -> openshell.v1.ReportMainProcessExitResponse
194, // 465: openshell.v1.OpenShell.FinalizeMainProcessExit:output_type -> openshell.v1.FinalizeMainProcessExitResponse
199, // 466: openshell.v1.OpenShell.RelayStream:output_type -> openshell.v1.RelayFrame
201, // 467: openshell.v1.OpenShell.PeerRelay:output_type -> openshell.v1.PeerRelayFrame
85, // 468: openshell.v1.OpenShell.PeerReportProviderReadiness:output_type -> openshell.v1.ReportProviderReadinessResponse
248, // 469: openshell.v1.OpenShell.PeerReportEndpointStatus:output_type -> openshell.v1.ReportEndpointStatusResponse
83, // 470: openshell.v1.OpenShell.PeerGetSandboxProviderStatus:output_type -> openshell.v1.GetSandboxProviderStatusResponse
110, // 471: openshell.v1.OpenShell.WatchSandbox:output_type -> openshell.v1.SandboxStreamEvent
211, // 472: openshell.v1.OpenShell.SubmitPolicyAnalysis:output_type -> openshell.v1.SubmitPolicyAnalysisResponse
213, // 473: openshell.v1.OpenShell.GetDraftPolicy:output_type -> openshell.v1.GetDraftPolicyResponse
215, // 474: openshell.v1.OpenShell.ApproveDraftChunk:output_type -> openshell.v1.ApproveDraftChunkResponse
217, // 475: openshell.v1.OpenShell.RejectDraftChunk:output_type -> openshell.v1.RejectDraftChunkResponse
220, // 476: openshell.v1.OpenShell.ApproveAllDraftChunks:output_type -> openshell.v1.ApproveAllDraftChunksResponse
222, // 477: openshell.v1.OpenShell.EditDraftChunk:output_type -> openshell.v1.EditDraftChunkResponse
224, // 478: openshell.v1.OpenShell.UndoDraftChunk:output_type -> openshell.v1.UndoDraftChunkResponse
226, // 479: openshell.v1.OpenShell.ClearDraftChunks:output_type -> openshell.v1.ClearDraftChunksResponse
229, // 480: openshell.v1.OpenShell.GetDraftHistory:output_type -> openshell.v1.GetDraftHistoryResponse
21, // 481: openshell.v1.OpenShell.IssueSandboxToken:output_type -> openshell.v1.IssueSandboxTokenResponse
23, // 482: openshell.v1.OpenShell.RefreshSandboxToken:output_type -> openshell.v1.RefreshSandboxTokenResponse
231, // 483: openshell.v1.OpenShell.CreateWorkspace:output_type -> openshell.v1.CreateWorkspaceResponse
233, // 484: openshell.v1.OpenShell.GetWorkspace:output_type -> openshell.v1.GetWorkspaceResponse
235, // 485: openshell.v1.OpenShell.ListWorkspaces:output_type -> openshell.v1.ListWorkspacesResponse
237, // 486: openshell.v1.OpenShell.DeleteWorkspace:output_type -> openshell.v1.DeleteWorkspaceResponse
240, // 487: openshell.v1.OpenShell.AddWorkspaceMember:output_type -> openshell.v1.AddWorkspaceMemberResponse
242, // 488: openshell.v1.OpenShell.RemoveWorkspaceMember:output_type -> openshell.v1.RemoveWorkspaceMemberResponse
244, // 489: openshell.v1.OpenShell.ListWorkspaceMembers:output_type -> openshell.v1.ListWorkspaceMembersResponse
408, // [408:490] is the sub-list for method output_type
326, // [326:408] is the sub-list for method input_type
326, // [326:326] is the sub-list for extension type_name
326, // [326:326] is the sub-list for extension extendee
0, // [0:326] is the sub-list for field type_name
}
func init() { file_openshell_proto_init() }