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