Skip to main content

this_me/kernel/
execute.rs

1use std::collections::BTreeMap;
2use std::fmt;
3
4use super::{
5    path_starts_with, unwrap_secret_v1, ExplainResult, InspectMemory, InspectResult, IntoPath,
6    Kernel, KernelError, KernelEvent, Memory, P256PrivateKey, Path, RecomputeMode, Snapshot,
7    StoredWrappedKey, Value, WrappedSecretCleartext, WrappedSecretError, WrappedSecretOutput,
8};
9
10#[derive(Debug, Clone, PartialEq)]
11pub struct MeTargetAst {
12    pub scheme: String,
13    pub namespace: String,
14    pub operation: String,
15    pub path: String,
16    pub raw: Option<String>,
17    pub context_raw: Option<String>,
18}
19
20#[derive(Debug, Clone, PartialEq)]
21pub enum ExecuteValue {
22    None,
23    Value(Value),
24    Memories(Vec<Memory>),
25    Events(Vec<KernelEvent>),
26    Snapshot(Snapshot),
27    Inspect(InspectResult),
28    Explain(ExplainResult),
29    Mode(RecomputeMode),
30    KeySpaceManifest(BTreeMap<String, StoredWrappedKey>),
31    WrappedKey(Value),
32    WrappedKeyWrite {
33        envelope: Value,
34        recipient_key_id: Option<String>,
35    },
36    WrappedKeyOpenOptions {
37        recipient_key_id: Option<String>,
38        recipient_private_key: Option<P256PrivateKey>,
39        output: WrappedSecretOutput,
40    },
41    RecipientPrivateKey(Vec<u8>),
42    Bytes(Vec<u8>),
43}
44
45#[derive(Debug, Clone, PartialEq)]
46pub enum ExecuteError {
47    Kernel(KernelError),
48    EmptyTarget,
49    InvalidTarget(String),
50    MissingNamespace(String),
51    MissingNamespaceBeforeContext(String),
52    MissingOperation(String),
53    MalformedContext(String),
54    MissingBody(&'static str),
55    InvalidBody(&'static str),
56    UnsupportedNamespace(String),
57    UnsupportedSelfOperation(String),
58    UnsupportedKernelOperation(String),
59    UnsupportedKernelPath { operation: String, path: String },
60    UnsupportedKeysOperation(String),
61    EmptyRecipientKeyId,
62    EmptyKeyId(&'static str),
63    KeySpaceNotFound(String),
64    InvalidWrappedKeyEnvelope,
65    NoRecipientPrivateKey(String),
66    SelfWriteRequiresPath,
67    SelfExplainRequiresPath,
68}
69
70impl fmt::Display for ExecuteError {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        match self {
73            Self::Kernel(error) => write!(f, "{error}"),
74            Self::EmptyTarget => write!(f, "execute(...) received an empty me target"),
75            Self::InvalidTarget(target) => write!(
76                f,
77                "invalid me target \"{target}\": expected \":\" between namespace and operation"
78            ),
79            Self::MissingNamespace(target) => {
80                write!(f, "invalid me target \"{target}\": missing namespace")
81            }
82            Self::MissingNamespaceBeforeContext(target) => write!(
83                f,
84                "invalid me target \"{target}\": missing namespace before context"
85            ),
86            Self::MissingOperation(target) => {
87                write!(f, "invalid me target \"{target}\": missing operation")
88            }
89            Self::MalformedContext(target) => {
90                write!(f, "invalid me target \"{target}\": malformed context segment")
91            }
92            Self::MissingBody(message) => write!(f, "{message}"),
93            Self::InvalidBody(message) => write!(f, "{message}"),
94            Self::UnsupportedNamespace(namespace) => write!(
95                f,
96                "external me target \"{namespace}\" must be resolved by cleaker or monad.ai before reaching the local kernel"
97            ),
98            Self::UnsupportedSelfOperation(operation) => {
99                write!(f, "unsupported self operation: {operation}")
100            }
101            Self::UnsupportedKernelOperation(operation) => {
102                write!(f, "unsupported kernel operation: {operation}")
103            }
104            Self::UnsupportedKernelPath { operation, path } => write!(
105                f,
106                "unsupported kernel:{operation} path: {}",
107                if path.is_empty() { "<root>" } else { path }
108            ),
109            Self::UnsupportedKeysOperation(operation) => {
110                write!(f, "unsupported keys operation: {operation}")
111            }
112            Self::EmptyRecipientKeyId => {
113                write!(f, "install_recipient_key(...) requires a recipient key id")
114            }
115            Self::EmptyKeyId(message) => write!(f, "{message}"),
116            Self::KeySpaceNotFound(key_id) => write!(f, "key space \"{key_id}\" was not found"),
117            Self::InvalidWrappedKeyEnvelope => {
118                write!(f, "store_wrapped_key(...) requires a valid WrappedSecretV1 envelope")
119            }
120            Self::NoRecipientPrivateKey(key_id) => write!(
121                f,
122                "no recipient private key is available to open \"{key_id}\". Install one first or pass it inline"
123            ),
124            Self::SelfWriteRequiresPath => write!(f, "self:write requires a semantic path"),
125            Self::SelfExplainRequiresPath => write!(f, "self:explain requires a semantic path"),
126        }
127    }
128}
129
130impl std::error::Error for ExecuteError {}
131
132impl From<KernelError> for ExecuteError {
133    fn from(error: KernelError) -> Self {
134        Self::Kernel(error)
135    }
136}
137
138impl From<WrappedSecretError> for ExecuteError {
139    fn from(error: WrappedSecretError) -> Self {
140        match error {
141            WrappedSecretError::InvalidEnvelope => Self::InvalidWrappedKeyEnvelope,
142            _ => Self::InvalidBody("wrapped secret cryptographic operation failed"),
143        }
144    }
145}
146
147impl From<Value> for ExecuteValue {
148    fn from(value: Value) -> Self {
149        Self::Value(value)
150    }
151}
152
153impl From<&str> for ExecuteValue {
154    fn from(value: &str) -> Self {
155        Self::Value(Value::from(value))
156    }
157}
158
159impl From<String> for ExecuteValue {
160    fn from(value: String) -> Self {
161        Self::Value(Value::from(value))
162    }
163}
164
165impl From<bool> for ExecuteValue {
166    fn from(value: bool) -> Self {
167        Self::Value(Value::from(value))
168    }
169}
170
171impl From<u64> for ExecuteValue {
172    fn from(value: u64) -> Self {
173        Self::Value(Value::from(value))
174    }
175}
176
177impl From<i64> for ExecuteValue {
178    fn from(value: i64) -> Self {
179        Self::Value(Value::from(value))
180    }
181}
182
183impl From<f64> for ExecuteValue {
184    fn from(value: f64) -> Self {
185        Self::Value(Value::from(value))
186    }
187}
188
189impl Kernel {
190    pub fn execute(
191        &mut self,
192        raw_target: impl AsRef<str>,
193        body: Option<ExecuteValue>,
194    ) -> Result<ExecuteValue, ExecuteError> {
195        let target = parse_executable_target(raw_target.as_ref())?;
196
197        match target.namespace.as_str() {
198            "self" => self.handle_self_target(&target.operation, &target.path, body),
199            "kernel" => self.handle_kernel_target(&target.operation, &target.path, body),
200            namespace => Err(ExecuteError::UnsupportedNamespace(namespace.to_string())),
201        }
202    }
203
204    pub fn execute_ast(
205        &mut self,
206        target: MeTargetAst,
207        body: Option<ExecuteValue>,
208    ) -> Result<ExecuteValue, ExecuteError> {
209        if target.namespace.trim().is_empty() {
210            return Err(ExecuteError::MissingNamespace(
211                target.raw.unwrap_or_else(|| "<ast>".to_string()),
212            ));
213        }
214        if target.operation.trim().is_empty() {
215            return Err(ExecuteError::MissingOperation(
216                target.raw.unwrap_or_else(|| "<ast>".to_string()),
217            ));
218        }
219
220        let namespace = target.namespace.trim().to_string();
221        let operation = target.operation.trim().to_ascii_lowercase();
222        match namespace.as_str() {
223            "self" => self.handle_self_target(&operation, target.path.trim(), body),
224            "kernel" => self.handle_kernel_target(&operation, target.path.trim(), body),
225            namespace => Err(ExecuteError::UnsupportedNamespace(namespace.to_string())),
226        }
227    }
228
229    fn handle_self_target(
230        &mut self,
231        operation: &str,
232        raw_path: &str,
233        body: Option<ExecuteValue>,
234    ) -> Result<ExecuteValue, ExecuteError> {
235        if let Some(key_id) = parse_keyspace_path(raw_path) {
236            return self.handle_keyspace_target(operation, key_id.as_deref(), body);
237        }
238
239        let path = normalize_executable_path_inner(raw_path)?;
240
241        match operation {
242            "read" => Ok(self
243                .read(path.parts)
244                .cloned()
245                .map(ExecuteValue::Value)
246                .unwrap_or(ExecuteValue::None)),
247            "write" => {
248                if path.parts.is_empty() {
249                    return Err(ExecuteError::SelfWriteRequiresPath);
250                }
251                let value = expect_value_body(body, "self:write requires a body payload")?;
252                self.postulate(path.parts, value.clone())?;
253                Ok(ExecuteValue::Value(value))
254            }
255            "inspect" => Ok(ExecuteValue::Inspect(self.inspect_at_path(&path.parts))),
256            "explain" => {
257                if path.parts.is_empty() {
258                    return Err(ExecuteError::SelfExplainRequiresPath);
259                }
260                Ok(ExecuteValue::Explain(self.explain(path.parts)?))
261            }
262            operation => Err(ExecuteError::UnsupportedSelfOperation(
263                operation.to_string(),
264            )),
265        }
266    }
267
268    fn handle_kernel_target(
269        &mut self,
270        operation: &str,
271        raw_path: &str,
272        body: Option<ExecuteValue>,
273    ) -> Result<ExecuteValue, ExecuteError> {
274        let path = normalize_executable_path_inner(raw_path)?;
275        let key = path.key;
276
277        match operation {
278            "read" => self.handle_kernel_read(&key),
279            "drain" => self.handle_kernel_drain(&path.parts, &key),
280            "export" => self.handle_kernel_export(&key),
281            "import" => {
282                let snapshot = expect_snapshot_body(body, "kernel:import requires a payload")?;
283                *self = Kernel::hydrate(snapshot)?;
284                Ok(ExecuteValue::Snapshot(self.export_snapshot()))
285            }
286            "hydrate" => {
287                let snapshot = expect_snapshot_body(body, "kernel:hydrate requires a payload")?;
288                *self = Kernel::hydrate(snapshot)?;
289                Ok(ExecuteValue::Snapshot(self.export_snapshot()))
290            }
291            "replay" => {
292                let memories = expect_memories_body(body, "kernel:replay requires a payload")?;
293                self.replay_memories(memories)?;
294                Ok(ExecuteValue::Memories(self.memories().to_vec()))
295            }
296            "rehydrate" => {
297                let snapshot = expect_snapshot_body(body, "kernel:rehydrate requires a payload")?;
298                *self = Kernel::hydrate(snapshot)?;
299                Ok(ExecuteValue::Snapshot(self.export_snapshot()))
300            }
301            "get" => self.handle_kernel_get(&key),
302            "set" => self.handle_kernel_set(&key, body),
303            operation => Err(ExecuteError::UnsupportedKernelOperation(
304                operation.to_string(),
305            )),
306        }
307    }
308
309    fn handle_kernel_read(&self, key: &str) -> Result<ExecuteValue, ExecuteError> {
310        if let Some(path) = event_filter_path(key) {
311            return Ok(ExecuteValue::Events(self.events_matching(path)?));
312        }
313
314        match key {
315            "memory" | "memories" | "logs" => Ok(ExecuteValue::Memories(self.memories().to_vec())),
316            "events" => Ok(ExecuteValue::Events(self.events().to_vec())),
317            "snapshot" => Ok(ExecuteValue::Snapshot(self.export_snapshot())),
318            "mode" | "recompute.mode" => Ok(ExecuteValue::Mode(self.recompute_mode())),
319            _ => Err(ExecuteError::UnsupportedKernelPath {
320                operation: "read".to_string(),
321                path: key.to_string(),
322            }),
323        }
324    }
325
326    fn handle_kernel_drain(
327        &mut self,
328        parts: &[String],
329        key: &str,
330    ) -> Result<ExecuteValue, ExecuteError> {
331        if parts.first().map(String::as_str) == Some("events") && parts.len() > 1 {
332            return Ok(ExecuteValue::Events(
333                self.drain_events_matching(parts[1..].to_vec())?,
334            ));
335        }
336
337        match key {
338            "events" => Ok(ExecuteValue::Events(self.drain_events())),
339            _ => Err(ExecuteError::UnsupportedKernelPath {
340                operation: "drain".to_string(),
341                path: key.to_string(),
342            }),
343        }
344    }
345
346    fn handle_kernel_export(&self, key: &str) -> Result<ExecuteValue, ExecuteError> {
347        match key {
348            "memory" | "memories" | "logs" => Ok(ExecuteValue::Memories(self.memories().to_vec())),
349            "snapshot" => Ok(ExecuteValue::Snapshot(self.export_snapshot())),
350            _ => Err(ExecuteError::UnsupportedKernelPath {
351                operation: "export".to_string(),
352                path: key.to_string(),
353            }),
354        }
355    }
356
357    fn handle_kernel_get(&self, key: &str) -> Result<ExecuteValue, ExecuteError> {
358        match key {
359            "mode" | "recompute.mode" => Ok(ExecuteValue::Mode(self.recompute_mode())),
360            _ => Err(ExecuteError::UnsupportedKernelPath {
361                operation: "get".to_string(),
362                path: key.to_string(),
363            }),
364        }
365    }
366
367    fn handle_kernel_set(
368        &mut self,
369        key: &str,
370        body: Option<ExecuteValue>,
371    ) -> Result<ExecuteValue, ExecuteError> {
372        match key {
373            "mode" | "recompute.mode" => {
374                let mode = expect_recompute_mode_body(body)?;
375                self.set_recompute_mode(mode);
376                Ok(ExecuteValue::Mode(self.recompute_mode()))
377            }
378            _ => Err(ExecuteError::UnsupportedKernelPath {
379                operation: "set".to_string(),
380                path: key.to_string(),
381            }),
382        }
383    }
384
385    fn inspect_at_path(&self, scope: &[String]) -> InspectResult {
386        if scope.is_empty() {
387            return self.inspect();
388        }
389
390        let snapshot = self.inspect();
391        InspectResult {
392            memories: snapshot
393                .memories
394                .into_iter()
395                .filter(|memory| matches_scope(&memory.path, scope))
396                .collect::<Vec<InspectMemory>>(),
397            index: snapshot
398                .index
399                .into_iter()
400                .filter(|(path, _)| matches_scope(path, scope))
401                .collect::<BTreeMap<Path, Value>>(),
402            secret_scopes: snapshot
403                .secret_scopes
404                .into_iter()
405                .filter(|path| matches_scope(path, scope))
406                .collect(),
407            noise_scopes: snapshot
408                .noise_scopes
409                .into_iter()
410                .filter(|path| matches_scope(path, scope))
411                .collect(),
412            derivations: snapshot
413                .derivations
414                .into_iter()
415                .filter(|path| matches_scope(path, scope))
416                .collect(),
417        }
418    }
419
420    pub fn install_recipient_key(
421        &mut self,
422        recipient_key_id: &str,
423        private_key: impl Into<Vec<u8>>,
424    ) -> Result<&mut Self, ExecuteError> {
425        let key_id = recipient_key_id.trim();
426        if key_id.is_empty() {
427            return Err(ExecuteError::EmptyRecipientKeyId);
428        }
429        let private_key = P256PrivateKey::from_slice(&private_key.into()).map_err(|_| {
430            ExecuteError::InvalidBody("recipient private key must be a P-256 scalar")
431        })?;
432        self.recipient_keyring
433            .insert(key_id.to_string(), private_key);
434        Ok(self)
435    }
436
437    pub fn uninstall_recipient_key(&mut self, recipient_key_id: &str) -> &mut Self {
438        let key_id = recipient_key_id.trim();
439        if !key_id.is_empty() {
440            self.recipient_keyring.remove(key_id);
441        }
442        self
443    }
444
445    pub fn store_wrapped_key(
446        &mut self,
447        key_id: &str,
448        envelope: Value,
449        recipient_key_id: Option<String>,
450    ) -> Result<&mut Self, ExecuteError> {
451        let normalized_key_id = key_id.trim();
452        if normalized_key_id.is_empty() {
453            return Err(ExecuteError::EmptyKeyId(
454                "store_wrapped_key(...) requires a key id",
455            ));
456        }
457        ensure_wrapped_secret_v1_envelope(&envelope)?;
458        self.key_spaces.insert(
459            normalized_key_id.to_string(),
460            StoredWrappedKey {
461                envelope,
462                recipient_key_id,
463            },
464        );
465        Ok(self)
466    }
467
468    pub fn read_wrapped_key(&self, key_id: &str) -> Result<Value, ExecuteError> {
469        let Some(entry) = self.key_spaces.get(key_id) else {
470            return Err(ExecuteError::KeySpaceNotFound(key_id.to_string()));
471        };
472        Ok(entry.envelope.clone())
473    }
474
475    pub fn key_space_manifest(&self) -> BTreeMap<String, StoredWrappedKey> {
476        self.key_spaces.clone()
477    }
478
479    fn handle_keyspace_target(
480        &mut self,
481        operation: &str,
482        key_id: Option<&str>,
483        body: Option<ExecuteValue>,
484    ) -> Result<ExecuteValue, ExecuteError> {
485        match operation {
486            "read" => {
487                if let Some(key_id) = key_id {
488                    Ok(ExecuteValue::WrappedKey(self.read_wrapped_key(key_id)?))
489                } else {
490                    Ok(ExecuteValue::KeySpaceManifest(self.key_space_manifest()))
491                }
492            }
493            "write" => {
494                let Some(key_id) = key_id else {
495                    return Err(ExecuteError::EmptyKeyId(
496                        "self:write/keys requires a key id",
497                    ));
498                };
499                let (envelope, recipient_key_id) = expect_wrapped_key_write_body(body)?;
500                self.store_wrapped_key(key_id, envelope.clone(), recipient_key_id)?;
501                Ok(ExecuteValue::WrappedKey(envelope))
502            }
503            "open" | "use" => {
504                let Some(key_id) = key_id else {
505                    return Err(ExecuteError::EmptyKeyId("self:open/keys requires a key id"));
506                };
507                let entry = self
508                    .key_spaces
509                    .get(key_id)
510                    .ok_or_else(|| ExecuteError::KeySpaceNotFound(key_id.to_string()))?;
511                let (inline_private_key, recipient_key_id, output) = match body {
512                    Some(ExecuteValue::WrappedKeyOpenOptions {
513                        recipient_key_id,
514                        recipient_private_key,
515                        output,
516                    }) => (recipient_private_key, recipient_key_id, output),
517                    Some(ExecuteValue::RecipientPrivateKey(private_key)) => (
518                        Some(P256PrivateKey::from_slice(&private_key).map_err(|_| {
519                            ExecuteError::InvalidBody(
520                                "recipient private key must be a P-256 scalar",
521                            )
522                        })?),
523                        None,
524                        WrappedSecretOutput::Bytes,
525                    ),
526                    Some(_) => {
527                        return Err(ExecuteError::InvalidBody(
528                            "self:open/keys expects recipient private key material",
529                        ))
530                    }
531                    None => (None, None, WrappedSecretOutput::Bytes),
532                };
533                let resolved_recipient_key_id = recipient_key_id
534                    .as_ref()
535                    .or(entry.recipient_key_id.as_ref());
536                let private_key = inline_private_key.or_else(|| {
537                    resolved_recipient_key_id
538                        .and_then(|key_id| self.recipient_keyring.get(key_id).cloned())
539                });
540                let Some(private_key) = private_key else {
541                    return Err(ExecuteError::NoRecipientPrivateKey(key_id.to_string()));
542                };
543                match unwrap_secret_v1(&entry.envelope, &private_key, output)? {
544                    WrappedSecretCleartext::Bytes(bytes) => Ok(ExecuteValue::Bytes(bytes)),
545                    WrappedSecretCleartext::Utf8(text) => {
546                        Ok(ExecuteValue::Value(Value::from(text)))
547                    }
548                }
549            }
550            operation => Err(ExecuteError::UnsupportedKeysOperation(
551                operation.to_string(),
552            )),
553        }
554    }
555}
556
557#[derive(Debug, Clone, PartialEq, Eq)]
558struct ExecutablePath {
559    key: String,
560    parts: Path,
561}
562
563pub fn parse_executable_target(raw_target: &str) -> Result<MeTargetAst, ExecuteError> {
564    let raw = raw_target.trim();
565    if raw.is_empty() {
566        return Err(ExecuteError::EmptyTarget);
567    }
568
569    let without_scheme = raw.strip_prefix("me://").unwrap_or(raw);
570    let Some(colon_index) = find_top_level_colon(without_scheme) else {
571        return Err(ExecuteError::InvalidTarget(raw.to_string()));
572    };
573
574    let namespace_with_context = without_scheme[..colon_index].trim();
575    let rhs = without_scheme[colon_index + 1..].trim();
576    if namespace_with_context.is_empty() {
577        return Err(ExecuteError::MissingNamespace(raw.to_string()));
578    }
579    if rhs.is_empty() {
580        return Err(ExecuteError::MissingOperation(raw.to_string()));
581    }
582
583    let slash_index = rhs.find('/');
584    let operation = slash_index
585        .map(|index| &rhs[..index])
586        .unwrap_or(rhs)
587        .trim()
588        .to_ascii_lowercase();
589    let path = slash_index
590        .map(|index| &rhs[index + 1..])
591        .unwrap_or("")
592        .trim()
593        .to_string();
594    if operation.is_empty() {
595        return Err(ExecuteError::MissingOperation(raw.to_string()));
596    }
597
598    let (namespace, context_raw) = split_target_namespace(namespace_with_context, raw)?;
599    Ok(MeTargetAst {
600        scheme: "me".to_string(),
601        namespace,
602        operation,
603        path,
604        raw: Some(raw.to_string()),
605        context_raw,
606    })
607}
608
609pub fn normalize_executable_path(raw_path: &str) -> Result<(String, Path), ExecuteError> {
610    let path = normalize_executable_path_inner(raw_path)?;
611    Ok((path.key, path.parts))
612}
613
614pub fn parse_keyspace_path(raw_path: &str) -> Option<Option<String>> {
615    let trimmed = raw_path.trim().trim_matches('/');
616    if trimmed.is_empty() {
617        return None;
618    }
619    if trimmed == "keys" {
620        return Some(None);
621    }
622    if let Some(key_id) = trimmed.strip_prefix("keys/") {
623        return Some(non_empty_key_id(key_id));
624    }
625    trimmed.strip_prefix("keys.").map(non_empty_key_id)
626}
627
628fn normalize_executable_path_inner(raw_path: &str) -> Result<ExecutablePath, ExecuteError> {
629    let dotted = raw_path
630        .trim()
631        .trim_matches('/')
632        .replace('/', ".")
633        .trim()
634        .to_string();
635    if dotted.is_empty() {
636        return Ok(ExecutablePath {
637            key: String::new(),
638            parts: Vec::new(),
639        });
640    }
641    let parts = dotted.into_path().map_err(KernelError::InvalidPath)?;
642    Ok(ExecutablePath {
643        key: parts.join("."),
644        parts,
645    })
646}
647
648fn event_filter_path(key: &str) -> Option<String> {
649    key.strip_prefix("events.")
650        .map(str::to_string)
651        .or_else(|| key.strip_prefix("events/").map(str::to_string))
652}
653
654fn split_target_namespace(
655    namespace_with_context: &str,
656    raw_target: &str,
657) -> Result<(String, Option<String>), ExecuteError> {
658    let Some(open_index) = namespace_with_context.find('[') else {
659        return Ok((namespace_with_context.to_string(), None));
660    };
661
662    let close_index = namespace_with_context.rfind(']');
663    if close_index
664        .is_none_or(|index| index < open_index || index != namespace_with_context.len() - 1)
665    {
666        return Err(ExecuteError::MalformedContext(raw_target.to_string()));
667    }
668    let close_index = close_index.expect("checked above");
669    let namespace = namespace_with_context[..open_index].trim();
670    if namespace.is_empty() {
671        return Err(ExecuteError::MissingNamespaceBeforeContext(
672            raw_target.to_string(),
673        ));
674    }
675    let context_raw = namespace_with_context[open_index + 1..close_index].trim();
676    Ok((
677        namespace.to_string(),
678        (!context_raw.is_empty()).then(|| context_raw.to_string()),
679    ))
680}
681
682fn find_top_level_colon(value: &str) -> Option<usize> {
683    let mut bracket_depth = 0_u32;
684    let mut quote = None;
685    let mut escaped = false;
686
687    for (index, ch) in value.char_indices() {
688        if escaped {
689            escaped = false;
690            continue;
691        }
692        if let Some(expected_quote) = quote {
693            if ch == '\\' {
694                escaped = true;
695            } else if ch == expected_quote {
696                quote = None;
697            }
698            continue;
699        }
700
701        match ch {
702            '"' | '\'' => quote = Some(ch),
703            '[' => bracket_depth += 1,
704            ']' => bracket_depth = bracket_depth.saturating_sub(1),
705            ':' if bracket_depth == 0 => return Some(index),
706            _ => {}
707        }
708    }
709
710    None
711}
712
713fn expect_value_body(
714    body: Option<ExecuteValue>,
715    missing_message: &'static str,
716) -> Result<Value, ExecuteError> {
717    match body {
718        Some(ExecuteValue::Value(value)) => Ok(value),
719        None => Err(ExecuteError::MissingBody(missing_message)),
720        _ => Err(ExecuteError::InvalidBody(
721            "expected a semantic value payload",
722        )),
723    }
724}
725
726fn expect_snapshot_body(
727    body: Option<ExecuteValue>,
728    missing_message: &'static str,
729) -> Result<Snapshot, ExecuteError> {
730    match body {
731        Some(ExecuteValue::Snapshot(snapshot)) => Ok(snapshot),
732        None => Err(ExecuteError::MissingBody(missing_message)),
733        _ => Err(ExecuteError::InvalidBody("expected a snapshot payload")),
734    }
735}
736
737fn expect_memories_body(
738    body: Option<ExecuteValue>,
739    missing_message: &'static str,
740) -> Result<Vec<Memory>, ExecuteError> {
741    match body {
742        Some(ExecuteValue::Memories(memories)) => Ok(memories),
743        None => Err(ExecuteError::MissingBody(missing_message)),
744        _ => Err(ExecuteError::InvalidBody("expected a memory log payload")),
745    }
746}
747
748fn expect_recompute_mode_body(body: Option<ExecuteValue>) -> Result<RecomputeMode, ExecuteError> {
749    match body {
750        Some(ExecuteValue::Mode(mode)) => Ok(mode),
751        Some(ExecuteValue::Value(Value::String(mode))) if mode == "eager" => {
752            Ok(RecomputeMode::Eager)
753        }
754        Some(ExecuteValue::Value(Value::String(mode))) if mode == "lazy" => Ok(RecomputeMode::Lazy),
755        None => Err(ExecuteError::MissingBody("kernel:set requires a payload")),
756        _ => Err(ExecuteError::InvalidBody(
757            "kernel:set/recompute.mode only accepts \"eager\" or \"lazy\"",
758        )),
759    }
760}
761
762fn expect_wrapped_key_write_body(
763    body: Option<ExecuteValue>,
764) -> Result<(Value, Option<String>), ExecuteError> {
765    match body {
766        Some(ExecuteValue::WrappedKeyWrite {
767            envelope,
768            recipient_key_id,
769        }) => {
770            ensure_wrapped_secret_v1_envelope(&envelope)?;
771            Ok((envelope, recipient_key_id))
772        }
773        Some(ExecuteValue::WrappedKey(envelope)) | Some(ExecuteValue::Value(envelope)) => {
774            ensure_wrapped_secret_v1_envelope(&envelope)?;
775            Ok((envelope, None))
776        }
777        None => Err(ExecuteError::MissingBody(
778            "self:write/keys requires a payload",
779        )),
780        _ => Err(ExecuteError::InvalidBody(
781            "self:write/keys expects a wrapped key envelope payload",
782        )),
783    }
784}
785
786fn ensure_wrapped_secret_v1_envelope(envelope: &Value) -> Result<(), ExecuteError> {
787    let Value::Object(object) = envelope else {
788        return Err(ExecuteError::InvalidWrappedKeyEnvelope);
789    };
790    if object.get("version") != Some(&Value::from(1_u64)) {
791        return Err(ExecuteError::InvalidWrappedKeyEnvelope);
792    }
793    if !object.contains_key("kid") || !object.contains_key("encryption") {
794        return Err(ExecuteError::InvalidWrappedKeyEnvelope);
795    }
796    Ok(())
797}
798
799fn non_empty_key_id(key_id: &str) -> Option<String> {
800    let key_id = key_id.trim();
801    (!key_id.is_empty()).then(|| key_id.to_string())
802}
803
804fn matches_scope(candidate: &[String], scope: &[String]) -> bool {
805    candidate == scope || path_starts_with(candidate, scope)
806}