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