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