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 = "String::is_empty")]
347 pub build_key: String,
348 pub created_at_ms: u64,
349 pub updated_at_ms: u64,
350}
351
352#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
353#[serde(rename_all = "snake_case")]
354pub enum TemplateTarget {
355 Computer,
356 Sandbox,
357}
358
359#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
360#[serde(rename_all = "snake_case")]
361pub enum TemplateVersionState {
362 Draft,
363 Published,
364 Deprecated,
365}
366
367#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
368#[serde(deny_unknown_fields, rename_all = "camelCase")]
369pub struct TemplateVersionRecord {
370 pub template_id: String,
371 pub version: String,
372 pub scope: ResourceScope,
373 pub provider: String,
374 pub created_by: PrincipalRef,
375 #[serde(default, skip_serializing_if = "Option::is_none")]
376 pub provider_template_id: Option<String>,
377 pub target: TemplateTarget,
378 #[serde(default, skip_serializing_if = "Option::is_none")]
379 pub base_snapshot_id: Option<String>,
380 #[serde(default)]
381 pub resource_profile: BTreeMap<String, String>,
382 #[serde(default)]
383 pub parameter_schema: BTreeMap<String, String>,
384 pub state: TemplateVersionState,
385 pub created_at_ms: u64,
386}
387
388#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
389#[serde(rename_all = "snake_case")]
390pub enum SpaceCapability {
391 Read,
392 Write,
393 Share,
394 Manage,
395 Mount,
396 Snapshot,
397 Restore,
398 Delete,
399}
400
401#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
402#[serde(deny_unknown_fields, rename_all = "camelCase")]
403pub struct SpaceGrant {
404 pub id: String,
405 pub scope: ResourceScope,
406 pub space_id: String,
407 pub principal: PrincipalRef,
408 pub capabilities: BTreeSet<SpaceCapability>,
409 #[serde(default)]
410 pub path_prefixes: Vec<String>,
411 #[serde(default, skip_serializing_if = "Option::is_none")]
412 pub expires_at_ms: Option<u64>,
413 pub active: bool,
414 pub version: u64,
415}
416
417#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
418#[serde(rename_all = "snake_case")]
419pub enum SpaceAccessMode {
420 ReadOnly,
421 DirectWrite,
422 CopyOnWrite,
423}
424
425#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
426#[serde(rename_all = "snake_case")]
427pub enum SpaceSessionLifecycle {
428 Opening,
429 Active,
430 Closing,
431 Closed,
432 Expired,
433 Revoked,
434}
435
436#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
437#[serde(deny_unknown_fields, rename_all = "camelCase")]
438pub struct SpaceCollaborationSession {
439 pub id: String,
440 pub scope: ResourceScope,
441 pub space_id: String,
442 pub principal: PrincipalRef,
443 #[serde(default, skip_serializing_if = "Option::is_none")]
444 pub delegation_id: Option<String>,
445 pub requested_mode: SpaceAccessMode,
446 pub effective_mode: SpaceAccessMode,
447 pub lifecycle: SpaceSessionLifecycle,
448 pub last_heartbeat_at_ms: u64,
449 pub expires_at_ms: u64,
450 pub version: u64,
451}
452
453#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
454#[serde(deny_unknown_fields, rename_all = "camelCase")]
455pub struct SpaceAccessTicketRecord {
456 pub id: String,
457 pub token_hash: String,
458 pub scope: ResourceScope,
459 pub space_id: String,
460 pub session_id: String,
461 pub mode: SpaceAccessMode,
462 #[serde(default)]
465 pub capability_paths: BTreeMap<SpaceCapability, Vec<String>>,
466 #[serde(default, skip_serializing_if = "Option::is_none")]
467 pub fencing_token: Option<u64>,
468 pub expires_at_ms: u64,
469 pub revoked: bool,
470}
471
472#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
473#[serde(deny_unknown_fields, rename_all = "camelCase")]
474pub struct IssuedSpaceAccessTicket {
475 pub ticket: SpaceAccessTicketRecord,
476 pub token: String,
479}
480
481#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
482#[serde(deny_unknown_fields, rename_all = "camelCase")]
483pub struct SpaceWriteLease {
484 pub id: String,
485 pub scope: ResourceScope,
486 pub space_id: String,
487 pub session_id: String,
488 pub fencing_token: u64,
489 pub version: u64,
490 pub acquired_at_ms: u64,
491 pub expires_at_ms: u64,
492 pub active: bool,
493}
494
495#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
496#[serde(deny_unknown_fields, rename_all = "camelCase")]
497pub struct DelegationRecord {
498 pub id: String,
499 pub scope: ResourceScope,
500 pub grantor_user_id: String,
501 pub delegate_agent_id: String,
502 #[serde(default)]
503 pub computer_ids: BTreeSet<String>,
504 #[serde(default)]
505 pub space_ids: BTreeSet<String>,
506 pub capabilities: BTreeSet<SpaceCapability>,
507 #[serde(default)]
508 pub path_prefixes: Vec<String>,
509 pub purpose: String,
510 pub expires_at_ms: u64,
511 #[serde(default, skip_serializing_if = "Option::is_none")]
512 pub revoked_at_ms: Option<u64>,
513}
514
515#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
516#[serde(rename_all = "snake_case")]
517pub enum ChangeSetLifecycle {
518 Ready,
519 Applied,
520}
521
522#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
523#[serde(deny_unknown_fields, rename_all = "camelCase")]
524pub struct SpaceChangeSetRecord {
525 pub id: String,
526 pub scope: ResourceScope,
527 pub source_space_id: String,
528 pub target_space_id: String,
529 pub base_revision: u64,
530 pub created_by_session_id: String,
531 #[serde(default, skip_serializing_if = "Option::is_none")]
532 pub provider_change_ref: Option<String>,
533 pub lifecycle: ChangeSetLifecycle,
534 pub created_at_ms: u64,
535}
536
537#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
538#[serde(deny_unknown_fields, rename_all = "camelCase")]
539pub struct CreateComputerRequest {
540 pub provider: String,
541 #[serde(default, skip_serializing_if = "Option::is_none")]
542 pub snapshot_id: Option<String>,
543 #[serde(default, skip_serializing_if = "Option::is_none")]
544 pub template_id: Option<String>,
545 #[serde(default, skip_serializing_if = "Option::is_none")]
546 pub template_version: Option<String>,
547 #[serde(default)]
548 pub profile: BTreeMap<String, String>,
549 #[serde(default)]
551 pub owners: Vec<OwnerRef>,
552}
553
554#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
555#[serde(deny_unknown_fields, rename_all = "camelCase")]
556pub struct CreateSpaceRequest {
557 pub computer_id: String,
558 pub persistence: SpacePersistence,
559 #[serde(default, skip_serializing_if = "Option::is_none")]
560 pub source_snapshot_id: Option<String>,
561 #[serde(default)]
563 pub owners: Vec<OwnerRef>,
564}
565
566#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
567#[serde(deny_unknown_fields, rename_all = "camelCase")]
568pub struct CreateSandboxRequest {
569 pub provider: String,
570 pub placement: SandboxPlacement,
571 #[serde(default, skip_serializing_if = "Option::is_none")]
572 pub delegation_id: Option<String>,
573 pub ttl_ms: u64,
574 #[serde(default)]
575 pub mounts: Vec<SandboxMount>,
576 #[serde(default, skip_serializing_if = "Option::is_none")]
577 pub snapshot_id: Option<String>,
578 #[serde(default, skip_serializing_if = "Option::is_none")]
579 pub template_id: Option<String>,
580 #[serde(default, skip_serializing_if = "Option::is_none")]
581 pub template_version: Option<String>,
582 #[serde(default)]
583 pub profile: BTreeMap<String, String>,
584}
585
586#[derive(Debug, Clone, PartialEq, Eq)]
589pub struct ProviderComputerRequest {
590 pub template_external_id: Option<String>,
591 pub profile: BTreeMap<String, String>,
592}
593
594#[derive(Debug, Clone, PartialEq, Eq)]
595pub struct ProviderSpaceRequest {
596 pub persistence: SpacePersistence,
597 pub source_snapshot_external_id: Option<String>,
598}
599
600#[derive(Debug, Clone, PartialEq, Eq)]
601pub struct ProviderSandboxMount {
602 pub alias: String,
603 pub space_directory: String,
604 pub mode: SpaceAccessMode,
605 pub path_prefix: Option<String>,
606}
607
608#[derive(Debug, Clone, PartialEq, Eq)]
609pub enum ProviderSandboxPlacement {
610 Computer(String),
611 ProviderPool(String),
612}
613
614#[derive(Debug, Clone, PartialEq, Eq)]
615pub struct ProviderSandboxRequest {
616 pub placement: ProviderSandboxPlacement,
617 pub ttl_ms: u64,
618 pub mounts: Vec<ProviderSandboxMount>,
619 pub template_external_id: Option<String>,
620 pub source_snapshot_external_id: Option<String>,
621 pub profile: BTreeMap<String, String>,
622}
623
624#[derive(Debug, Clone, PartialEq, Eq)]
625pub enum ProviderSnapshotSource {
626 Computer(String),
627 Sandbox(String),
628 Space(String),
629}
630
631#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
632#[serde(deny_unknown_fields, rename_all = "camelCase")]
633pub struct ListEnvironmentResourcesQuery {
634 #[serde(default, skip_serializing_if = "Option::is_none")]
635 pub owner_kind: Option<OwnerKind>,
636 #[serde(default, skip_serializing_if = "Option::is_none")]
637 pub owner_id: Option<String>,
638 #[serde(default, skip_serializing_if = "Vec::is_empty")]
640 pub contains_all: Vec<OwnerRef>,
641}
642
643#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
644#[serde(deny_unknown_fields, rename_all = "camelCase")]
645pub struct RevokeSpaceGrantRequest {
646 pub expected_version: u64,
647}
648
649#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
650#[serde(deny_unknown_fields, rename_all = "camelCase")]
651pub struct CreateSpaceGrantRequest {
652 pub principal: PrincipalRef,
653 pub capabilities: BTreeSet<SpaceCapability>,
654 #[serde(default)]
655 pub path_prefixes: Vec<String>,
656 #[serde(default, skip_serializing_if = "Option::is_none")]
657 pub expires_at_ms: Option<u64>,
658}
659
660#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
661#[serde(deny_unknown_fields, rename_all = "camelCase")]
662pub struct OpenSpaceSessionRequest {
663 pub mode: SpaceAccessMode,
664 #[serde(default, skip_serializing_if = "Option::is_none")]
665 pub delegation_id: Option<String>,
666 pub ttl_ms: u64,
667}
668
669#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
670#[serde(deny_unknown_fields, rename_all = "camelCase")]
671pub struct IssueSpaceAccessTicketRequest {
672 pub session_id: String,
673 pub ttl_ms: u64,
674}
675
676#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
677#[serde(deny_unknown_fields, rename_all = "camelCase")]
678pub struct AcquireSpaceWriteLeaseRequest {
679 pub session_id: String,
680 pub ttl_ms: u64,
681}
682
683#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
684#[serde(deny_unknown_fields, rename_all = "camelCase")]
685pub struct ReleaseSpaceWriteLeaseRequest {
686 pub session_id: String,
687 pub fencing_token: u64,
688}
689
690#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
691#[serde(deny_unknown_fields, rename_all = "camelCase")]
692pub struct HeartbeatSpaceSessionRequest {
693 pub ttl_ms: u64,
694}
695
696#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
697#[serde(deny_unknown_fields, rename_all = "camelCase")]
698pub struct CreateDelegationRequest {
699 pub delegate_agent_id: String,
700 #[serde(default)]
701 pub computer_ids: BTreeSet<String>,
702 #[serde(default)]
703 pub space_ids: BTreeSet<String>,
704 pub capabilities: BTreeSet<SpaceCapability>,
705 #[serde(default)]
706 pub path_prefixes: Vec<String>,
707 pub purpose: String,
708 pub expires_at_ms: u64,
709}
710
711#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
712#[serde(deny_unknown_fields, rename_all = "camelCase")]
713pub struct CreateTemplateVersionRequest {
714 pub template_id: String,
715 pub version: String,
716 pub provider: String,
717 #[serde(default, skip_serializing_if = "Option::is_none")]
718 pub provider_template_id: Option<String>,
719 pub target: TemplateTarget,
720 #[serde(default, skip_serializing_if = "Option::is_none")]
721 pub base_snapshot_id: Option<String>,
722 #[serde(default)]
723 pub resource_profile: BTreeMap<String, String>,
724 #[serde(default)]
725 pub parameter_schema: BTreeMap<String, String>,
726}
727
728#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
729#[serde(deny_unknown_fields, rename_all = "camelCase")]
730pub struct CreateSpaceChangeSetRequest {
731 pub source_space_id: String,
732 pub target_space_id: String,
733 pub created_by_session_id: String,
734}
735
736#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
737#[serde(deny_unknown_fields, rename_all = "camelCase")]
738pub struct ApplySpaceChangeSetRequest {
739 pub access_ticket_token: String,
740 pub fencing_token: u64,
741 pub expected_revision: u64,
742}
743
744#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
745#[serde(deny_unknown_fields, rename_all = "camelCase")]
746pub struct WriteSpaceFileRequest {
747 pub access_ticket_token: String,
748 pub fencing_token: u64,
749 pub expected_revision: u64,
750 #[serde(with = "base64_bytes")]
751 pub content: Vec<u8>,
752}
753
754#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
755#[serde(deny_unknown_fields, rename_all = "camelCase")]
756pub struct ReadSpaceFileRequest {
757 pub access_ticket_token: String,
758 pub path: String,
759}
760
761#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
762#[serde(deny_unknown_fields, rename_all = "camelCase")]
763pub struct ListSpaceFilesRequest {
764 pub access_ticket_token: String,
765 #[serde(default)]
766 pub path: String,
767}
768
769#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
770#[serde(deny_unknown_fields, rename_all = "camelCase")]
771pub struct DeleteSpaceFileRequest {
772 pub access_ticket_token: String,
773 pub fencing_token: u64,
774 pub expected_revision: u64,
775}
776
777#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
778#[serde(deny_unknown_fields, rename_all = "camelCase")]
779pub struct ProviderFileContent {
780 pub bytes: Vec<u8>,
781 #[serde(default, skip_serializing_if = "Option::is_none")]
782 pub provider_revision: Option<String>,
783}
784
785#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
786#[serde(deny_unknown_fields, rename_all = "camelCase")]
787pub struct ProviderFileEntry {
788 pub path: String,
789 pub is_dir: bool,
790 #[serde(default, skip_serializing_if = "Option::is_none")]
791 pub size_bytes: Option<u64>,
792}
793
794#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
795#[serde(deny_unknown_fields, rename_all = "camelCase")]
796pub struct ProviderWriteResult {
797 #[serde(default, skip_serializing_if = "Option::is_none")]
798 pub provider_revision: Option<String>,
799}