oxicode_sdk/security/capability/
resolve.rs1use uuid::Uuid;
7
8use super::types::CSpaceBuilder;
9
10pub fn resolve_cspace(
18 template: Option<&str>,
19 workspace: Option<&str>,
20 extra_domains: Option<&[String]>,
21 agent_id: Uuid,
22) -> super::types::CSpace {
23 let name = template.unwrap_or("empty");
24 let mut builder = CSpaceBuilder::new(agent_id).name(name);
25
26 match name {
27 "admin" | "superuser" => {
28 builder = builder.all_access();
29 }
30 "standard" | "default" => {
31 builder = builder.standard();
32 if let Some(ws) = workspace {
34 use super::types::{ResourceRef, Rights};
35 builder = builder.grant(
36 ResourceRef::Path {
37 pattern: format!("{ws}/**"),
38 },
39 vec![Rights::Read, Rights::Write, Rights::Execute],
40 );
41 }
42 }
43 "worker" => {
44 builder = builder.worker();
45 if let Some(ws) = workspace {
46 use super::types::{ResourceRef, Rights};
47 builder = builder.grant(
48 ResourceRef::Path {
49 pattern: format!("{ws}/**"),
50 },
51 vec![Rights::Read, Rights::Write, Rights::Execute],
52 );
53 }
54 }
55 _ => {
56 }
58 }
59
60 if let Some(domains) = extra_domains {
62 use super::types::{ResourceRef, Rights};
63 for domain in domains {
64 builder = builder.grant(
65 ResourceRef::KernelDomain {
66 domain: domain.clone(),
67 },
68 vec![Rights::Read, Rights::Write, Rights::Execute],
69 );
70 }
71 }
72
73 builder.build()
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use crate::security::capability::types::{ResourceRef, Rights};
80
81 #[test]
82 fn test_resolve_standard() {
83 let id = Uuid::new_v4();
84 let cs = resolve_cspace(Some("standard"), None, None, id);
85 assert!(cs.can(
86 &ResourceRef::KernelDomain {
87 domain: "read".into()
88 },
89 Rights::Execute
90 ));
91 assert!(cs.can(
92 &ResourceRef::KernelDomain {
93 domain: "memory".into()
94 },
95 Rights::Read
96 ));
97 }
98
99 #[test]
100 fn test_resolve_admin() {
101 let id = Uuid::new_v4();
102 let cs = resolve_cspace(Some("admin"), None, None, id);
103 assert!(cs.can(
104 &ResourceRef::KernelDomain {
105 domain: "anything".into()
106 },
107 Rights::Grant
108 ));
109 }
110
111 #[test]
112 fn test_resolve_worker() {
113 let id = Uuid::new_v4();
114 let cs = resolve_cspace(Some("worker"), None, None, id);
115 assert!(cs.can(
116 &ResourceRef::KernelDomain {
117 domain: "subagent".into()
118 },
119 Rights::Execute
120 ));
121 }
122
123 #[test]
124 fn test_resolve_unknown_is_empty() {
125 let id = Uuid::new_v4();
126 let cs = resolve_cspace(Some("nonexistent"), None, None, id);
127 assert!(cs.is_empty());
128 }
129
130 #[test]
131 fn test_resolve_with_workspace() {
132 let id = Uuid::new_v4();
133 let cs = resolve_cspace(Some("standard"), Some("/my/project"), None, id);
134 assert!(cs.can(
135 &ResourceRef::Path {
136 pattern: "/my/project/src/lib.rs".into()
137 },
138 Rights::Read
139 ));
140 }
141
142 #[test]
143 fn test_resolve_with_extra_domains() {
144 let id = Uuid::new_v4();
145 let cs = resolve_cspace(
146 Some("standard"),
147 None,
148 Some(&["custom_tool".to_string()]),
149 id,
150 );
151 assert!(cs.can(
152 &ResourceRef::KernelDomain {
153 domain: "custom_tool".into()
154 },
155 Rights::Execute
156 ));
157 }
158}