Skip to main content

this_me/kernel/
mod.rs

1use std::collections::{BTreeMap, BTreeSet, VecDeque};
2use std::fmt;
3use std::sync::Arc;
4
5mod evaluator;
6mod execute;
7mod json;
8mod path;
9mod proof;
10mod secret_material;
11mod wrapped_secret;
12
13use evaluator::{evaluate_expression, extract_expression_refs};
14pub use execute::{
15    normalize_executable_path, parse_executable_target, ExecuteError, ExecuteValue, MeTargetAst,
16};
17pub use json::{
18    execute_value_to_json, kernel_event_to_json, kernel_value_from_json, kernel_value_to_json,
19    memory_to_json, parse_kernel_value, proof_result_to_json, snapshot_from_json, snapshot_to_json,
20    JsonCodecError,
21};
22pub use path::{IntoPath, ParsedPath, Path, PathParseError, PathPart, Selector};
23pub use proof::{
24    derive_branch_proof_seed, derive_compound_seed, derive_identity_hash, normalize_proof_payload,
25    normalize_root_namespace, prove_with_timestamp, verify_ed25519_signature, ProofError,
26    ProofInput, ProofResult,
27};
28use secret_material::{
29    decrypt_blob_v3_cleartext, derive_blob_v3_keys, derive_secret_material_v3,
30    encrypt_blob_v3_cleartext, lineage_segment, random_blob_v3_nonce,
31};
32pub use secret_material::{BlobV3DerivedKeys, SecretMaterialPurpose};
33pub use wrapped_secret::{
34    export_p256_public_key_from_private, generate_p256_key_pair, unwrap_secret_v1, wrap_secret_v1,
35    P256KeyPair, P256PrivateKey, P256PublicKeyCoordinates, WrappedSecretCleartext,
36    WrappedSecretError, WrappedSecretOutput,
37};
38
39const V3_DOMAIN: &str = "this.me/blob/v3";
40const V3_NO_NOISE_SENTINEL: &str = "this.me/blob/v3/no-noise";
41
42#[derive(Debug, Clone, PartialEq)]
43pub enum Value {
44    Null,
45    Bool(bool),
46    Number(f64),
47    String(String),
48    Array(Vec<Value>),
49    Object(BTreeMap<String, Value>),
50    Pointer(Path),
51    Identity(String),
52}
53
54impl From<&str> for Value {
55    fn from(value: &str) -> Self {
56        Self::String(value.to_string())
57    }
58}
59
60impl From<String> for Value {
61    fn from(value: String) -> Self {
62        Self::String(value)
63    }
64}
65
66impl From<bool> for Value {
67    fn from(value: bool) -> Self {
68        Self::Bool(value)
69    }
70}
71
72impl From<i64> for Value {
73    fn from(value: i64) -> Self {
74        Self::Number(value as f64)
75    }
76}
77
78impl From<u64> for Value {
79    fn from(value: u64) -> Self {
80        Self::Number(value as f64)
81    }
82}
83
84impl From<f64> for Value {
85    fn from(value: f64) -> Self {
86        Self::Number(value)
87    }
88}
89
90#[derive(Debug, Clone, PartialEq)]
91pub struct Memory {
92    pub path: Path,
93    pub operator: Option<String>,
94    pub expression: Option<Value>,
95    pub value: Value,
96    pub prev_hash: Option<String>,
97    pub hash: String,
98}
99
100#[derive(Debug, Clone, PartialEq, Eq)]
101pub struct OperatorDefinition {
102    pub kind: String,
103}
104
105#[derive(Debug, Clone, PartialEq, Default)]
106pub struct Snapshot {
107    pub memories: Vec<Memory>,
108    pub local_secrets: BTreeMap<Path, String>,
109    pub local_noises: BTreeMap<Path, String>,
110    pub key_spaces: BTreeMap<String, StoredWrappedKey>,
111    pub operators: BTreeMap<String, OperatorDefinition>,
112}
113
114#[derive(Debug, Clone, PartialEq)]
115pub struct StoredWrappedKey {
116    pub envelope: Value,
117    pub recipient_key_id: Option<String>,
118}
119
120#[derive(Debug, Clone, PartialEq)]
121pub struct KernelEvent {
122    pub path: Path,
123    pub operator: Option<String>,
124    pub value: Option<Value>,
125    pub memory_hash: String,
126}
127
128#[derive(Debug, Clone, PartialEq)]
129pub struct InspectResult {
130    pub memories: Vec<InspectMemory>,
131    pub index: BTreeMap<Path, Value>,
132    pub secret_scopes: Vec<Path>,
133    pub noise_scopes: Vec<Path>,
134    pub derivations: Vec<Path>,
135}
136
137#[derive(Debug, Clone, PartialEq)]
138pub struct InspectMemory {
139    pub path: Path,
140    pub operator: Option<String>,
141    pub expression: Option<Value>,
142    pub value: Value,
143    pub prev_hash: Option<String>,
144    pub hash: String,
145}
146
147#[derive(Debug, Clone, PartialEq)]
148pub struct ExplainResult {
149    pub path: Path,
150    pub value: Option<Value>,
151    pub expr: Option<String>,
152    pub derivation: Option<ExplainDerivation>,
153    pub meta: ExplainMeta,
154}
155
156#[derive(Debug, Clone, PartialEq)]
157pub struct ExplainDerivation {
158    pub expression: String,
159    pub inputs: Vec<ExplainInput>,
160}
161
162#[derive(Debug, Clone, PartialEq)]
163pub struct ExplainInput {
164    pub label: String,
165    pub path: Path,
166    pub value: Option<Value>,
167    pub origin: ExplainOrigin,
168    pub masked: bool,
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq)]
172pub enum ExplainOrigin {
173    Public,
174    Secret,
175}
176
177#[derive(Debug, Clone, Copy, PartialEq, Eq)]
178pub enum SecretMaterialMode {
179    Branch,
180    Value,
181}
182
183#[derive(Debug, Clone, Copy, PartialEq, Eq)]
184pub enum RecomputeMode {
185    Eager,
186    Lazy,
187}
188
189#[derive(Debug, Clone, PartialEq, Eq)]
190pub struct ExplainMeta {
191    pub depends_on: Vec<Path>,
192    pub resolved_path: Path,
193    pub pointer_chain: Vec<Path>,
194    pub secret: bool,
195    pub k: usize,
196    pub recomputed: Vec<Path>,
197    pub source_path: Option<Path>,
198}
199
200#[derive(Debug, Clone, PartialEq, Eq)]
201pub enum KernelError {
202    EmptyPath,
203    EmptyExpression,
204    EmptyNoise,
205    EmptyOperator,
206    EmptyOperatorKind,
207    EmptyQuery,
208    EmptySecret,
209    InvalidPath(PathParseError),
210    InvalidIdentity(String),
211    NonFiniteNumber,
212    NoSecretContext(Path),
213    RandomUnavailable,
214    ReservedOperator(String),
215    SecretBlobDecryptFailed(Path),
216    RootSecretBranchUnsupported,
217    HydrationHashMismatch {
218        path: Path,
219        expected: String,
220        actual: String,
221    },
222    HydrationChainMismatch {
223        index: usize,
224        expected_prev_hash: Option<String>,
225        actual_prev_hash: Option<String>,
226    },
227}
228
229impl fmt::Display for KernelError {
230    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231        match self {
232            Self::EmptyPath => write!(f, "path cannot be empty"),
233            Self::EmptyExpression => write!(f, "expression cannot be empty"),
234            Self::EmptyNoise => write!(f, "noise cannot be empty"),
235            Self::EmptyOperator => write!(f, "operator cannot be empty"),
236            Self::EmptyOperatorKind => write!(f, "operator kind cannot be empty"),
237            Self::EmptyQuery => write!(f, "query must contain at least one path"),
238            Self::EmptySecret => write!(f, "secret cannot be empty"),
239            Self::InvalidPath(error) => write!(f, "invalid path: {error}"),
240            Self::InvalidIdentity(value) => write!(f, "invalid identity: {value}"),
241            Self::NonFiniteNumber => write!(f, "numbers must be finite"),
242            Self::NoSecretContext(path) => write!(
243                f,
244                "no secret context active for {}",
245                if path.is_empty() {
246                    "<root>".to_string()
247                } else {
248                    path.join(".")
249                }
250            ),
251            Self::RandomUnavailable => write!(f, "secure random bytes are unavailable"),
252            Self::ReservedOperator(operator) => {
253                write!(f, "operator {operator} is reserved")
254            }
255            Self::SecretBlobDecryptFailed(path) => write!(
256                f,
257                "secret blob decrypt failed for {}",
258                if path.is_empty() {
259                    "<root>".to_string()
260                } else {
261                    path.join(".")
262                }
263            ),
264            Self::RootSecretBranchUnsupported => {
265                write!(f, "branch v3 derivation does not support root secret scope")
266            }
267            Self::HydrationHashMismatch {
268                path,
269                expected,
270                actual,
271            } => write!(
272                f,
273                "memory hash mismatch at {}: expected {}, got {}",
274                path.join("."),
275                expected,
276                actual
277            ),
278            Self::HydrationChainMismatch {
279                index,
280                expected_prev_hash,
281                actual_prev_hash,
282            } => write!(
283                f,
284                "memory chain mismatch at index {}: expected prev_hash {:?}, got {:?}",
285                index, expected_prev_hash, actual_prev_hash
286            ),
287        }
288    }
289}
290
291impl std::error::Error for KernelError {}
292
293#[derive(Debug, Clone)]
294pub struct Kernel {
295    memories: Vec<Memory>,
296    index: BTreeMap<Path, Value>,
297    private_index: BTreeMap<Path, Value>,
298    secret_scopes: BTreeSet<Path>,
299    noise_scopes: BTreeSet<Path>,
300    local_secrets: BTreeMap<Path, String>,
301    local_noises: BTreeMap<Path, String>,
302    key_spaces: BTreeMap<String, StoredWrappedKey>,
303    recipient_keyring: BTreeMap<String, P256PrivateKey>,
304    derivations: BTreeMap<Path, DerivationRecord>,
305    ref_subscribers: BTreeMap<Path, BTreeSet<Path>>,
306    events: Vec<KernelEvent>,
307    active_identity: Option<String>,
308    seed: Option<String>,
309    identity_hash: Option<String>,
310    active_expression: Option<String>,
311    operators: BTreeMap<String, OperatorDefinition>,
312    last_recompute_wave_by_target: BTreeMap<Path, Arc<RecomputeWave>>,
313    active_recompute_wave: Option<RecomputeWave>,
314    recompute_mode: RecomputeMode,
315    path_version_clock: u64,
316    path_versions: BTreeMap<Path, u64>,
317}
318
319#[derive(Debug, Clone, PartialEq, Eq)]
320struct DerivationRecord {
321    eval_scope: Path,
322    expression: String,
323    refs: Vec<DerivationRef>,
324    ref_versions: BTreeMap<Path, u64>,
325}
326
327#[derive(Debug, Clone, PartialEq, Eq)]
328struct DerivationRef {
329    label: String,
330    path: Path,
331}
332
333#[derive(Debug, Clone, PartialEq, Eq)]
334struct RecomputeWave {
335    source_path: Path,
336    recomputed: BTreeSet<Path>,
337}
338
339#[derive(Debug, Clone, PartialEq, Eq)]
340struct PointerResolution {
341    resolved_path: Path,
342    pointer_chain: Vec<Path>,
343}
344
345impl Default for Kernel {
346    fn default() -> Self {
347        Self {
348            memories: Vec::new(),
349            index: BTreeMap::new(),
350            private_index: BTreeMap::new(),
351            secret_scopes: BTreeSet::new(),
352            noise_scopes: BTreeSet::new(),
353            local_secrets: BTreeMap::new(),
354            local_noises: BTreeMap::new(),
355            key_spaces: BTreeMap::new(),
356            recipient_keyring: BTreeMap::new(),
357            derivations: BTreeMap::new(),
358            ref_subscribers: BTreeMap::new(),
359            events: Vec::new(),
360            active_identity: None,
361            seed: None,
362            identity_hash: None,
363            active_expression: None,
364            operators: default_operators(),
365            last_recompute_wave_by_target: BTreeMap::new(),
366            active_recompute_wave: None,
367            recompute_mode: RecomputeMode::Eager,
368            path_version_clock: 0,
369            path_versions: BTreeMap::new(),
370        }
371    }
372}
373
374impl Kernel {
375    pub fn new() -> Self {
376        Self::default()
377    }
378
379    pub fn with_seed(seed: impl Into<String>) -> Self {
380        let mut kernel = Self::new();
381        kernel.set_seed(seed);
382        kernel
383    }
384
385    pub fn with_compound_seed(who: &str, secret: &str) -> Self {
386        let mut kernel = Self::new();
387        kernel.reseed_identity(who, secret);
388        kernel
389    }
390
391    pub fn memories(&self) -> &[Memory] {
392        &self.memories
393    }
394
395    pub fn set_seed(&mut self, seed: impl Into<String>) -> &mut Self {
396        let seed = seed.into();
397        self.identity_hash = Some(derive_identity_hash(&seed));
398        self.seed = Some(seed);
399        self
400    }
401
402    pub fn reseed_identity(&mut self, who: &str, secret: &str) -> &mut Self {
403        let seed = derive_compound_seed(who, secret);
404        self.identity_hash = Some(derive_identity_hash(&seed));
405        self.seed = Some(seed);
406        self.active_expression = Some(who.to_string());
407        self
408    }
409
410    pub fn identity_hash(&self) -> Option<&str> {
411        self.identity_hash.as_deref()
412    }
413
414    pub fn active_expression(&self) -> Option<&str> {
415        self.active_expression.as_deref()
416    }
417
418    pub fn set_active_expression(&mut self, expression: impl Into<Option<String>>) -> &mut Self {
419        self.active_expression = expression.into();
420        self
421    }
422
423    pub fn prove_with_timestamp(
424        &self,
425        input: ProofInput,
426        timestamp: u64,
427    ) -> Result<ProofResult, ProofError> {
428        let seed = self.seed.as_deref().ok_or(ProofError::EmptySeed)?;
429        let expression = self
430            .active_expression
431            .as_deref()
432            .ok_or(ProofError::ActiveExpressionRequired)?;
433        prove_with_timestamp(
434            seed,
435            expression,
436            &input.root_namespace,
437            input.challenge.as_deref(),
438            timestamp,
439        )
440    }
441
442    pub fn inspect(&self) -> InspectResult {
443        self.inspect_memories(self.memories.iter())
444    }
445
446    pub fn inspect_last(&self, last: usize) -> InspectResult {
447        if last == 0 || last >= self.memories.len() {
448            return self.inspect();
449        }
450        self.inspect_memories(self.memories[self.memories.len() - last..].iter())
451    }
452
453    pub fn active_identity(&self) -> Option<&str> {
454        self.active_identity.as_deref()
455    }
456
457    pub fn operators(&self) -> &BTreeMap<String, OperatorDefinition> {
458        &self.operators
459    }
460
461    pub fn events(&self) -> &[KernelEvent] {
462        &self.events
463    }
464
465    pub fn event_cursor(&self) -> usize {
466        self.events.len()
467    }
468
469    pub fn events_since(&self, cursor: usize) -> &[KernelEvent] {
470        let cursor = cursor.min(self.events.len());
471        &self.events[cursor..]
472    }
473
474    pub fn drain_events_since(&mut self, cursor: usize) -> Vec<KernelEvent> {
475        if cursor >= self.events.len() {
476            return Vec::new();
477        }
478        self.events.split_off(cursor)
479    }
480
481    pub fn drain_events(&mut self) -> Vec<KernelEvent> {
482        std::mem::take(&mut self.events)
483    }
484
485    pub fn events_matching(&self, path: impl IntoPath) -> Result<Vec<KernelEvent>, KernelError> {
486        let path = path.into_path().map_err(KernelError::InvalidPath)?;
487        Ok(self
488            .events
489            .iter()
490            .filter(|event| event_matches_subscription_path(&path, &event.path))
491            .cloned()
492            .collect())
493    }
494
495    pub fn drain_events_matching(
496        &mut self,
497        path: impl IntoPath,
498    ) -> Result<Vec<KernelEvent>, KernelError> {
499        let path = path.into_path().map_err(KernelError::InvalidPath)?;
500        let mut drained = Vec::new();
501        let mut retained = Vec::new();
502
503        for event in self.events.drain(..) {
504            if event_matches_subscription_path(&path, &event.path) {
505                drained.push(event);
506            } else {
507                retained.push(event);
508            }
509        }
510
511        self.events = retained;
512        Ok(drained)
513    }
514
515    pub fn clear_events(&mut self) -> &mut Self {
516        self.events.clear();
517        self
518    }
519
520    pub fn operator_kind(&self, operator: &str) -> Option<&str> {
521        self.operators
522            .get(operator)
523            .map(|definition| definition.kind.as_str())
524    }
525
526    pub fn recompute_mode(&self) -> RecomputeMode {
527        self.recompute_mode
528    }
529
530    pub fn set_recompute_mode(&mut self, mode: RecomputeMode) -> &mut Self {
531        self.recompute_mode = mode;
532        self
533    }
534
535    pub fn define_operator(&mut self, operator: &str, kind: &str) -> Result<(), KernelError> {
536        let operator = operator.trim();
537        let kind = kind.trim();
538
539        if operator.is_empty() {
540            return Err(KernelError::EmptyOperator);
541        }
542        if operator == "+" {
543            return Err(KernelError::ReservedOperator(operator.to_string()));
544        }
545        if kind.is_empty() {
546            return Err(KernelError::EmptyOperatorKind);
547        }
548
549        self.operators.insert(
550            operator.to_string(),
551            OperatorDefinition {
552                kind: kind.to_string(),
553            },
554        );
555        Ok(())
556    }
557
558    pub fn is_secret_scope(&self, path: impl IntoPath) -> bool {
559        let Ok(path) = path.into_path() else {
560            return false;
561        };
562        self.secret_scopes.contains(&path)
563    }
564
565    pub fn is_noise_scope(&self, path: impl IntoPath) -> bool {
566        let Ok(path) = path.into_path() else {
567            return false;
568        };
569        self.noise_scopes.contains(&path)
570    }
571
572    pub fn effective_secret(&self, path: impl IntoPath) -> Result<String, KernelError> {
573        let path = path.into_path().map_err(KernelError::InvalidPath)?;
574        Ok(self.compute_effective_secret(&path))
575    }
576
577    pub fn secret_material_v3(
578        &self,
579        path: impl IntoPath,
580        mode: SecretMaterialMode,
581        purpose: SecretMaterialPurpose,
582    ) -> Result<[u8; 32], KernelError> {
583        let path = path.into_path().map_err(KernelError::InvalidPath)?;
584        let chain = self.collect_secret_chain_v3(&path, mode)?;
585        derive_secret_material_v3(&chain, purpose).ok_or(KernelError::NoSecretContext(path))
586    }
587
588    pub fn secret_blob_keys_v3(
589        &self,
590        path: impl IntoPath,
591        mode: SecretMaterialMode,
592    ) -> Result<BlobV3DerivedKeys, KernelError> {
593        let path = path.into_path().map_err(KernelError::InvalidPath)?;
594        let chain = self.collect_secret_chain_v3(&path, mode)?;
595        let purpose = match mode {
596            SecretMaterialMode::Branch => SecretMaterialPurpose::Branch,
597            SecretMaterialMode::Value => SecretMaterialPurpose::Value,
598        };
599        derive_blob_v3_keys(&chain, purpose, &path).ok_or(KernelError::NoSecretContext(path))
600    }
601
602    pub fn encrypt_secret_value_v3(
603        &self,
604        path: impl IntoPath,
605        value: impl Into<Value>,
606        nonce: [u8; 16],
607    ) -> Result<String, KernelError> {
608        let path = path.into_path().map_err(KernelError::InvalidPath)?;
609        let keys = self.secret_blob_keys_v3(path.clone(), SecretMaterialMode::Value)?;
610        let value = value.into();
611        ensure_value_is_supported(&value)?;
612        let mut json = String::new();
613        push_json_value(&mut json, &value);
614        Ok(encrypt_blob_v3_cleartext(json.as_bytes(), &keys, nonce))
615    }
616
617    pub fn decrypt_secret_value_v3(
618        &self,
619        path: impl IntoPath,
620        blob: &str,
621    ) -> Result<Option<Value>, KernelError> {
622        let path = path.into_path().map_err(KernelError::InvalidPath)?;
623        let keys = self.secret_blob_keys_v3(path, SecretMaterialMode::Value)?;
624        let Some(cleartext) = decrypt_blob_v3_cleartext(blob, &keys) else {
625            return Ok(None);
626        };
627        let Ok(json) = String::from_utf8(cleartext) else {
628            return Ok(None);
629        };
630        Ok(json_to_value(&json))
631    }
632
633    pub fn postulate(
634        &mut self,
635        path: impl IntoPath,
636        value: impl Into<Value>,
637    ) -> Result<&Memory, KernelError> {
638        self.postulate_with_operator(path, None, value)
639    }
640
641    pub fn postulate_with_operator(
642        &mut self,
643        path: impl IntoPath,
644        operator: Option<String>,
645        value: impl Into<Value>,
646    ) -> Result<&Memory, KernelError> {
647        let path = path.into_path().map_err(KernelError::InvalidPath)?;
648        if path.is_empty() {
649            return Err(KernelError::EmptyPath);
650        }
651
652        self.commit_memory(path, operator, value.into())
653    }
654
655    pub fn remove(&mut self, path: impl IntoPath) -> Result<&Memory, KernelError> {
656        self.postulate_with_operator(path, Some("-".to_string()), Value::String("-".to_string()))
657    }
658
659    pub fn derive(
660        &mut self,
661        scope: impl IntoPath,
662        name: impl IntoPath,
663        expression: &str,
664    ) -> Result<&Memory, KernelError> {
665        let eval_scope = scope.into_path().map_err(KernelError::InvalidPath)?;
666        let name = name.into_path().map_err(KernelError::InvalidPath)?;
667        let expression = expression.trim();
668
669        if name.is_empty() {
670            return Err(KernelError::EmptyPath);
671        }
672        if expression.is_empty() {
673            return Err(KernelError::EmptyExpression);
674        }
675
676        let target_path = eval_scope.iter().cloned().chain(name).collect::<Vec<_>>();
677
678        self.register_derivation(
679            target_path.clone(),
680            eval_scope.clone(),
681            expression.to_string(),
682        );
683
684        let value = self
685            .evaluate_expression(&eval_scope, expression)
686            .unwrap_or_else(|| Value::String(expression.to_string()));
687
688        self.commit_memory_with_expression(
689            target_path,
690            Some("=".to_string()),
691            value,
692            Some(Value::String(expression.to_string())),
693            true,
694        )
695    }
696
697    pub fn collect<I, P>(&self, paths: I) -> Result<Value, KernelError>
698    where
699        I: IntoIterator<Item = P>,
700        P: IntoPath,
701    {
702        self.collect_from_scope(&[], paths)
703    }
704
705    pub fn query<I, P>(
706        &mut self,
707        target_path: impl IntoPath,
708        paths: I,
709    ) -> Result<&Memory, KernelError>
710    where
711        I: IntoIterator<Item = P>,
712        P: IntoPath,
713    {
714        let target_path = target_path.into_path().map_err(KernelError::InvalidPath)?;
715        if target_path.is_empty() {
716            return Err(KernelError::EmptyPath);
717        }
718
719        let value = self.collect_from_scope(&target_path, paths)?;
720        self.commit_memory(target_path, Some("?".to_string()), value)
721    }
722
723    pub fn noise(&mut self, path: impl IntoPath, noise: &str) -> Result<&Memory, KernelError> {
724        if noise.trim().is_empty() {
725            return Err(KernelError::EmptyNoise);
726        }
727
728        let path = path.into_path().map_err(KernelError::InvalidPath)?;
729        if path.is_empty() {
730            return Err(KernelError::EmptyPath);
731        }
732
733        let path_for_noise = path.clone();
734        let memory_index = self.memories.len();
735        self.local_noises
736            .insert(path_for_noise.clone(), noise.trim().to_string());
737        self.commit_memory(
738            path,
739            Some("~".to_string()),
740            Value::String("***".to_string()),
741        )?;
742        Ok(&self.memories[memory_index])
743    }
744
745    pub fn secret(&mut self, path: impl IntoPath, secret: &str) -> Result<&Memory, KernelError> {
746        if secret.trim().is_empty() {
747            return Err(KernelError::EmptySecret);
748        }
749
750        let path = path.into_path().map_err(KernelError::InvalidPath)?;
751        if path.is_empty() {
752            return Err(KernelError::EmptyPath);
753        }
754
755        let path_for_secret = path.clone();
756        let memory_index = self.memories.len();
757        self.local_secrets
758            .insert(path_for_secret.clone(), secret.trim().to_string());
759        self.commit_memory(
760            path,
761            Some("_".to_string()),
762            Value::String("***".to_string()),
763        )?;
764        Ok(&self.memories[memory_index])
765    }
766
767    pub fn pointer(
768        &mut self,
769        path: impl IntoPath,
770        target: impl IntoPath,
771    ) -> Result<&Memory, KernelError> {
772        let target = target.into_path().map_err(KernelError::InvalidPath)?;
773        if target.is_empty() {
774            return Err(KernelError::EmptyPath);
775        }
776        self.postulate_with_operator(path, Some("__".to_string()), Value::Pointer(target))
777    }
778
779    pub fn claim_identity(&mut self, id: &str) -> Result<&Memory, KernelError> {
780        let id = normalize_identity(id)?;
781        self.active_identity = Some(id.clone());
782        self.commit_memory(Vec::new(), Some("@".to_string()), Value::Identity(id))
783    }
784
785    pub fn identity(&mut self, path: impl IntoPath, id: &str) -> Result<&Memory, KernelError> {
786        let id = normalize_identity(id)?;
787        self.postulate_with_operator(path, Some("@".to_string()), Value::Identity(id))
788    }
789
790    pub fn read(&self, path: impl IntoPath) -> Option<&Value> {
791        let Ok(path) = path.into_path() else {
792            return None;
793        };
794        self.resolve_index_pointer_path(&path, 8)
795            .and_then(|resolved| self.read_owner_path(&resolved))
796    }
797
798    pub fn read_fresh(&mut self, path: impl IntoPath) -> Option<Value> {
799        let Ok(path) = path.into_path() else {
800            return None;
801        };
802        let resolved = self
803            .resolve_index_pointer_path(&path, 8)
804            .unwrap_or_else(|| path.clone());
805        self.ensure_target_fresh(&resolved, &mut BTreeSet::new());
806        self.resolve_index_pointer_path(&path, 8)
807            .and_then(|resolved| self.read_owner_path(&resolved).cloned())
808    }
809
810    pub fn read_public(&self, path: impl IntoPath) -> Option<&Value> {
811        let Ok(path) = path.into_path() else {
812            return None;
813        };
814        self.resolve_index_pointer_path(&path, 8)
815            .and_then(|resolved| self.index.get(&resolved))
816    }
817
818    pub fn children(&self, prefix: impl IntoPath) -> Result<Vec<String>, KernelError> {
819        let prefix = prefix.into_path().map_err(KernelError::InvalidPath)?;
820        let mut children = BTreeSet::new();
821
822        for path in self.index.keys() {
823            if path.len() <= prefix.len() || !path_starts_with(path, &prefix) {
824                continue;
825            }
826            children.insert(path[prefix.len()].clone());
827        }
828
829        Ok(children.into_iter().collect())
830    }
831
832    pub fn read_public_subtree(&self, prefix: impl IntoPath) -> Result<Option<Value>, KernelError> {
833        let prefix = prefix.into_path().map_err(KernelError::InvalidPath)?;
834        if let Some(value) = self.index.get(&prefix) {
835            return Ok(Some(value.clone()));
836        }
837
838        let mut root = BTreeMap::new();
839        let mut wrote_any = false;
840
841        for (path, value) in &self.index {
842            if path.len() <= prefix.len() || !path_starts_with(path, &prefix) {
843                continue;
844            }
845            insert_subtree_value(&mut root, &path[prefix.len()..], value.clone());
846            wrote_any = true;
847        }
848
849        Ok(wrote_any.then_some(Value::Object(root)))
850    }
851
852    pub fn explain_fresh(&mut self, path: impl IntoPath) -> Result<ExplainResult, KernelError> {
853        let path = path.into_path().map_err(KernelError::InvalidPath)?;
854        self.read_fresh(path.clone());
855        self.explain(path)
856    }
857
858    pub fn explain(&self, path: impl IntoPath) -> Result<ExplainResult, KernelError> {
859        let path = path.into_path().map_err(KernelError::InvalidPath)?;
860        let resolution = self
861            .resolve_index_pointer_trace(&path, 8)
862            .unwrap_or_else(|| PointerResolution {
863                resolved_path: path.clone(),
864                pointer_chain: Vec::new(),
865            });
866        let value = self.read_owner_path(&resolution.resolved_path).cloned();
867        let record = self.derivations.get(&resolution.resolved_path);
868        let derivation = record.map(|record| ExplainDerivation {
869            expression: record.expression.clone(),
870            inputs: record
871                .refs
872                .iter()
873                .map(|reference| {
874                    let masked = self.is_under_secret_scope(&reference.path);
875                    ExplainInput {
876                        label: reference.label.clone(),
877                        path: reference.path.clone(),
878                        value: if masked {
879                            Some(Value::String("****".to_string()))
880                        } else {
881                            self.read(reference.path.clone()).cloned()
882                        },
883                        origin: if masked {
884                            ExplainOrigin::Secret
885                        } else {
886                            ExplainOrigin::Public
887                        },
888                        masked,
889                    }
890                })
891                .collect(),
892        });
893        let depends_on = record
894            .map(|record| {
895                record
896                    .refs
897                    .iter()
898                    .map(|reference| reference.path.clone())
899                    .collect()
900            })
901            .unwrap_or_default();
902        let expr = record.map(|record| record.expression.clone());
903        let secret = self.is_under_secret_scope(&resolution.resolved_path);
904        let wave = self
905            .last_recompute_wave_by_target
906            .get(&resolution.resolved_path);
907        let recomputed = wave
908            .map(|wave| wave.recomputed.iter().cloned().collect::<Vec<_>>())
909            .unwrap_or_default();
910
911        Ok(ExplainResult {
912            path,
913            value,
914            expr,
915            meta: ExplainMeta {
916                depends_on,
917                resolved_path: resolution.resolved_path,
918                pointer_chain: resolution.pointer_chain,
919                secret,
920                k: recomputed.len(),
921                recomputed,
922                source_path: wave.map(|wave| wave.source_path.clone()),
923            },
924            derivation,
925        })
926    }
927
928    pub fn export_snapshot(&self) -> Snapshot {
929        Snapshot {
930            memories: self.memories.clone(),
931            local_secrets: self.local_secrets.clone(),
932            local_noises: self.local_noises.clone(),
933            key_spaces: self.key_spaces.clone(),
934            operators: self.operators.clone(),
935        }
936    }
937
938    pub fn hydrate(snapshot: Snapshot) -> Result<Self, KernelError> {
939        let mut kernel = Self::new();
940        kernel.operators.extend(snapshot.operators.clone());
941        kernel.key_spaces = snapshot.key_spaces.clone();
942        let mut expected_prev_hash = None;
943
944        for (index, memory) in snapshot.memories.into_iter().enumerate() {
945            if memory.prev_hash != expected_prev_hash {
946                return Err(KernelError::HydrationChainMismatch {
947                    index,
948                    expected_prev_hash,
949                    actual_prev_hash: memory.prev_hash,
950                });
951            }
952
953            let operator_kind = memory
954                .operator
955                .as_deref()
956                .and_then(|operator| kernel.operator_kind(operator))
957                .map(ToOwned::to_owned);
958            if operator_kind.as_deref() == Some("secret") {
959                if let Some(secret) = snapshot.local_secrets.get(&memory.path) {
960                    kernel
961                        .local_secrets
962                        .insert(memory.path.clone(), secret.clone());
963                }
964            }
965            if operator_kind.as_deref() == Some("noise") {
966                if let Some(noise) = snapshot.local_noises.get(&memory.path) {
967                    kernel
968                        .local_noises
969                        .insert(memory.path.clone(), noise.clone());
970                }
971            }
972
973            let expected = hash_memory(
974                &memory.path,
975                memory.operator.as_deref(),
976                memory.expression.as_ref(),
977                &memory.value,
978                &kernel.compute_effective_secret(&memory.path),
979                memory.prev_hash.as_deref(),
980            );
981            if expected != memory.hash {
982                return Err(KernelError::HydrationHashMismatch {
983                    path: memory.path,
984                    expected,
985                    actual: memory.hash,
986                });
987            }
988
989            if operator_kind.as_deref() == Some("eval") {
990                if let Some(expression) = expression_string_from_memory(&memory) {
991                    let eval_scope = parent_path(&memory.path);
992                    kernel.register_derivation(memory.path.clone(), eval_scope, expression);
993                }
994            }
995            kernel.apply_memory(&memory)?;
996            expected_prev_hash = Some(memory.hash.clone());
997            let operator_kind = memory
998                .operator
999                .as_deref()
1000                .and_then(|operator| kernel.operator_kind(operator));
1001            if operator_kind == Some("identity") && memory.path.is_empty() {
1002                if let Value::Identity(id) = &memory.value {
1003                    kernel.active_identity = Some(id.clone());
1004                }
1005            }
1006            kernel.memories.push(memory);
1007        }
1008
1009        Ok(kernel)
1010    }
1011
1012    pub fn learn(&mut self, memory: &Memory) -> Result<&Memory, KernelError> {
1013        let memory_index = self.memories.len();
1014        self.learn_record(memory)?;
1015        Ok(&self.memories[memory_index])
1016    }
1017
1018    pub fn replay_memories<I>(&mut self, memories: I) -> Result<(), KernelError>
1019    where
1020        I: IntoIterator<Item = Memory>,
1021    {
1022        let mut replayed = Self::new();
1023        replayed.operators = self.operators.clone();
1024        replayed.recompute_mode = self.recompute_mode;
1025
1026        for memory in memories {
1027            replayed.learn(&memory)?;
1028        }
1029
1030        replayed.clear_events();
1031        *self = replayed;
1032        Ok(())
1033    }
1034
1035    fn resolve_index_pointer_path(&self, path: &[String], max_hops: usize) -> Option<Path> {
1036        self.resolve_index_pointer_trace(path, max_hops)
1037            .map(|resolution| resolution.resolved_path)
1038    }
1039
1040    fn resolve_index_pointer_trace(
1041        &self,
1042        path: &[String],
1043        max_hops: usize,
1044    ) -> Option<PointerResolution> {
1045        let mut current = path.to_vec();
1046        let mut visited = BTreeSet::new();
1047        let mut pointer_chain = Vec::new();
1048
1049        for _ in 0..max_hops {
1050            if let Some(Value::Pointer(target)) = self.index.get(&current) {
1051                if !visited.insert(current.clone()) {
1052                    return None;
1053                }
1054                pointer_chain.push(current.clone());
1055                current = target.clone();
1056                continue;
1057            }
1058
1059            let mut redirected = false;
1060            for prefix_len in (0..current.len()).rev() {
1061                let prefix = current[..prefix_len].to_vec();
1062                let Some(Value::Pointer(target)) = self.index.get(&prefix) else {
1063                    continue;
1064                };
1065                if !visited.insert(prefix.clone()) {
1066                    return None;
1067                }
1068                pointer_chain.push(prefix.clone());
1069                let suffix = current[prefix_len..].to_vec();
1070                current = target.iter().cloned().chain(suffix).collect();
1071                redirected = true;
1072                break;
1073            }
1074
1075            if redirected {
1076                continue;
1077            }
1078
1079            return Some(PointerResolution {
1080                resolved_path: current,
1081                pointer_chain,
1082            });
1083        }
1084
1085        None
1086    }
1087
1088    fn read_owner_path(&self, path: &[String]) -> Option<&Value> {
1089        if self.is_under_secret_scope(path) {
1090            return self.private_index.get(path);
1091        }
1092        self.index.get(path)
1093    }
1094
1095    fn commit_memory(
1096        &mut self,
1097        path: Path,
1098        operator: Option<String>,
1099        value: Value,
1100    ) -> Result<&Memory, KernelError> {
1101        self.commit_memory_with_expression(path, operator, value.clone(), Some(value), true)
1102    }
1103
1104    fn commit_memory_with_expression(
1105        &mut self,
1106        path: Path,
1107        operator: Option<String>,
1108        value: Value,
1109        expression: Option<Value>,
1110        invalidate: bool,
1111    ) -> Result<&Memory, KernelError> {
1112        ensure_value_is_supported(&value)?;
1113        if let Some(expression) = &expression {
1114            ensure_value_is_supported(expression)?;
1115        }
1116
1117        let prev_hash = self.memories.last().map(|memory| memory.hash.clone());
1118        let effective_secret = self.compute_effective_secret(&path);
1119        let stored_value = self.stored_value_for_memory(&path, operator.as_deref(), &value)?;
1120        let hash = hash_memory(
1121            &path,
1122            operator.as_deref(),
1123            expression.as_ref(),
1124            &stored_value,
1125            &effective_secret,
1126            prev_hash.as_deref(),
1127        );
1128        let source_path = path.clone();
1129        let memory_index = self.memories.len();
1130        let memory = Memory {
1131            path,
1132            operator,
1133            expression,
1134            value: stored_value,
1135            prev_hash,
1136            hash,
1137        };
1138
1139        self.apply_memory(&memory)?;
1140        self.bump_path_version(&source_path);
1141        self.memories.push(memory);
1142        self.record_event_from_memory(memory_index, &source_path);
1143        if invalidate {
1144            self.invalidate_from_path(&source_path);
1145        }
1146        Ok(&self.memories[memory_index])
1147    }
1148
1149    fn apply_memory(&mut self, memory: &Memory) -> Result<(), KernelError> {
1150        let operator_kind = memory
1151            .operator
1152            .as_deref()
1153            .and_then(|operator| self.operator_kind(operator))
1154            .map(ToOwned::to_owned);
1155
1156        match operator_kind.as_deref() {
1157            Some("secret") => {
1158                self.secret_scopes.insert(memory.path.clone());
1159                move_index_prefix_to_private(
1160                    &mut self.index,
1161                    &mut self.private_index,
1162                    &memory.path,
1163                );
1164            }
1165            Some("noise") => {
1166                self.noise_scopes.insert(memory.path.clone());
1167            }
1168            Some("remove") => {
1169                remove_index_prefix(&mut self.index, &memory.path);
1170                remove_index_prefix(&mut self.private_index, &memory.path);
1171                self.secret_scopes
1172                    .retain(|scope| !path_starts_with(scope, &memory.path));
1173                self.noise_scopes
1174                    .retain(|scope| !path_starts_with(scope, &memory.path));
1175                self.local_secrets
1176                    .retain(|scope, _| !path_starts_with(scope, &memory.path));
1177                self.local_noises
1178                    .retain(|scope, _| !path_starts_with(scope, &memory.path));
1179                self.clear_derivations_by_prefix(&memory.path);
1180            }
1181            Some("identity") if memory.path.is_empty() => {
1182                if let Value::Identity(id) = &memory.value {
1183                    self.active_identity = Some(id.clone());
1184                }
1185                self.index.insert(memory.path.clone(), memory.value.clone());
1186            }
1187            _ if self.is_under_secret_scope(&memory.path) => {
1188                self.index.remove(&memory.path);
1189                let value = self.value_for_private_index(memory)?;
1190                self.private_index.insert(memory.path.clone(), value);
1191            }
1192            _ => {
1193                self.index.insert(memory.path.clone(), memory.value.clone());
1194            }
1195        }
1196        Ok(())
1197    }
1198
1199    fn record_event_from_memory(&mut self, memory_index: usize, path: &[String]) {
1200        let Some(memory) = self.memories.get(memory_index) else {
1201            return;
1202        };
1203        self.events.push(KernelEvent {
1204            path: path.to_vec(),
1205            operator: memory.operator.clone(),
1206            value: self.read_owner_path(path).cloned(),
1207            memory_hash: memory.hash.clone(),
1208        });
1209    }
1210
1211    fn learn_record(&mut self, memory: &Memory) -> Result<(), KernelError> {
1212        let operator_kind = memory
1213            .operator
1214            .as_deref()
1215            .and_then(|operator| self.operator_kind(operator))
1216            .map(ToOwned::to_owned);
1217
1218        if memory.path.is_empty() && operator_kind.as_deref() != Some("identity") {
1219            return Err(KernelError::EmptyPath);
1220        }
1221
1222        match operator_kind.as_deref() {
1223            Some("secret") => {
1224                let secret = secret_from_memory(memory);
1225                let memory_index = self.memories.len();
1226                self.local_secrets.insert(memory.path.clone(), secret);
1227                self.commit_memory_with_expression(
1228                    memory.path.clone(),
1229                    memory.operator.clone(),
1230                    Value::String("***".to_string()),
1231                    memory.expression.clone(),
1232                    true,
1233                )?;
1234                debug_assert_eq!(self.memories.len(), memory_index + 1);
1235            }
1236            Some("noise") => {
1237                let noise = secret_from_memory(memory);
1238                let memory_index = self.memories.len();
1239                self.local_noises.insert(memory.path.clone(), noise);
1240                self.commit_memory_with_expression(
1241                    memory.path.clone(),
1242                    memory.operator.clone(),
1243                    Value::String("***".to_string()),
1244                    memory.expression.clone(),
1245                    true,
1246                )?;
1247                debug_assert_eq!(self.memories.len(), memory_index + 1);
1248            }
1249            Some("identity") => {
1250                let id = identity_from_memory(memory)?;
1251                let id = normalize_identity(&id)?;
1252                self.commit_memory_with_expression(
1253                    memory.path.clone(),
1254                    memory.operator.clone(),
1255                    Value::Identity(id.clone()),
1256                    memory.expression.clone(),
1257                    true,
1258                )?;
1259                if memory.path.is_empty() {
1260                    self.active_identity = Some(id);
1261                }
1262            }
1263            Some("pointer") => {
1264                let target = pointer_from_memory(memory)?;
1265                self.commit_memory_with_expression(
1266                    memory.path.clone(),
1267                    memory.operator.clone(),
1268                    Value::Pointer(target),
1269                    memory.expression.clone(),
1270                    true,
1271                )?;
1272            }
1273            Some("remove") => {
1274                self.commit_memory_with_expression(
1275                    memory.path.clone(),
1276                    memory.operator.clone(),
1277                    Value::String("-".to_string()),
1278                    memory.expression.clone(),
1279                    true,
1280                )?;
1281            }
1282            Some("eval") => {
1283                if let Some(expression) = expression_string_from_memory(memory) {
1284                    let eval_scope = parent_path(&memory.path);
1285                    self.register_derivation(memory.path.clone(), eval_scope, expression);
1286                }
1287                self.commit_memory_with_expression(
1288                    memory.path.clone(),
1289                    memory.operator.clone(),
1290                    memory.value.clone(),
1291                    memory.expression.clone(),
1292                    true,
1293                )?;
1294            }
1295            _ => {
1296                self.commit_memory_with_expression(
1297                    memory.path.clone(),
1298                    memory.operator.clone(),
1299                    memory.value.clone(),
1300                    memory.expression.clone(),
1301                    true,
1302                )?;
1303            }
1304        }
1305
1306        Ok(())
1307    }
1308
1309    fn is_under_secret_scope(&self, path: &[String]) -> bool {
1310        self.secret_scopes
1311            .iter()
1312            .any(|scope| path_starts_with(path, scope))
1313    }
1314
1315    fn stored_value_for_memory(
1316        &self,
1317        path: &[String],
1318        operator: Option<&str>,
1319        value: &Value,
1320    ) -> Result<Value, KernelError> {
1321        if !self.should_encrypt_memory_value(path, operator, value) {
1322            return Ok(value.clone());
1323        }
1324        let nonce = random_blob_v3_nonce().ok_or(KernelError::RandomUnavailable)?;
1325        let blob = self.encrypt_secret_value_v3(path.to_vec(), value.clone(), nonce)?;
1326        Ok(Value::String(blob))
1327    }
1328
1329    fn should_encrypt_memory_value(
1330        &self,
1331        path: &[String],
1332        operator: Option<&str>,
1333        value: &Value,
1334    ) -> bool {
1335        operator.is_none()
1336            && self.is_under_secret_scope(path)
1337            && !matches!(value, Value::Pointer(_) | Value::Identity(_))
1338    }
1339
1340    fn value_for_private_index(&self, memory: &Memory) -> Result<Value, KernelError> {
1341        if !self.should_encrypt_memory_value(
1342            &memory.path,
1343            memory.operator.as_deref(),
1344            &memory.value,
1345        ) {
1346            return Ok(memory.value.clone());
1347        }
1348        let Value::String(blob) = &memory.value else {
1349            return Err(KernelError::SecretBlobDecryptFailed(memory.path.clone()));
1350        };
1351        self.decrypt_secret_value_v3(memory.path.clone(), blob)?
1352            .ok_or_else(|| KernelError::SecretBlobDecryptFailed(memory.path.clone()))
1353    }
1354
1355    fn compute_effective_secret(&self, path: &[String]) -> String {
1356        let active_noise = self.find_active_noise(path);
1357        let mut seed = String::from("root");
1358
1359        if let Some((_, noise)) = &active_noise {
1360            seed = portable_hash_fnv1a(&format!("noise::{noise}"));
1361        }
1362
1363        for index in 1..=path.len() {
1364            let secret_path = path[..index].to_vec();
1365            let Some(secret) = self.local_secrets.get(&secret_path) else {
1366                continue;
1367            };
1368            if !secret_allowed_under_noise(
1369                active_noise.as_ref().map(|(path, _)| path),
1370                &secret_path,
1371            ) {
1372                continue;
1373            }
1374            seed = portable_hash_fnv1a(&format!("{seed}::{secret}"));
1375        }
1376
1377        if seed == "root" {
1378            String::new()
1379        } else {
1380            seed
1381        }
1382    }
1383
1384    fn find_active_noise(&self, path: &[String]) -> Option<(Path, String)> {
1385        let mut active = None;
1386        for index in 1..=path.len() {
1387            let noise_path = path[..index].to_vec();
1388            if let Some(noise) = self.local_noises.get(&noise_path) {
1389                active = Some((noise_path, noise.clone()));
1390            }
1391        }
1392        active
1393    }
1394
1395    fn collect_secret_chain_v3(
1396        &self,
1397        target_path: &[String],
1398        mode: SecretMaterialMode,
1399    ) -> Result<Vec<Vec<u8>>, KernelError> {
1400        let scope_path = self
1401            .resolve_branch_scope(target_path)
1402            .ok_or_else(|| KernelError::NoSecretContext(target_path.to_vec()))?;
1403        if mode == SecretMaterialMode::Branch && scope_path.is_empty() {
1404            return Err(KernelError::RootSecretBranchUnsupported);
1405        }
1406
1407        let anchor_path = match mode {
1408            SecretMaterialMode::Branch => scope_path.clone(),
1409            SecretMaterialMode::Value => target_path.to_vec(),
1410        };
1411        let active_noise = self.find_active_noise(&anchor_path);
1412        let noise_boundary = active_noise
1413            .as_ref()
1414            .map(|(path, _)| path.join("."))
1415            .unwrap_or_else(|| V3_NO_NOISE_SENTINEL.to_string());
1416
1417        let mut chain = vec![
1418            V3_DOMAIN.as_bytes().to_vec(),
1419            match mode {
1420                SecretMaterialMode::Branch => b"branch".to_vec(),
1421                SecretMaterialMode::Value => b"value".to_vec(),
1422            },
1423            scope_path.join(".").into_bytes(),
1424            anchor_path.join(".").into_bytes(),
1425            noise_boundary.into_bytes(),
1426        ];
1427        chain.extend(self.collect_lineage_segments(&anchor_path, active_noise.as_ref()));
1428        Ok(chain)
1429    }
1430
1431    fn resolve_branch_scope(&self, path: &[String]) -> Option<Path> {
1432        let mut best = self.local_secrets.get(&Vec::new()).map(|_| Vec::new());
1433        for index in 1..=path.len() {
1434            let scope_path = path[..index].to_vec();
1435            if self.local_secrets.contains_key(&scope_path) {
1436                best = Some(scope_path);
1437            }
1438        }
1439        best
1440    }
1441
1442    fn collect_lineage_segments(
1443        &self,
1444        anchor_path: &[String],
1445        active_noise: Option<&(Path, String)>,
1446    ) -> Vec<Vec<u8>> {
1447        let mut out = Vec::new();
1448
1449        if let Some((path, noise)) = active_noise {
1450            out.push(lineage_segment("noise", &path.join("."), noise));
1451        } else if let Some(root_secret) = self.local_secrets.get(&Vec::new()) {
1452            out.push(lineage_segment("secret", "", root_secret));
1453        }
1454
1455        for index in 1..=anchor_path.len() {
1456            let secret_path = anchor_path[..index].to_vec();
1457            let Some(secret) = self.local_secrets.get(&secret_path) else {
1458                continue;
1459            };
1460            if !secret_allowed_under_noise(active_noise.map(|(path, _)| path), &secret_path) {
1461                continue;
1462            }
1463            out.push(lineage_segment("secret", &secret_path.join("."), secret));
1464        }
1465
1466        out
1467    }
1468
1469    fn register_derivation(&mut self, target_path: Path, eval_scope: Path, expression: String) {
1470        self.unregister_derivation(&target_path);
1471
1472        let mut seen = BTreeSet::new();
1473        let refs = extract_expression_refs(&expression)
1474            .into_iter()
1475            .flat_map(|label| {
1476                self.resolve_derivation_ref_paths(&label, &eval_scope)
1477                    .into_iter()
1478                    .map(move |path| (label.clone(), path))
1479            })
1480            .filter_map(|(label, path)| {
1481                seen.insert((label.clone(), path.clone()))
1482                    .then_some(DerivationRef { label, path })
1483            })
1484            .collect::<Vec<_>>();
1485        let ref_versions = refs
1486            .iter()
1487            .map(|reference| {
1488                (
1489                    reference.path.clone(),
1490                    self.current_path_version(&reference.path),
1491                )
1492            })
1493            .collect::<BTreeMap<_, _>>();
1494
1495        for reference in &refs {
1496            self.ref_subscribers
1497                .entry(reference.path.clone())
1498                .or_default()
1499                .insert(target_path.clone());
1500        }
1501
1502        self.derivations.insert(
1503            target_path,
1504            DerivationRecord {
1505                eval_scope,
1506                expression,
1507                refs,
1508                ref_versions,
1509            },
1510        );
1511    }
1512
1513    fn resolve_derivation_ref_paths(&self, label: &str, eval_scope: &[String]) -> Vec<Path> {
1514        let Ok(parts) = label.into_path() else {
1515            return Vec::new();
1516        };
1517        if parts.is_empty() {
1518            return Vec::new();
1519        }
1520        if label.contains('.') {
1521            return vec![parts];
1522        }
1523
1524        let relative = eval_scope
1525            .iter()
1526            .cloned()
1527            .chain(parts.iter().cloned())
1528            .collect::<Path>();
1529        if relative == parts || self.read(relative.clone()).is_some() {
1530            return vec![relative];
1531        }
1532        if self.read(parts.clone()).is_some() {
1533            return vec![parts];
1534        }
1535        vec![relative]
1536    }
1537
1538    fn unregister_derivation(&mut self, target_path: &[String]) {
1539        let Some(record) = self.derivations.remove(target_path) else {
1540            return;
1541        };
1542        self.last_recompute_wave_by_target.remove(target_path);
1543
1544        for reference in record.refs {
1545            if let Some(subscribers) = self.ref_subscribers.get_mut(&reference.path) {
1546                subscribers.remove(target_path);
1547                if subscribers.is_empty() {
1548                    self.ref_subscribers.remove(&reference.path);
1549                }
1550            }
1551        }
1552    }
1553
1554    fn clear_derivations_by_prefix(&mut self, prefix: &[String]) {
1555        let targets = self
1556            .derivations
1557            .keys()
1558            .filter(|target| path_starts_with(target, prefix))
1559            .cloned()
1560            .collect::<Vec<_>>();
1561
1562        for target in targets {
1563            self.unregister_derivation(&target);
1564        }
1565    }
1566
1567    fn invalidate_from_path(&mut self, source_path: &[String]) {
1568        if self.recompute_mode == RecomputeMode::Lazy {
1569            return;
1570        }
1571
1572        let started_wave = self.begin_recompute_wave(source_path);
1573        let mut queue = VecDeque::from([source_path.to_vec()]);
1574        let mut seen_targets = BTreeSet::new();
1575
1576        while let Some(changed_path) = queue.pop_front() {
1577            let subscribers = self
1578                .ref_subscribers
1579                .get(&changed_path)
1580                .cloned()
1581                .unwrap_or_default();
1582
1583            for target_path in subscribers {
1584                if !seen_targets.insert(target_path.clone()) {
1585                    continue;
1586                }
1587                if self.recompute_target(&target_path) {
1588                    queue.push_back(target_path);
1589                }
1590            }
1591        }
1592
1593        if started_wave {
1594            self.finalize_recompute_wave();
1595        }
1596    }
1597
1598    fn recompute_target(&mut self, target_path: &[String]) -> bool {
1599        let Some(record) = self.derivations.get(target_path).cloned() else {
1600            return false;
1601        };
1602
1603        let value = self
1604            .evaluate_expression(&record.eval_scope, &record.expression)
1605            .unwrap_or_else(|| Value::String(record.expression.clone()));
1606
1607        let recomputed = self
1608            .commit_memory_with_expression(
1609                target_path.to_vec(),
1610                Some("=".to_string()),
1611                value,
1612                Some(Value::String(record.expression)),
1613                false,
1614            )
1615            .is_ok();
1616
1617        if recomputed {
1618            self.refresh_derivation_ref_versions(target_path);
1619            self.record_recomputed_target(target_path);
1620        }
1621
1622        recomputed
1623    }
1624
1625    fn ensure_target_fresh(
1626        &mut self,
1627        target_path: &[String],
1628        visiting: &mut BTreeSet<Path>,
1629    ) -> bool {
1630        if self.recompute_mode != RecomputeMode::Lazy {
1631            return false;
1632        }
1633        if !self.derivations.contains_key(target_path) {
1634            return false;
1635        }
1636        if !visiting.insert(target_path.to_vec()) {
1637            return false;
1638        }
1639
1640        let started_wave = self.begin_recompute_wave(target_path);
1641        let refs = self
1642            .derivations
1643            .get(target_path)
1644            .map(|record| record.refs.clone())
1645            .unwrap_or_default();
1646
1647        for reference in refs {
1648            if self.derivations.contains_key(&reference.path) {
1649                self.ensure_target_fresh(&reference.path, visiting);
1650            }
1651        }
1652
1653        let changed = if self.derivation_refs_changed(target_path) {
1654            self.recompute_target(target_path)
1655        } else {
1656            false
1657        };
1658
1659        visiting.remove(target_path);
1660        if started_wave {
1661            self.finalize_recompute_wave();
1662        }
1663        changed
1664    }
1665
1666    fn current_path_version(&self, path: &[String]) -> u64 {
1667        self.path_versions.get(path).copied().unwrap_or_default()
1668    }
1669
1670    fn bump_path_version(&mut self, path: &[String]) {
1671        self.path_version_clock = self.path_version_clock.saturating_add(1);
1672        self.path_versions
1673            .insert(path.to_vec(), self.path_version_clock);
1674    }
1675
1676    fn derivation_refs_changed(&self, target_path: &[String]) -> bool {
1677        let Some(record) = self.derivations.get(target_path) else {
1678            return false;
1679        };
1680
1681        record.refs.iter().any(|reference| {
1682            self.current_path_version(&reference.path)
1683                > record
1684                    .ref_versions
1685                    .get(&reference.path)
1686                    .copied()
1687                    .unwrap_or_default()
1688        })
1689    }
1690
1691    fn refresh_derivation_ref_versions(&mut self, target_path: &[String]) {
1692        let Some(refs) = self
1693            .derivations
1694            .get(target_path)
1695            .map(|record| record.refs.clone())
1696        else {
1697            return;
1698        };
1699
1700        let ref_versions = refs
1701            .iter()
1702            .map(|reference| {
1703                (
1704                    reference.path.clone(),
1705                    self.current_path_version(&reference.path),
1706                )
1707            })
1708            .collect::<BTreeMap<_, _>>();
1709
1710        if let Some(record) = self.derivations.get_mut(target_path) {
1711            record.ref_versions = ref_versions;
1712        }
1713    }
1714
1715    fn begin_recompute_wave(&mut self, source_path: &[String]) -> bool {
1716        if self.active_recompute_wave.is_some() {
1717            return false;
1718        }
1719        self.active_recompute_wave = Some(RecomputeWave {
1720            source_path: source_path.to_vec(),
1721            recomputed: BTreeSet::new(),
1722        });
1723        true
1724    }
1725
1726    fn record_recomputed_target(&mut self, target_path: &[String]) {
1727        let Some(wave) = &mut self.active_recompute_wave else {
1728            return;
1729        };
1730        wave.recomputed.insert(target_path.to_vec());
1731    }
1732
1733    fn finalize_recompute_wave(&mut self) {
1734        let Some(wave) = self.active_recompute_wave.take() else {
1735            return;
1736        };
1737        if wave.recomputed.is_empty() {
1738            return;
1739        }
1740        let wave = Arc::new(wave);
1741        for target_path in &wave.recomputed {
1742            self.last_recompute_wave_by_target
1743                .insert(target_path.clone(), Arc::clone(&wave));
1744        }
1745    }
1746
1747    fn evaluate_expression(&self, eval_scope: &[String], expression: &str) -> Option<Value> {
1748        evaluate_expression(self, eval_scope, expression)
1749    }
1750
1751    fn collect_from_scope<I, P>(&self, scope: &[String], paths: I) -> Result<Value, KernelError>
1752    where
1753        I: IntoIterator<Item = P>,
1754        P: IntoPath,
1755    {
1756        let mut values = Vec::new();
1757
1758        for path in paths {
1759            let path = path.into_path().map_err(KernelError::InvalidPath)?;
1760            if path.is_empty() {
1761                return Err(KernelError::EmptyPath);
1762            }
1763            let path = resolve_query_path(scope, path);
1764            values.push(self.read(path).cloned().unwrap_or(Value::Null));
1765        }
1766
1767        if values.is_empty() {
1768            return Err(KernelError::EmptyQuery);
1769        }
1770
1771        Ok(Value::Array(values))
1772    }
1773
1774    fn inspect_memories<'a>(&self, memories: impl Iterator<Item = &'a Memory>) -> InspectResult {
1775        InspectResult {
1776            memories: memories
1777                .map(|memory| InspectMemory {
1778                    path: memory.path.clone(),
1779                    operator: memory.operator.clone(),
1780                    expression: if self.is_under_secret_scope(&memory.path) {
1781                        None
1782                    } else {
1783                        memory.expression.clone()
1784                    },
1785                    value: if self.is_under_secret_scope(&memory.path) {
1786                        Value::String("****".to_string())
1787                    } else {
1788                        memory.value.clone()
1789                    },
1790                    prev_hash: memory.prev_hash.clone(),
1791                    hash: memory.hash.clone(),
1792                })
1793                .collect(),
1794            index: self.index.clone(),
1795            secret_scopes: self.secret_scopes.iter().cloned().collect(),
1796            noise_scopes: self.noise_scopes.iter().cloned().collect(),
1797            derivations: self.derivations.keys().cloned().collect(),
1798        }
1799    }
1800}
1801
1802fn remove_index_prefix(index: &mut BTreeMap<Path, Value>, prefix: &[String]) {
1803    index.retain(|path, _| !path_starts_with(path, prefix));
1804}
1805
1806fn insert_subtree_value(root: &mut BTreeMap<String, Value>, rel_path: &[String], value: Value) {
1807    let Some((head, tail)) = rel_path.split_first() else {
1808        return;
1809    };
1810    if tail.is_empty() {
1811        root.insert(head.clone(), value);
1812        return;
1813    }
1814
1815    let entry = root
1816        .entry(head.clone())
1817        .or_insert_with(|| Value::Object(BTreeMap::new()));
1818    if !matches!(entry, Value::Object(_)) {
1819        *entry = Value::Object(BTreeMap::new());
1820    }
1821    let Value::Object(child) = entry else {
1822        return;
1823    };
1824    insert_subtree_value(child, tail, value);
1825}
1826
1827fn default_operators() -> BTreeMap<String, OperatorDefinition> {
1828    [
1829        ("_", "secret"),
1830        ("~", "noise"),
1831        ("__", "pointer"),
1832        ("->", "pointer"),
1833        ("@", "identity"),
1834        ("=", "eval"),
1835        ("?", "query"),
1836        ("-", "remove"),
1837    ]
1838    .into_iter()
1839    .map(|(operator, kind)| {
1840        (
1841            operator.to_string(),
1842            OperatorDefinition {
1843                kind: kind.to_string(),
1844            },
1845        )
1846    })
1847    .collect()
1848}
1849
1850fn move_index_prefix_to_private(
1851    index: &mut BTreeMap<Path, Value>,
1852    private_index: &mut BTreeMap<Path, Value>,
1853    prefix: &[String],
1854) {
1855    let keys = index
1856        .keys()
1857        .filter(|path| path_starts_with(path, prefix))
1858        .cloned()
1859        .collect::<Vec<_>>();
1860
1861    for key in keys {
1862        if let Some(value) = index.remove(&key) {
1863            private_index.insert(key, value);
1864        }
1865    }
1866}
1867
1868fn path_starts_with(path: &[String], prefix: &[String]) -> bool {
1869    path.len() >= prefix.len() && path.iter().zip(prefix).all(|(left, right)| left == right)
1870}
1871
1872fn parent_path(path: &[String]) -> Path {
1873    path.split_last()
1874        .map(|(_, parent)| parent.to_vec())
1875        .unwrap_or_default()
1876}
1877
1878fn resolve_query_path(scope: &[String], path: Path) -> Path {
1879    if scope.is_empty() || path.len() != 1 {
1880        return path;
1881    }
1882    scope.iter().cloned().chain(path).collect()
1883}
1884
1885fn secret_from_memory(memory: &Memory) -> String {
1886    memory
1887        .expression
1888        .as_ref()
1889        .and_then(string_from_value)
1890        .filter(|value| !value.is_empty())
1891        .map(|value| value.trim().to_string())
1892        .or_else(|| match &memory.value {
1893            Value::String(value) => {
1894                let value = value.trim();
1895                (!value.is_empty() && value != "***" && value != "****").then(|| value.to_string())
1896            }
1897            _ => None,
1898        })
1899        .unwrap_or_else(|| "***".to_string())
1900}
1901
1902fn identity_from_memory(memory: &Memory) -> Result<String, KernelError> {
1903    identity_from_value(&memory.value)
1904        .or_else(|| memory.expression.as_ref().and_then(identity_from_value))
1905        .ok_or_else(|| KernelError::InvalidIdentity(String::new()))
1906}
1907
1908fn identity_from_value(value: &Value) -> Option<String> {
1909    match value {
1910        Value::Identity(id) | Value::String(id) => Some(id.clone()),
1911        Value::Object(values) => values.get("__id").and_then(identity_from_value),
1912        _ => None,
1913    }
1914}
1915
1916fn pointer_from_memory(memory: &Memory) -> Result<Path, KernelError> {
1917    pointer_from_value(&memory.value)
1918        .or_else(|| memory.expression.as_ref().and_then(pointer_from_value))
1919        .filter(|path| !path.is_empty())
1920        .ok_or(KernelError::EmptyPath)
1921}
1922
1923fn pointer_from_value(value: &Value) -> Option<Path> {
1924    match value {
1925        Value::Pointer(path) => Some(path.clone()),
1926        Value::String(path) => path.as_str().into_path().ok(),
1927        Value::Object(values) => values.get("__ptr").and_then(pointer_from_value),
1928        _ => None,
1929    }
1930}
1931
1932fn expression_string_from_memory(memory: &Memory) -> Option<String> {
1933    memory.expression.as_ref().and_then(string_from_value)
1934}
1935
1936fn string_from_value(value: &Value) -> Option<String> {
1937    match value {
1938        Value::String(value) => Some(value.trim().to_string()),
1939        _ => None,
1940    }
1941}
1942
1943fn ensure_value_is_supported(value: &Value) -> Result<(), KernelError> {
1944    match value {
1945        Value::Number(number) if !number.is_finite() => Err(KernelError::NonFiniteNumber),
1946        Value::Array(values) => {
1947            for value in values {
1948                ensure_value_is_supported(value)?;
1949            }
1950            Ok(())
1951        }
1952        Value::Object(values) => {
1953            for value in values.values() {
1954                ensure_value_is_supported(value)?;
1955            }
1956            Ok(())
1957        }
1958        Value::Pointer(path) if path.is_empty() => Err(KernelError::EmptyPath),
1959        Value::Identity(id) => normalize_identity(id).map(|_| ()),
1960        _ => Ok(()),
1961    }
1962}
1963
1964fn normalize_identity(input: &str) -> Result<String, KernelError> {
1965    let id = input.trim().to_ascii_lowercase();
1966    if id.len() < 3 || id.len() > 63 {
1967        return Err(KernelError::InvalidIdentity(input.to_string()));
1968    }
1969    if id.contains('.') {
1970        return Err(KernelError::InvalidIdentity(input.to_string()));
1971    }
1972
1973    let bytes = id.as_bytes();
1974    let is_label_char =
1975        |byte: u8| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'-';
1976    let is_edge_char = |byte: u8| byte.is_ascii_lowercase() || byte.is_ascii_digit();
1977
1978    if !bytes.iter().copied().all(is_label_char) {
1979        return Err(KernelError::InvalidIdentity(input.to_string()));
1980    }
1981    if !is_edge_char(bytes[0]) || !is_edge_char(bytes[bytes.len() - 1]) {
1982        return Err(KernelError::InvalidIdentity(input.to_string()));
1983    }
1984
1985    Ok(id)
1986}
1987
1988fn hash_memory(
1989    path: &[String],
1990    operator: Option<&str>,
1991    expression: Option<&Value>,
1992    value: &Value,
1993    effective_secret: &str,
1994    prev_hash: Option<&str>,
1995) -> String {
1996    let mut input = String::new();
1997    input.push_str("{\"path\":");
1998    push_json_string(&mut input, &path.join("."));
1999    input.push_str(",\"operator\":");
2000    push_json_optional_string(&mut input, operator);
2001    input.push_str(",\"expression\":");
2002    push_json_optional_value(&mut input, expression);
2003    input.push_str(",\"value\":");
2004    push_json_value(&mut input, value);
2005    input.push_str(",\"effectiveSecret\":");
2006    push_json_string(&mut input, effective_secret);
2007    input.push_str(",\"prevHash\":");
2008    push_json_string(&mut input, prev_hash.unwrap_or(""));
2009    input.push('}');
2010
2011    portable_hash_fnv1a(&input)
2012}
2013
2014fn secret_allowed_under_noise(noise_path: Option<&Path>, secret_path: &[String]) -> bool {
2015    let Some(noise_path) = noise_path else {
2016        return true;
2017    };
2018    path_starts_with(secret_path, noise_path)
2019}
2020
2021fn event_matches_subscription_path(subscribed_path: &[String], written_path: &[String]) -> bool {
2022    subscribed_path.is_empty()
2023        || subscribed_path == written_path
2024        || path_starts_with(subscribed_path, written_path)
2025        || path_starts_with(written_path, subscribed_path)
2026}
2027
2028fn portable_hash_fnv1a(input: &str) -> String {
2029    let mut hash = 0x811c_9dc5_u32;
2030    for unit in input.encode_utf16() {
2031        hash ^= u32::from(unit);
2032        hash = hash.wrapping_mul(0x0100_0193);
2033    }
2034    format!("{hash:08x}")
2035}
2036
2037fn push_json_optional_string(out: &mut String, value: Option<&str>) {
2038    match value {
2039        Some(value) => push_json_string(out, value),
2040        None => out.push_str("null"),
2041    }
2042}
2043
2044fn push_json_optional_value(out: &mut String, value: Option<&Value>) {
2045    match value {
2046        Some(value) => push_json_value(out, value),
2047        None => out.push_str("null"),
2048    }
2049}
2050
2051fn push_json_string(out: &mut String, value: &str) {
2052    out.push('"');
2053    for ch in value.chars() {
2054        match ch {
2055            '"' => out.push_str("\\\""),
2056            '\\' => out.push_str("\\\\"),
2057            '\u{08}' => out.push_str("\\b"),
2058            '\u{0c}' => out.push_str("\\f"),
2059            '\n' => out.push_str("\\n"),
2060            '\r' => out.push_str("\\r"),
2061            '\t' => out.push_str("\\t"),
2062            ch if ch <= '\u{1f}' => {
2063                out.push_str("\\u00");
2064                push_hex_nibble(out, (ch as u32 >> 4) & 0x0f);
2065                push_hex_nibble(out, ch as u32 & 0x0f);
2066            }
2067            ch => out.push(ch),
2068        }
2069    }
2070    out.push('"');
2071}
2072
2073fn push_hex_nibble(out: &mut String, value: u32) {
2074    let ch = match value {
2075        0..=9 => char::from(b'0' + value as u8),
2076        10..=15 => char::from(b'a' + (value as u8 - 10)),
2077        _ => unreachable!("hex nibble must be <= 15"),
2078    };
2079    out.push(ch);
2080}
2081
2082fn push_json_value(out: &mut String, value: &Value) {
2083    match value {
2084        Value::Null => out.push_str("null"),
2085        Value::Bool(value) => out.push_str(if *value { "true" } else { "false" }),
2086        Value::Number(value) => {
2087            if value.to_bits() == (-0.0_f64).to_bits() {
2088                out.push('0');
2089            } else {
2090                out.push_str(&value.to_string());
2091            }
2092        }
2093        Value::String(value) => push_json_string(out, value),
2094        Value::Array(values) => {
2095            out.push('[');
2096            for (index, value) in values.iter().enumerate() {
2097                if index > 0 {
2098                    out.push(',');
2099                }
2100                push_json_value(out, value);
2101            }
2102            out.push(']');
2103        }
2104        Value::Object(values) => {
2105            out.push('{');
2106            for (index, (key, value)) in values.iter().enumerate() {
2107                if index > 0 {
2108                    out.push(',');
2109                }
2110                push_json_string(out, key);
2111                out.push(':');
2112                push_json_value(out, value);
2113            }
2114            out.push('}');
2115        }
2116        Value::Pointer(path) => {
2117            out.push_str("{\"__ptr\":");
2118            push_json_string(out, &path.join("."));
2119            out.push('}');
2120        }
2121        Value::Identity(id) => {
2122            out.push_str("{\"__id\":");
2123            push_json_string(out, id);
2124            out.push('}');
2125        }
2126    }
2127}
2128
2129fn json_to_value(input: &str) -> Option<Value> {
2130    let value = serde_json::from_str::<serde_json::Value>(input).ok()?;
2131    serde_json_to_value(value)
2132}
2133
2134fn serde_json_to_value(value: serde_json::Value) -> Option<Value> {
2135    match value {
2136        serde_json::Value::Null => Some(Value::Null),
2137        serde_json::Value::Bool(value) => Some(Value::Bool(value)),
2138        serde_json::Value::Number(value) => value.as_f64().map(Value::Number),
2139        serde_json::Value::String(value) => Some(Value::String(value)),
2140        serde_json::Value::Array(values) => values
2141            .into_iter()
2142            .map(serde_json_to_value)
2143            .collect::<Option<Vec<_>>>()
2144            .map(Value::Array),
2145        serde_json::Value::Object(values) => values
2146            .into_iter()
2147            .map(|(key, value)| serde_json_to_value(value).map(|value| (key, value)))
2148            .collect::<Option<BTreeMap<_, _>>>()
2149            .map(Value::Object),
2150    }
2151}