1use anyhow::Result;
2use async_trait::async_trait;
3use serde::{Deserialize, Serialize};
4use std::collections::{BTreeMap, BTreeSet};
5use std::fmt::Debug;
6use std::sync::Arc;
7
8mod base64_bytes {
9 use base64::{Engine as _, engine::general_purpose::STANDARD};
10 use serde::{Deserialize, Deserializer, Serializer};
11
12 pub fn serialize<S>(value: &[u8], serializer: S) -> Result<S::Ok, S::Error>
13 where
14 S: Serializer,
15 {
16 serializer.serialize_str(&STANDARD.encode(value))
17 }
18
19 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
20 where
21 D: Deserializer<'de>,
22 {
23 let value = String::deserialize(deserializer)?;
24 STANDARD.decode(value).map_err(serde::de::Error::custom)
25 }
26}
27
28mod catalog;
29pub use catalog::*;
30
31mod ports;
32pub use ports::*;
33
34mod owners;
35pub use owners::*;
36
37mod commands;
38pub use commands::*;
39
40mod resources;
41pub use resources::*;
42
43mod skills;
44pub use skills::*;
45
46pub const COMPUTERS_PATH: &str = "/internal/v1/workspace/computers";
47pub const COMPUTER_PATH: &str = "/internal/v1/workspace/computers/{computerId}";
48pub const SPACES_PATH: &str = "/internal/v1/workspace/spaces";
49pub const SPACE_PATH: &str = "/internal/v1/workspace/spaces/{spaceId}";
50pub const SPACE_GRANTS_PATH: &str = "/internal/v1/workspace/spaces/{spaceId}/grants";
51pub const SPACE_GRANT_REVOKE_PATH: &str =
52 "/internal/v1/workspace/spaces/{spaceId}/grants/{grantId}/revoke";
53pub const SPACE_SESSIONS_PATH: &str = "/internal/v1/workspace/spaces/{spaceId}/sessions";
54pub const SPACE_SESSION_HEARTBEAT_PATH: &str =
55 "/internal/v1/workspace/space-sessions/{sessionId}/heartbeat";
56pub const SPACE_SESSION_CLOSE_PATH: &str =
57 "/internal/v1/workspace/space-sessions/{sessionId}/close";
58pub const SPACE_TICKETS_PATH: &str = "/internal/v1/workspace/space-access-tickets";
59pub const SPACE_LEASES_PATH: &str = "/internal/v1/workspace/spaces/{spaceId}/leases";
60pub const SPACE_LEASE_PATH: &str = "/internal/v1/workspace/spaces/{spaceId}/leases/{leaseId}";
61pub const SPACE_FILES_PATH: &str = "/internal/v1/workspace/spaces/{spaceId}/files/{*filePath}";
62pub const SPACE_FILES_READ_PATH: &str = "/internal/v1/workspace/spaces/{spaceId}/files/read";
63pub const SPACE_FILES_LIST_PATH: &str = "/internal/v1/workspace/spaces/{spaceId}/files/list";
64pub const SPACE_CHANGE_SETS_PATH: &str = "/internal/v1/workspace/spaces/{spaceId}/change-sets";
65pub const SPACE_CHANGE_SET_APPLY_PATH: &str =
66 "/internal/v1/workspace/spaces/{spaceId}/change-sets/{changeSetId}/apply";
67pub const SANDBOXES_PATH: &str = "/internal/v1/workspace/sandboxes";
68pub const SANDBOX_PATH: &str = "/internal/v1/workspace/sandboxes/{sandboxId}";
69pub const SANDBOX_STOP_PATH: &str = "/internal/v1/workspace/sandboxes/{sandboxId}/stop";
70pub const SNAPSHOTS_PATH: &str = "/internal/v1/workspace/snapshots";
71pub const SNAPSHOT_PATH: &str = "/internal/v1/workspace/snapshots/{snapshotId}";
72pub const BUILD_BUILTIN_SNAPSHOTS_PATH: &str = "/internal/v1/workspace/snapshots:build-builtin";
73pub const CATALOG_SNAPSHOTS_PATH: &str = "/internal/v1/workspace/snapshots:catalog";
74pub const TEMPLATES_PATH: &str = "/internal/v1/workspace/templates";
75pub const TEMPLATE_VERSIONS_PATH: &str = "/internal/v1/workspace/templates/{templateId}/versions";
76pub const TEMPLATE_VERSION_PATH: &str =
77 "/internal/v1/workspace/templates/{templateId}/versions/{version}";
78pub const TEMPLATE_VERSION_PUBLISH_PATH: &str =
79 "/internal/v1/workspace/templates/{templateId}/versions/{version}/publish";
80pub const TEMPLATE_VERSION_DEPRECATE_PATH: &str =
81 "/internal/v1/workspace/templates/{templateId}/versions/{version}/deprecate";
82pub const DELEGATIONS_PATH: &str = "/internal/v1/workspace/delegations";
83pub const DELEGATION_REVOKE_PATH: &str = "/internal/v1/workspace/delegations/{delegationId}/revoke";
84pub const ENVIRONMENT_MAX_FILE_BYTES: usize = 8 * 1024 * 1024;
85pub const ENVIRONMENT_MAX_PATH_BYTES: usize = 4096;
86
87pub fn space_directory_path(space_id: &str) -> String {
89 format!("spaces/{space_id}")
90}
91
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
93#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
94pub enum EnvironmentErrorCode {
95 NotFound,
96 Forbidden,
97 Conflict,
98 InvalidState,
99 CapabilityUnsupported,
100 TicketExpired,
101 LeaseRequired,
102 StaleFencingToken,
103 RevisionConflict,
104}
105
106#[derive(Debug, Clone)]
107pub struct EnvironmentDomainError {
108 pub code: EnvironmentErrorCode,
109 pub message: String,
110}
111
112impl EnvironmentDomainError {
113 pub fn new(code: EnvironmentErrorCode, message: impl Into<String>) -> Self {
114 Self {
115 code,
116 message: message.into(),
117 }
118 }
119}
120
121impl std::fmt::Display for EnvironmentDomainError {
122 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 formatter.write_str(&self.message)
124 }
125}
126
127impl std::error::Error for EnvironmentDomainError {}
128
129#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
130#[serde(rename_all = "snake_case")]
131pub enum PrincipalKind {
132 User,
133 Agent,
134}
135
136#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
137#[serde(deny_unknown_fields, rename_all = "camelCase")]
138pub struct PrincipalRef {
139 pub kind: PrincipalKind,
140 pub id: String,
141}
142
143impl PrincipalRef {
144 pub fn user(id: impl Into<String>) -> Self {
145 Self {
146 kind: PrincipalKind::User,
147 id: id.into(),
148 }
149 }
150
151 pub fn agent(id: impl Into<String>) -> Self {
152 Self {
153 kind: PrincipalKind::Agent,
154 id: id.into(),
155 }
156 }
157}
158
159#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
160#[serde(deny_unknown_fields, rename_all = "camelCase")]
161pub struct ResourceScope {
162 pub tenant_id: String,
163 pub project_id: String,
164}
165
166#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
167#[serde(deny_unknown_fields, rename_all = "camelCase")]
168pub struct ProviderResourceRef {
169 pub provider: String,
170 pub external_id: String,
171}
172
173#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
174#[serde(deny_unknown_fields, rename_all = "camelCase")]
175pub struct ProviderCapabilities {
176 #[serde(default)]
177 pub capabilities: BTreeSet<String>,
178}
179
180impl ProviderCapabilities {
181 pub fn supports(&self, capability: &str) -> bool {
182 self.capabilities.contains(capability)
183 }
184}
185
186#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
187#[serde(rename_all = "snake_case")]
188pub enum ComputerLifecycle {
189 Ready,
190 Deleted,
191}
192
193#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
194#[serde(deny_unknown_fields, rename_all = "camelCase")]
195pub struct ComputerRecord {
196 pub id: String,
197 pub scope: ResourceScope,
198 pub provider_ref: ProviderResourceRef,
199 pub lifecycle: ComputerLifecycle,
200 pub capabilities: ProviderCapabilities,
201 pub owners: Vec<OwnerRef>,
202 pub version: u64,
203 pub created_at_ms: u64,
204 pub updated_at_ms: u64,
205}
206
207#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
208#[serde(deny_unknown_fields, rename_all = "camelCase")]
209pub struct ComputerBinding {
210 pub computer_id: String,
211 pub principal: PrincipalRef,
212 pub role: String,
213 pub active: bool,
214 pub bound_at_ms: u64,
215 #[serde(default, skip_serializing_if = "Option::is_none")]
216 pub released_at_ms: Option<u64>,
217 pub version: u64,
218}
219
220#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
221#[serde(rename_all = "snake_case")]
222pub enum SpacePersistence {
223 Persistent,
224 CopyOnWrite,
225}
226
227#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
228#[serde(rename_all = "snake_case")]
229pub enum SpaceLifecycle {
230 Ready,
231 Deleted,
232}
233
234#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
235#[serde(deny_unknown_fields, rename_all = "camelCase")]
236pub struct SpaceRecord {
237 pub id: String,
238 pub computer_id: String,
239 pub scope: ResourceScope,
240 pub persistence: SpacePersistence,
241 pub lifecycle: SpaceLifecycle,
242 pub capabilities: ProviderCapabilities,
243 pub owners: Vec<OwnerRef>,
244 #[serde(default, skip_serializing_if = "Option::is_none")]
245 pub source_snapshot_id: Option<String>,
246 pub revision: u64,
247 pub version: u64,
248 pub created_at_ms: u64,
249 pub updated_at_ms: u64,
250}
251
252#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
253#[serde(rename_all = "snake_case")]
254pub enum SandboxPlacement {
255 Computer(String),
256 ProviderPool(String),
257}
258
259#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
260#[serde(rename_all = "snake_case")]
261pub enum SandboxLifecycle {
262 Ready,
263 Stopped,
264 Expired,
265}
266
267#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
268#[serde(deny_unknown_fields, rename_all = "camelCase")]
269pub struct SandboxMount {
270 pub alias: String,
271 pub space_id: String,
272 pub mode: SpaceAccessMode,
273 #[serde(default, skip_serializing_if = "Option::is_none")]
274 pub path_prefix: Option<String>,
275 pub access_ticket_token: String,
276}
277
278#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
281#[serde(deny_unknown_fields, rename_all = "camelCase")]
282pub struct SandboxMountRecord {
283 pub alias: String,
284 pub space_id: String,
285 pub mode: SpaceAccessMode,
286 #[serde(default, skip_serializing_if = "Option::is_none")]
287 pub path_prefix: Option<String>,
288 pub access_ticket_id: String,
289}
290
291#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
292#[serde(deny_unknown_fields, rename_all = "camelCase")]
293pub struct SandboxRecord {
294 pub id: String,
295 pub scope: ResourceScope,
296 pub provider_ref: ProviderResourceRef,
297 pub placement: SandboxPlacement,
298 pub lifecycle: SandboxLifecycle,
299 pub owners: Vec<OwnerRef>,
300 #[serde(default, skip_serializing_if = "Option::is_none")]
301 pub access_delegation_id: Option<String>,
302 pub capabilities: ProviderCapabilities,
303 #[serde(default)]
304 pub mounts: Vec<SandboxMountRecord>,
305 pub expires_at_ms: u64,
306 pub version: u64,
307 pub created_at_ms: u64,
308 pub updated_at_ms: u64,
309}
310
311#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
312#[serde(rename_all = "snake_case")]
313pub enum SnapshotLifecycle {
314 Building,
315 Ready,
316 Failed,
317 Deleted,
318}
319
320#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
321#[serde(tag = "kind", rename_all = "snake_case")]
322pub enum SnapshotSourceRecord {
323 Build { spec: SnapshotBuildSpec },
324}
325
326#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
327#[serde(deny_unknown_fields, rename_all = "camelCase")]
328pub struct SnapshotRecord {
329 pub id: String,
330 pub scope: ResourceScope,
331 pub provider: String,
332 pub provider_ref: ProviderResourceRef,
333 pub source: SnapshotSourceRecord,
334 pub visibility: SnapshotVisibility,
335 pub owners: Vec<OwnerRef>,
336 #[serde(default)]
337 pub builtin: bool,
338 pub created_by: PrincipalRef,
339 pub lifecycle: SnapshotLifecycle,
340 #[serde(default, skip_serializing_if = "Option::is_none")]
341 pub digest: Option<String>,
342 #[serde(default, skip_serializing_if = "Option::is_none")]
343 pub size_bytes: Option<u64>,
344 #[serde(default, skip_serializing_if = "Option::is_none")]
345 pub error: Option<String>,
346 #[serde(default, skip_serializing_if = "Option::is_none")]
347 pub provider_build_id: Option<String>,
348 #[serde(default, skip_serializing_if = "Option::is_none")]
349 pub build_stage: Option<String>,
350 #[serde(default, skip_serializing_if = "Vec::is_empty")]
351 pub build_logs: Vec<String>,
352 #[serde(default, skip_serializing_if = "String::is_empty")]
353 pub build_key: String,
354 pub created_at_ms: u64,
355 pub updated_at_ms: u64,
356}
357
358#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
359#[serde(rename_all = "snake_case")]
360pub enum TemplateTarget {
361 Computer,
362 Sandbox,
363}
364
365#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
366#[serde(rename_all = "snake_case")]
367pub enum TemplateVersionState {
368 Draft,
369 Published,
370 Deprecated,
371}
372
373#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
374#[serde(deny_unknown_fields, rename_all = "camelCase")]
375pub struct TemplateVersionRecord {
376 pub template_id: String,
377 pub version: String,
378 pub scope: ResourceScope,
379 pub provider: String,
380 pub created_by: PrincipalRef,
381 #[serde(default, skip_serializing_if = "Option::is_none")]
382 pub provider_template_id: Option<String>,
383 pub target: TemplateTarget,
384 #[serde(default, skip_serializing_if = "Option::is_none")]
385 pub base_snapshot_id: Option<String>,
386 #[serde(default)]
387 pub resource_profile: BTreeMap<String, String>,
388 #[serde(default)]
389 pub parameter_schema: BTreeMap<String, String>,
390 pub state: TemplateVersionState,
391 pub created_at_ms: u64,
392}
393
394#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
395#[serde(rename_all = "snake_case")]
396pub enum SpaceCapability {
397 Read,
398 Write,
399 Share,
400 Manage,
401 Mount,
402 Snapshot,
403 Restore,
404 Delete,
405}
406
407#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
408#[serde(deny_unknown_fields, rename_all = "camelCase")]
409pub struct SpaceGrant {
410 pub id: String,
411 pub scope: ResourceScope,
412 pub space_id: String,
413 pub principal: PrincipalRef,
414 pub capabilities: BTreeSet<SpaceCapability>,
415 #[serde(default)]
416 pub path_prefixes: Vec<String>,
417 #[serde(default, skip_serializing_if = "Option::is_none")]
418 pub expires_at_ms: Option<u64>,
419 pub active: bool,
420 pub version: u64,
421}
422
423#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
424#[serde(rename_all = "snake_case")]
425pub enum SpaceAccessMode {
426 ReadOnly,
427 DirectWrite,
428 CopyOnWrite,
429}
430
431#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
432#[serde(rename_all = "snake_case")]
433pub enum SpaceSessionLifecycle {
434 Opening,
435 Active,
436 Closing,
437 Closed,
438 Expired,
439 Revoked,
440}
441
442#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
443#[serde(deny_unknown_fields, rename_all = "camelCase")]
444pub struct SpaceCollaborationSession {
445 pub id: String,
446 pub scope: ResourceScope,
447 pub space_id: String,
448 pub principal: PrincipalRef,
449 #[serde(default, skip_serializing_if = "Option::is_none")]
450 pub delegation_id: Option<String>,
451 pub requested_mode: SpaceAccessMode,
452 pub effective_mode: SpaceAccessMode,
453 pub lifecycle: SpaceSessionLifecycle,
454 pub last_heartbeat_at_ms: u64,
455 pub expires_at_ms: u64,
456 pub version: u64,
457}
458
459#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
460#[serde(deny_unknown_fields, rename_all = "camelCase")]
461pub struct SpaceAccessTicketRecord {
462 pub id: String,
463 pub token_hash: String,
464 pub scope: ResourceScope,
465 pub space_id: String,
466 pub session_id: String,
467 pub mode: SpaceAccessMode,
468 #[serde(default)]
471 pub capability_paths: BTreeMap<SpaceCapability, Vec<String>>,
472 #[serde(default, skip_serializing_if = "Option::is_none")]
473 pub fencing_token: Option<u64>,
474 pub expires_at_ms: u64,
475 pub revoked: bool,
476}
477
478#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
479#[serde(deny_unknown_fields, rename_all = "camelCase")]
480pub struct IssuedSpaceAccessTicket {
481 pub ticket: SpaceAccessTicketRecord,
482 pub token: String,
485}
486
487#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
488#[serde(deny_unknown_fields, rename_all = "camelCase")]
489pub struct SpaceWriteLease {
490 pub id: String,
491 pub scope: ResourceScope,
492 pub space_id: String,
493 pub session_id: String,
494 pub fencing_token: u64,
495 pub version: u64,
496 pub acquired_at_ms: u64,
497 pub expires_at_ms: u64,
498 pub active: bool,
499}
500
501#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
502#[serde(deny_unknown_fields, rename_all = "camelCase")]
503pub struct DelegationRecord {
504 pub id: String,
505 pub scope: ResourceScope,
506 pub grantor_user_id: String,
507 pub delegate_agent_id: String,
508 #[serde(default)]
509 pub computer_ids: BTreeSet<String>,
510 #[serde(default)]
511 pub space_ids: BTreeSet<String>,
512 pub capabilities: BTreeSet<SpaceCapability>,
513 #[serde(default)]
514 pub path_prefixes: Vec<String>,
515 pub purpose: String,
516 pub expires_at_ms: u64,
517 #[serde(default, skip_serializing_if = "Option::is_none")]
518 pub revoked_at_ms: Option<u64>,
519}
520
521#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
522#[serde(rename_all = "snake_case")]
523pub enum ChangeSetLifecycle {
524 Ready,
525 Applied,
526}
527
528#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
529#[serde(deny_unknown_fields, rename_all = "camelCase")]
530pub struct SpaceChangeSetRecord {
531 pub id: String,
532 pub scope: ResourceScope,
533 pub source_space_id: String,
534 pub target_space_id: String,
535 pub base_revision: u64,
536 pub created_by_session_id: String,
537 #[serde(default, skip_serializing_if = "Option::is_none")]
538 pub provider_change_ref: Option<String>,
539 pub lifecycle: ChangeSetLifecycle,
540 pub created_at_ms: u64,
541}
542
543#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
544#[serde(deny_unknown_fields, rename_all = "camelCase")]
545pub struct CreateComputerRequest {
546 pub provider: String,
547 #[serde(default, skip_serializing_if = "Option::is_none")]
548 pub snapshot_id: Option<String>,
549 #[serde(default, skip_serializing_if = "Option::is_none")]
550 pub template_id: Option<String>,
551 #[serde(default, skip_serializing_if = "Option::is_none")]
552 pub template_version: Option<String>,
553 #[serde(default)]
554 pub profile: BTreeMap<String, String>,
555 #[serde(default)]
557 pub owners: Vec<OwnerRef>,
558}
559
560#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
561#[serde(deny_unknown_fields, rename_all = "camelCase")]
562pub struct CreateSpaceRequest {
563 pub computer_id: String,
564 pub persistence: SpacePersistence,
565 #[serde(default, skip_serializing_if = "Option::is_none")]
566 pub source_snapshot_id: Option<String>,
567 #[serde(default)]
569 pub owners: Vec<OwnerRef>,
570}
571
572#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
573#[serde(deny_unknown_fields, rename_all = "camelCase")]
574pub struct CreateSandboxRequest {
575 pub provider: String,
576 pub placement: SandboxPlacement,
577 #[serde(default, skip_serializing_if = "Option::is_none")]
578 pub delegation_id: Option<String>,
579 pub ttl_ms: u64,
580 #[serde(default)]
581 pub mounts: Vec<SandboxMount>,
582 #[serde(default, skip_serializing_if = "Option::is_none")]
583 pub snapshot_id: Option<String>,
584 #[serde(default, skip_serializing_if = "Option::is_none")]
585 pub template_id: Option<String>,
586 #[serde(default, skip_serializing_if = "Option::is_none")]
587 pub template_version: Option<String>,
588 #[serde(default)]
589 pub profile: BTreeMap<String, String>,
590}
591
592#[derive(Debug, Clone, PartialEq, Eq)]
595pub struct ProviderComputerRequest {
596 pub template_external_id: Option<String>,
597 pub profile: BTreeMap<String, String>,
598}
599
600#[derive(Debug, Clone, PartialEq, Eq)]
601pub struct ProviderSpaceRequest {
602 pub persistence: SpacePersistence,
603 pub source_snapshot_external_id: Option<String>,
604}
605
606#[derive(Debug, Clone, PartialEq, Eq)]
607pub struct ProviderSandboxMount {
608 pub alias: String,
609 pub space_directory: String,
610 pub mode: SpaceAccessMode,
611 pub path_prefix: Option<String>,
612}
613
614#[derive(Debug, Clone, PartialEq, Eq)]
615pub enum ProviderSandboxPlacement {
616 Computer(String),
617 ProviderPool(String),
618}
619
620#[derive(Debug, Clone, PartialEq, Eq)]
621pub struct ProviderSandboxRequest {
622 pub placement: ProviderSandboxPlacement,
623 pub ttl_ms: u64,
624 pub mounts: Vec<ProviderSandboxMount>,
625 pub template_external_id: Option<String>,
626 pub source_snapshot_external_id: Option<String>,
627 pub profile: BTreeMap<String, String>,
628}
629
630#[derive(Debug, Clone, PartialEq, Eq)]
631pub enum ProviderSnapshotSource {
632 Computer(String),
633 Sandbox(String),
634 Space(String),
635}
636
637#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
638#[serde(deny_unknown_fields, rename_all = "camelCase")]
639pub struct ListEnvironmentResourcesQuery {
640 #[serde(default, skip_serializing_if = "Option::is_none")]
641 pub owner_kind: Option<OwnerKind>,
642 #[serde(default, skip_serializing_if = "Option::is_none")]
643 pub owner_id: Option<String>,
644 #[serde(default, skip_serializing_if = "Vec::is_empty")]
646 pub contains_all: Vec<OwnerRef>,
647}
648
649#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
650#[serde(deny_unknown_fields, rename_all = "camelCase")]
651pub struct RevokeSpaceGrantRequest {
652 pub expected_version: u64,
653}
654
655#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
656#[serde(deny_unknown_fields, rename_all = "camelCase")]
657pub struct CreateSpaceGrantRequest {
658 pub principal: PrincipalRef,
659 pub capabilities: BTreeSet<SpaceCapability>,
660 #[serde(default)]
661 pub path_prefixes: Vec<String>,
662 #[serde(default, skip_serializing_if = "Option::is_none")]
663 pub expires_at_ms: Option<u64>,
664}
665
666#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
667#[serde(deny_unknown_fields, rename_all = "camelCase")]
668pub struct OpenSpaceSessionRequest {
669 pub mode: SpaceAccessMode,
670 #[serde(default, skip_serializing_if = "Option::is_none")]
671 pub delegation_id: Option<String>,
672 pub ttl_ms: u64,
673}
674
675#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
676#[serde(deny_unknown_fields, rename_all = "camelCase")]
677pub struct IssueSpaceAccessTicketRequest {
678 pub session_id: String,
679 pub ttl_ms: u64,
680}
681
682#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
683#[serde(deny_unknown_fields, rename_all = "camelCase")]
684pub struct AcquireSpaceWriteLeaseRequest {
685 pub session_id: String,
686 pub ttl_ms: u64,
687}
688
689#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
690#[serde(deny_unknown_fields, rename_all = "camelCase")]
691pub struct ReleaseSpaceWriteLeaseRequest {
692 pub session_id: String,
693 pub fencing_token: u64,
694}
695
696#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
697#[serde(deny_unknown_fields, rename_all = "camelCase")]
698pub struct HeartbeatSpaceSessionRequest {
699 pub ttl_ms: u64,
700}
701
702#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
703#[serde(deny_unknown_fields, rename_all = "camelCase")]
704pub struct CreateDelegationRequest {
705 pub delegate_agent_id: String,
706 #[serde(default)]
707 pub computer_ids: BTreeSet<String>,
708 #[serde(default)]
709 pub space_ids: BTreeSet<String>,
710 pub capabilities: BTreeSet<SpaceCapability>,
711 #[serde(default)]
712 pub path_prefixes: Vec<String>,
713 pub purpose: String,
714 pub expires_at_ms: u64,
715}
716
717#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
718#[serde(deny_unknown_fields, rename_all = "camelCase")]
719pub struct CreateTemplateVersionRequest {
720 pub template_id: String,
721 pub version: String,
722 pub provider: String,
723 #[serde(default, skip_serializing_if = "Option::is_none")]
724 pub provider_template_id: Option<String>,
725 pub target: TemplateTarget,
726 #[serde(default, skip_serializing_if = "Option::is_none")]
727 pub base_snapshot_id: Option<String>,
728 #[serde(default)]
729 pub resource_profile: BTreeMap<String, String>,
730 #[serde(default)]
731 pub parameter_schema: BTreeMap<String, String>,
732}
733
734#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
735#[serde(deny_unknown_fields, rename_all = "camelCase")]
736pub struct CreateSpaceChangeSetRequest {
737 pub source_space_id: String,
738 pub target_space_id: String,
739 pub created_by_session_id: String,
740}
741
742#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
743#[serde(deny_unknown_fields, rename_all = "camelCase")]
744pub struct ApplySpaceChangeSetRequest {
745 pub access_ticket_token: String,
746 pub fencing_token: u64,
747 pub expected_revision: u64,
748}
749
750#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
751#[serde(deny_unknown_fields, rename_all = "camelCase")]
752pub struct WriteSpaceFileRequest {
753 pub access_ticket_token: String,
754 pub fencing_token: u64,
755 pub expected_revision: u64,
756 #[serde(with = "base64_bytes")]
757 pub content: Vec<u8>,
758}
759
760#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
761#[serde(deny_unknown_fields, rename_all = "camelCase")]
762pub struct ReadSpaceFileRequest {
763 pub access_ticket_token: String,
764 pub path: String,
765}
766
767#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
768#[serde(deny_unknown_fields, rename_all = "camelCase")]
769pub struct ListSpaceFilesRequest {
770 pub access_ticket_token: String,
771 #[serde(default)]
772 pub path: String,
773}
774
775#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
776#[serde(deny_unknown_fields, rename_all = "camelCase")]
777pub struct DeleteSpaceFileRequest {
778 pub access_ticket_token: String,
779 pub fencing_token: u64,
780 pub expected_revision: u64,
781}
782
783#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
784#[serde(deny_unknown_fields, rename_all = "camelCase")]
785pub struct ProviderFileContent {
786 pub bytes: Vec<u8>,
787 #[serde(default, skip_serializing_if = "Option::is_none")]
788 pub provider_revision: Option<String>,
789}
790
791#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
792#[serde(deny_unknown_fields, rename_all = "camelCase")]
793pub struct ProviderFileEntry {
794 pub path: String,
795 pub is_dir: bool,
796 #[serde(default, skip_serializing_if = "Option::is_none")]
797 pub size_bytes: Option<u64>,
798}
799
800#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
801#[serde(deny_unknown_fields, rename_all = "camelCase")]
802pub struct ProviderWriteResult {
803 #[serde(default, skip_serializing_if = "Option::is_none")]
804 pub provider_revision: Option<String>,
805}