1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum BuiltinExposure {
11 Undeclared,
14 PureGlobal,
16 CapabilityFunction { authority_argument: u16 },
20 HarnessMethod {
22 capability: CapabilityId,
23 method: &'static str,
24 },
25 PrivilegedWire,
28 RuntimeInternal,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
34pub enum CapabilityId {
35 Stdio,
36 Term,
37 Clock,
38 Fs,
39 Env,
40 Random,
41 Net,
42 Process,
43 Channels,
44 System,
45 Secrets,
46 Llm,
47 Agent,
48 Tenant,
49 Auth,
50 Observability,
51 Verdict,
52 Tools,
53 Ast,
54 CodeIndex,
55 Computer,
56 Embed,
57 Memory,
58 Sqlite,
59 Postgres,
60 FsWatch,
61 HostLease,
62 Scanner,
63 SecretStore,
64 TerminalSession,
65 Rules,
66 Lint,
67 Runtime,
68 Interaction,
69 Project,
70 Testing,
71}
72
73impl CapabilityId {
74 pub const fn variant_name(self) -> &'static str {
76 match self {
77 Self::Stdio => "Stdio",
78 Self::Term => "Term",
79 Self::Clock => "Clock",
80 Self::Fs => "Fs",
81 Self::Env => "Env",
82 Self::Random => "Random",
83 Self::Net => "Net",
84 Self::Process => "Process",
85 Self::Channels => "Channels",
86 Self::System => "System",
87 Self::Secrets => "Secrets",
88 Self::Llm => "Llm",
89 Self::Agent => "Agent",
90 Self::Tenant => "Tenant",
91 Self::Auth => "Auth",
92 Self::Observability => "Observability",
93 Self::Verdict => "Verdict",
94 Self::Tools => "Tools",
95 Self::Ast => "Ast",
96 Self::CodeIndex => "CodeIndex",
97 Self::Computer => "Computer",
98 Self::Embed => "Embed",
99 Self::Memory => "Memory",
100 Self::Sqlite => "Sqlite",
101 Self::Postgres => "Postgres",
102 Self::FsWatch => "FsWatch",
103 Self::HostLease => "HostLease",
104 Self::Scanner => "Scanner",
105 Self::SecretStore => "SecretStore",
106 Self::TerminalSession => "TerminalSession",
107 Self::Rules => "Rules",
108 Self::Lint => "Lint",
109 Self::Runtime => "Runtime",
110 Self::Interaction => "Interaction",
111 Self::Project => "Project",
112 Self::Testing => "Testing",
113 }
114 }
115
116 pub const ALL: &'static [Self] = &[
118 Self::Stdio,
119 Self::Term,
120 Self::Clock,
121 Self::Fs,
122 Self::Env,
123 Self::Random,
124 Self::Net,
125 Self::Process,
126 Self::Channels,
127 Self::System,
128 Self::Secrets,
129 Self::Llm,
130 Self::Agent,
131 Self::Tenant,
132 Self::Auth,
133 Self::Observability,
134 Self::Verdict,
135 Self::Tools,
136 Self::Ast,
137 Self::CodeIndex,
138 Self::Computer,
139 Self::Embed,
140 Self::Memory,
141 Self::Sqlite,
142 Self::Postgres,
143 Self::FsWatch,
144 Self::HostLease,
145 Self::Scanner,
146 Self::SecretStore,
147 Self::TerminalSession,
148 Self::Rules,
149 Self::Lint,
150 Self::Runtime,
151 Self::Interaction,
152 Self::Project,
153 Self::Testing,
154 ];
155
156 pub const fn field_name(self) -> &'static str {
158 match self {
159 Self::Stdio => "stdio",
160 Self::Term => "term",
161 Self::Clock => "clock",
162 Self::Fs => "fs",
163 Self::Env => "env",
164 Self::Random => "random",
165 Self::Net => "net",
166 Self::Process => "process",
167 Self::Channels => "channels",
168 Self::System => "system",
169 Self::Secrets => "secrets",
170 Self::Llm => "llm",
171 Self::Agent => "agent",
172 Self::Tenant => "tenant",
173 Self::Auth => "auth",
174 Self::Observability => "obs",
175 Self::Verdict => "verdict",
176 Self::Tools => "tools",
177 Self::Ast => "ast",
178 Self::CodeIndex => "code_index",
179 Self::Computer => "computer",
180 Self::Embed => "embed",
181 Self::Memory => "memory",
182 Self::Sqlite => "sqlite",
183 Self::Postgres => "postgres",
184 Self::FsWatch => "fs_watch",
185 Self::HostLease => "host_lease",
186 Self::Scanner => "scanner",
187 Self::SecretStore => "secret_store",
188 Self::TerminalSession => "terminal",
189 Self::Rules => "rules",
190 Self::Lint => "lint",
191 Self::Runtime => "runtime",
192 Self::Interaction => "interaction",
193 Self::Project => "project",
194 Self::Testing => "testing",
195 }
196 }
197
198 pub const fn type_name(self) -> &'static str {
200 match self {
201 Self::Stdio => "HarnessStdio",
202 Self::Term => "HarnessTerm",
203 Self::Clock => "HarnessClock",
204 Self::Fs => "HarnessFs",
205 Self::Env => "HarnessEnv",
206 Self::Random => "HarnessRandom",
207 Self::Net => "HarnessNet",
208 Self::Process => "HarnessProcess",
209 Self::Channels => "HarnessChannels",
210 Self::System => "HarnessSystem",
211 Self::Secrets => "HarnessSecrets",
212 Self::Llm => "HarnessLlm",
213 Self::Agent => "HarnessAgent",
214 Self::Tenant => "HarnessTenant",
215 Self::Auth => "HarnessAuth",
216 Self::Observability => "HarnessObs",
217 Self::Verdict => "HarnessVerdict",
218 Self::Tools => "HarnessTools",
219 Self::Ast => "HarnessAst",
220 Self::CodeIndex => "HarnessCodeIndex",
221 Self::Computer => "HarnessComputer",
222 Self::Embed => "HarnessEmbed",
223 Self::Memory => "HarnessMemory",
224 Self::Sqlite => "HarnessSqlite",
225 Self::Postgres => "HarnessPostgres",
226 Self::FsWatch => "HarnessFsWatch",
227 Self::HostLease => "HarnessHostLease",
228 Self::Scanner => "HarnessScanner",
229 Self::SecretStore => "HarnessSecretStore",
230 Self::TerminalSession => "HarnessTerminalSession",
231 Self::Rules => "HarnessRules",
232 Self::Lint => "HarnessLint",
233 Self::Runtime => "HarnessRuntime",
234 Self::Interaction => "HarnessInteraction",
235 Self::Project => "HarnessProject",
236 Self::Testing => "HarnessTesting",
237 }
238 }
239
240 pub const fn from_field_name(name: &str) -> Option<Self> {
242 match name.as_bytes() {
243 b"stdio" => Some(Self::Stdio),
244 b"term" => Some(Self::Term),
245 b"clock" => Some(Self::Clock),
246 b"fs" => Some(Self::Fs),
247 b"env" => Some(Self::Env),
248 b"random" => Some(Self::Random),
249 b"net" => Some(Self::Net),
250 b"process" => Some(Self::Process),
251 b"channels" => Some(Self::Channels),
252 b"system" => Some(Self::System),
253 b"secrets" => Some(Self::Secrets),
254 b"llm" => Some(Self::Llm),
255 b"agent" => Some(Self::Agent),
256 b"tenant" => Some(Self::Tenant),
257 b"auth" => Some(Self::Auth),
258 b"obs" => Some(Self::Observability),
259 b"verdict" => Some(Self::Verdict),
260 b"tools" => Some(Self::Tools),
261 b"ast" => Some(Self::Ast),
262 b"code_index" => Some(Self::CodeIndex),
263 b"computer" => Some(Self::Computer),
264 b"embed" => Some(Self::Embed),
265 b"memory" => Some(Self::Memory),
266 b"sqlite" => Some(Self::Sqlite),
267 b"postgres" => Some(Self::Postgres),
268 b"fs_watch" => Some(Self::FsWatch),
269 b"host_lease" => Some(Self::HostLease),
270 b"scanner" => Some(Self::Scanner),
271 b"secret_store" => Some(Self::SecretStore),
272 b"terminal" => Some(Self::TerminalSession),
273 b"rules" => Some(Self::Rules),
274 b"lint" => Some(Self::Lint),
275 b"runtime" => Some(Self::Runtime),
276 b"interaction" => Some(Self::Interaction),
277 b"project" => Some(Self::Project),
278 b"testing" => Some(Self::Testing),
279 _ => None,
280 }
281 }
282
283 pub fn from_type_name(name: &str) -> Option<Self> {
284 Self::ALL
285 .iter()
286 .copied()
287 .find(|capability| capability.type_name() == name)
288 }
289}
290
291#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
293pub enum EffectKind {
294 Stdio,
295 Fs,
296 Env,
297 Clock,
298 Random,
299 Network,
300 Process,
301 Llm,
302 Tool,
303 Mcp,
304 Host,
305 Worker,
306 Secret,
307 Observability,
308 Channel,
309 State,
310}
311
312#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
314pub enum EffectAccess {
315 Read,
316 Write,
317 Mutate,
318 Observe,
319}
320
321#[derive(Debug, Clone, Copy, PartialEq, Eq)]
326pub enum ResourceSelector {
327 Argument(u16),
329 Field {
331 argument: u16,
332 path: &'static [&'static str],
333 },
334 EachArgument(u16),
336 Constant(&'static str),
338 Dynamic,
341}
342
343#[derive(Debug, Clone, Copy, PartialEq, Eq)]
345pub struct EffectSpec {
346 pub kind: EffectKind,
347 pub access: EffectAccess,
348 pub resources: &'static [ResourceSelector],
349}
350
351impl EffectSpec {
352 pub const fn new(
353 kind: EffectKind,
354 access: EffectAccess,
355 resources: &'static [ResourceSelector],
356 ) -> Self {
357 Self {
358 kind,
359 access,
360 resources,
361 }
362 }
363}
364
365#[derive(Debug, Clone, Copy, PartialEq, Eq)]
368pub struct BuiltinContract {
369 pub exposure: BuiltinExposure,
370 pub effects: &'static [EffectSpec],
371}
372
373impl BuiltinContract {
374 pub const UNDECLARED: Self = Self {
375 exposure: BuiltinExposure::Undeclared,
376 effects: &[],
377 };
378
379 pub const PURE: Self = Self {
380 exposure: BuiltinExposure::PureGlobal,
381 effects: &[],
382 };
383
384 pub const RUNTIME_INTERNAL: Self = Self {
385 exposure: BuiltinExposure::RuntimeInternal,
386 effects: &[],
387 };
388
389 pub const fn harness(
390 capability: CapabilityId,
391 method: &'static str,
392 effects: &'static [EffectSpec],
393 ) -> Self {
394 Self {
395 exposure: BuiltinExposure::HarnessMethod { capability, method },
396 effects,
397 }
398 }
399
400 pub const fn capability_function(
401 authority_argument: u16,
402 effects: &'static [EffectSpec],
403 ) -> Self {
404 Self {
405 exposure: BuiltinExposure::CapabilityFunction { authority_argument },
406 effects,
407 }
408 }
409
410 pub const fn privileged_wire(effects: &'static [EffectSpec]) -> Self {
411 Self {
412 exposure: BuiltinExposure::PrivilegedWire,
413 effects,
414 }
415 }
416
417 pub const fn is_declared(self) -> bool {
418 !matches!(self.exposure, BuiltinExposure::Undeclared)
419 }
420
421 pub const fn is_pure(self) -> bool {
422 self.effects.is_empty()
423 }
424}