From 61841679156a17318af8daac73444e2d12f608b1 Mon Sep 17 00:00:00 2001 From: Alexy Date: Fri, 7 Aug 2026 22:46:47 -0700 Subject: [PATCH 01/24] perf: accelerate policy and memory hot paths --- CHANGELOG.md | 9 ++ crates/typesec-core/benches/policy_check.rs | 51 +++---- crates/typesec-memory/Cargo.toml | 5 + crates/typesec-memory/benches/memory_paths.rs | 103 ++++++++++++++ crates/typesec-memory/src/index.rs | 12 +- crates/typesec-memory/src/record.rs | 5 - crates/typesec-memory/src/store.rs | 19 ++- crates/typesec-memory/src/store/grust.rs | 9 +- crates/typesec-memory/src/store/memory.rs | 9 +- crates/typesec-memory/src/store/tests.rs | 15 ++ crates/typesec-odrl/benches/odrl_check.rs | 71 +++++++--- crates/typesec-odrl/src/engine.rs | 95 +++++++++---- crates/typesec-odrl/src/engine/index.rs | 36 ++--- crates/typesec-odrl/src/engine/tests.rs | 6 +- crates/typesec-rbac/benches/rbac_check.rs | 76 ++++++---- crates/typesec-rbac/src/engine.rs | 130 +++++++++++++----- 16 files changed, 487 insertions(+), 164 deletions(-) create mode 100644 crates/typesec-memory/benches/memory_paths.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index e251d99..c3309ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ by release version, then by the date the logical change landed. ## Unreleased +- Added per-operation Criterion coverage for core policy composition, RBAC + grant scaling, indexed ODRL decisions, in-memory record queries, and keyword + search so authorization and memory-path regressions are measured at realistic + policy and record counts. +- Indexed RBAC resource grants by permission, removed per-decision ODRL lookup + key and candidate-vector allocations, and made in-memory query/search result + selection borrow records until after sorting and limiting. ASCII text filters + now perform case-insensitive matching without lowercase allocations while + retaining the prior Unicode lowercase behavior. - Prepare the `0.13.1` registry release so the current cognition and capability-memory APIs are consumable by released Marciana crates. - Align the release metadata with Grust `0.12.1`, the published graph, diff --git a/crates/typesec-core/benches/policy_check.rs b/crates/typesec-core/benches/policy_check.rs index a5e3966..a6f7318 100644 --- a/crates/typesec-core/benches/policy_check.rs +++ b/crates/typesec-core/benches/policy_check.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use criterion::{Criterion, black_box, criterion_group, criterion_main}; +use criterion::{Criterion, Throughput, black_box, criterion_group, criterion_main}; use typesec_core::{ CanRead, CanWrite, Capability, CombineStrategy, ComposedEngine, LatticeEngine, Permission, PolicyEngine, PolicyResult, Resource, ResourceId, SubjectId, policy::mint_capability, @@ -39,16 +39,17 @@ fn bench_mint_capability_allow(c: &mut Criterion) { let engine = AllowAll; let resource = GenericResource::new("reports/q1", "report"); - c.bench_function("bench_mint_capability_allow", |b| { + let mut group = c.benchmark_group("policy_core"); + group.throughput(Throughput::Elements(1)); + group.bench_function("mint_capability_allow", |b| { b.iter(|| { - for _ in 0..1_000 { - let cap: Capability = - mint_capability(&engine, black_box("agent:bench"), black_box(&resource)) - .expect("allow"); - black_box(cap); - } + let cap: Capability = + mint_capability(&engine, black_box("agent:bench"), black_box(&resource)) + .expect("allow"); + black_box(cap); }) }); + group.finish(); } fn bench_lattice_promotion(c: &mut Criterion) { @@ -57,17 +58,18 @@ fn bench_lattice_promotion(c: &mut Criterion) { let subject = SubjectId::from("agent:bench"); let resource_id = ResourceId::from(resource.resource_id()); - c.bench_function("bench_lattice_promotion", |b| { + let mut group = c.benchmark_group("policy_core"); + group.throughput(Throughput::Elements(1)); + group.bench_function("lattice_promotion", |b| { b.iter(|| { - for _ in 0..1_000 { - let _ = black_box(engine.check( - black_box(&subject), - black_box(CanRead::name()), - black_box(&resource_id), - )); - } + black_box(engine.check( + black_box(&subject), + black_box(CanRead::name()), + black_box(&resource_id), + )) }) }); + group.finish(); } fn bench_composed_engine_deny_overrides(c: &mut Criterion) { @@ -79,17 +81,18 @@ fn bench_composed_engine_deny_overrides(c: &mut Criterion) { let subject = SubjectId::from("agent:bench"); let resource_id = ResourceId::from(resource.resource_id()); - c.bench_function("bench_composed_engine_deny_overrides", |b| { + let mut group = c.benchmark_group("policy_core"); + group.throughput(Throughput::Elements(1)); + group.bench_function("composed_deny_overrides", |b| { b.iter(|| { - for _ in 0..1_000 { - let _ = black_box(engine.check( - black_box(&subject), - black_box(CanWrite::name()), - black_box(&resource_id), - )); - } + black_box(engine.check( + black_box(&subject), + black_box(CanWrite::name()), + black_box(&resource_id), + )) }) }); + group.finish(); } criterion_group!( diff --git a/crates/typesec-memory/Cargo.toml b/crates/typesec-memory/Cargo.toml index efe334c..5083522 100644 --- a/crates/typesec-memory/Cargo.toml +++ b/crates/typesec-memory/Cargo.toml @@ -43,9 +43,14 @@ thiserror = { workspace = true } tracing = { workspace = true } [dev-dependencies] +criterion = { workspace = true } typesec-rbac = { version = "0.13.1", path = "../typesec-rbac" } typesec-odrl = { version = "0.13.1", path = "../typesec-odrl" } typesec-integrations = { version = "0.13.1", path = "../typesec-integrations" } ed25519-dalek = { workspace = true } chrono = { workspace = true } trybuild = "1" + +[[bench]] +name = "memory_paths" +harness = false diff --git a/crates/typesec-memory/benches/memory_paths.rs b/crates/typesec-memory/benches/memory_paths.rs new file mode 100644 index 0000000..8de2d6c --- /dev/null +++ b/crates/typesec-memory/benches/memory_paths.rs @@ -0,0 +1,103 @@ +use criterion::{Criterion, Throughput, black_box, criterion_group, criterion_main}; +use typesec_memory::{ + InMemoryStore, KeywordIndex, MemoryStore, SemanticIndex, StoreQuery, StoredRecord, +}; + +const RECORD_COUNT: usize = 10_000; + +fn record(index: usize) -> StoredRecord { + let text = if index.is_multiple_of(10) { + format!("record {index} contains the target phrase") + } else { + format!("ordinary memory record {index}") + }; + serde_json::from_value(serde_json::json!({ + "id": format!("bench-{index:05}"), + "space_id": "memory/agent:bench/profile", + "kind": "semantic", + "label": "internal", + "quarantined": false, + "entities": [], + "provenance": { "source": "operator" }, + "observed_at": "2026-08-07T00:00:00Z", + "valid_from": "2026-01-01T00:00:00Z", + "invalid_at": null, + "expires_at": null, + "purposes": [], + "content": { "text": text } + })) + .expect("valid benchmark record") +} + +fn populated_store() -> InMemoryStore { + let store = InMemoryStore::new(); + for index in 0..RECORD_COUNT { + store.put(record(index)).expect("insert benchmark record"); + } + store +} + +fn populated_keyword_index() -> KeywordIndex { + let index = KeywordIndex::new(); + for record_index in 0..RECORD_COUNT { + let text = if record_index.is_multiple_of(10) { + format!("record {record_index} contains the target phrase") + } else { + format!("ordinary memory record {record_index}") + }; + index + .index( + &typesec_memory::MemoryId::from_string(format!("bench-{record_index:05}")), + typesec_memory::Label::Internal, + &text, + ) + .expect("index benchmark record"); + } + index +} + +fn bench_store_queries(c: &mut Criterion) { + let store = populated_store(); + let latest = StoreQuery { + space_id: Some("memory/agent:bench/profile".to_owned()), + limit: Some(10), + ..StoreQuery::default() + }; + let text = StoreQuery { + space_id: Some("memory/agent:bench/profile".to_owned()), + text_contains: Some("TARGET PHRASE".to_owned()), + limit: Some(10), + ..StoreQuery::default() + }; + + let mut group = c.benchmark_group("memory_store_query_10k"); + group.sample_size(30); + group.throughput(Throughput::Elements(RECORD_COUNT as u64)); + group.bench_function("latest_limit_10", |b| { + b.iter(|| black_box(store.query(black_box(&latest)).expect("query"))) + }); + group.bench_function("case_insensitive_text_limit_10", |b| { + b.iter(|| black_box(store.query(black_box(&text)).expect("query"))) + }); + group.finish(); +} + +fn bench_keyword_search(c: &mut Criterion) { + let index = populated_keyword_index(); + let mut group = c.benchmark_group("keyword_index_search_10k"); + group.sample_size(30); + group.throughput(Throughput::Elements(RECORD_COUNT as u64)); + group.bench_function("target_phrase_limit_10", |b| { + b.iter(|| { + black_box( + index + .search(black_box("target phrase"), black_box(10)) + .expect("search"), + ) + }) + }); + group.finish(); +} + +criterion_group!(benches, bench_store_queries, bench_keyword_search); +criterion_main!(benches); diff --git a/crates/typesec-memory/src/index.rs b/crates/typesec-memory/src/index.rs index fa4b960..a10a1cf 100644 --- a/crates/typesec-memory/src/index.rs +++ b/crates/typesec-memory/src/index.rs @@ -169,14 +169,18 @@ impl SemanticIndex for KeywordIndex { .entries .read() .unwrap_or_else(std::sync::PoisonError::into_inner); - let mut scored: Vec<(usize, MemoryId)> = entries + let mut scored: Vec<(usize, &MemoryId)> = entries .iter() - .map(|(id, tokens)| (needle.intersection(tokens).count(), id.clone())) + .map(|(id, tokens)| (needle.intersection(tokens).count(), id)) .filter(|(score, _)| *score > 0) .collect(); // Best score first; ties broken by id for determinism. - scored.sort_by(|a, b| b.0.cmp(&a.0).then(a.1.cmp(&b.1))); - Ok(scored.into_iter().take(limit).map(|(_, id)| id).collect()) + scored.sort_by(|a, b| b.0.cmp(&a.0).then(a.1.cmp(b.1))); + Ok(scored + .into_iter() + .take(limit) + .map(|(_, id)| id.clone()) + .collect()) } } diff --git a/crates/typesec-memory/src/record.rs b/crates/typesec-memory/src/record.rs index 58c716d..d9b86cc 100644 --- a/crates/typesec-memory/src/record.rs +++ b/crates/typesec-memory/src/record.rs @@ -254,11 +254,6 @@ impl StoredRecord { &self.content } - /// Crate-internal: lowercased text for the shared store text filter. - pub(crate) fn content_text_lower(&self) -> String { - self.content.text.to_lowercase() - } - /// Crate-internal constructor used by the vault when persisting a draft. #[allow(clippy::too_many_arguments)] pub(crate) fn assemble( diff --git a/crates/typesec-memory/src/store.rs b/crates/typesec-memory/src/store.rs index 2539e08..e39ce57 100644 --- a/crates/typesec-memory/src/store.rs +++ b/crates/typesec-memory/src/store.rs @@ -113,7 +113,7 @@ impl StoreQuery { return false; } if let Some(needle) = &self.text_contains - && !record.content_text_lower().contains(&needle.to_lowercase()) + && !contains_case_insensitive(&record.content().text, needle) { return false; } @@ -130,6 +130,23 @@ impl StoreQuery { } } +/// Preserve Unicode lowercase matching while keeping the overwhelmingly common +/// ASCII path allocation-free. `eq_ignore_ascii_case` applies to arbitrary byte +/// slices, so this also avoids constructing a lowercase copy of every record in +/// a store scan. +fn contains_case_insensitive(haystack: &str, needle: &str) -> bool { + if needle.is_empty() { + return true; + } + if haystack.is_ascii() && needle.is_ascii() { + return haystack + .as_bytes() + .windows(needle.len()) + .any(|window| window.eq_ignore_ascii_case(needle.as_bytes())); + } + haystack.to_lowercase().contains(&needle.to_lowercase()) +} + /// One write within an atomic [`apply_batch`](MemoryStore::apply_batch). #[derive(Debug, Clone, Serialize, Deserialize)] pub enum StoreBatchOp { diff --git a/crates/typesec-memory/src/store/grust.rs b/crates/typesec-memory/src/store/grust.rs index 7decdb8..eb88843 100644 --- a/crates/typesec-memory/src/store/grust.rs +++ b/crates/typesec-memory/src/store/grust.rs @@ -135,17 +135,16 @@ impl MemoryStore for GrustMemoryStore { fn query(&self, query: &StoreQuery) -> Result, StoreError> { let inner = self.read(); - let mut out: Vec = inner + let mut matches: Vec<&StoredRecord> = inner .records .values() .filter(|record| query.matches(record)) - .cloned() .collect(); - out.sort_by(|a, b| b.observed_at.cmp(&a.observed_at).then(b.id.cmp(&a.id))); + matches.sort_by(|a, b| b.observed_at.cmp(&a.observed_at).then(b.id.cmp(&a.id))); if let Some(limit) = query.limit { - out.truncate(limit); + matches.truncate(limit); } - Ok(out) + Ok(matches.into_iter().cloned().collect()) } fn invalidate(&self, id: &MemoryId, at: DateTime) -> Result<(), StoreError> { diff --git a/crates/typesec-memory/src/store/memory.rs b/crates/typesec-memory/src/store/memory.rs index 91eb62f..3b38569 100644 --- a/crates/typesec-memory/src/store/memory.rs +++ b/crates/typesec-memory/src/store/memory.rs @@ -58,17 +58,16 @@ impl MemoryStore for InMemoryStore { fn query(&self, query: &StoreQuery) -> Result, StoreError> { let guard = self.read(); - let mut out: Vec = guard + let mut matches: Vec<&StoredRecord> = guard .values() .filter(|record| query.matches(record)) - .cloned() .collect(); // Deterministic order for tests/ranking: newest observation first. - out.sort_by(|a, b| b.observed_at.cmp(&a.observed_at).then(b.id.cmp(&a.id))); + matches.sort_by(|a, b| b.observed_at.cmp(&a.observed_at).then(b.id.cmp(&a.id))); if let Some(limit) = query.limit { - out.truncate(limit); + matches.truncate(limit); } - Ok(out) + Ok(matches.into_iter().cloned().collect()) } fn invalidate(&self, id: &MemoryId, at: DateTime) -> Result<(), StoreError> { diff --git a/crates/typesec-memory/src/store/tests.rs b/crates/typesec-memory/src/store/tests.rs index 2e1c1be..7450aa4 100644 --- a/crates/typesec-memory/src/store/tests.rs +++ b/crates/typesec-memory/src/store/tests.rs @@ -55,6 +55,21 @@ fn text_and_quarantine_filters() { assert!(include.matches(&quarantined)); } +#[test] +fn text_filter_preserves_unicode_lowercase_semantics() { + let unicode = StoreQuery { + text_contains: Some("CAFÉ".into()), + ..Default::default() + }; + assert!(unicode.matches(&rec("m1", Label::Public, "Rendez-vous au café"))); + + let empty = StoreQuery { + text_contains: Some(String::new()), + ..Default::default() + }; + assert!(empty.matches(&rec("m2", Label::Public, "anything"))); +} + #[test] fn purpose_filter_allows_untagged_and_overlapping() { let q = StoreQuery { diff --git a/crates/typesec-odrl/benches/odrl_check.rs b/crates/typesec-odrl/benches/odrl_check.rs index f6da893..724acd5 100644 --- a/crates/typesec-odrl/benches/odrl_check.rs +++ b/crates/typesec-odrl/benches/odrl_check.rs @@ -1,10 +1,10 @@ -use criterion::{Criterion, black_box, criterion_group, criterion_main}; +use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main}; use typesec_odrl::OdrlEngine; use typesec_odrl::constraint::ConstraintContext; -fn odrl_policy() -> String { +fn odrl_policy(policy_count: usize) -> String { let mut yaml = String::from("policies:\n"); - for idx in 0..10 { + for idx in 0..policy_count { yaml.push_str(&format!( r#" - uid: "policy-{idx}" type: Set @@ -23,24 +23,63 @@ fn odrl_policy() -> String { yaml } -fn bench_odrl_check_with_constraints(c: &mut Criterion) { - let yaml = odrl_policy(); - let engine = OdrlEngine::from_yaml(&yaml).expect("policy"); +fn irrelevant_policy(policy_count: usize) -> String { + let mut yaml = String::from("policies:\n"); + for idx in 0..policy_count { + yaml.push_str(&format!( + r#" - uid: "irrelevant-{idx}" + type: Set + rules: + - type: permission + assignee: "agent:{idx}" + action: read + target: "reports/{idx}/*" +"# + )); + } + yaml +} + +fn bench_odrl_checks(c: &mut Criterion) { let context = ConstraintContext::default().with_purpose("analytics"); + let mut group = c.benchmark_group("odrl_check"); + group.throughput(Throughput::Elements(1)); - c.bench_function("bench_odrl_check_with_constraints", |b| { + for policy_count in [1, 10, 100] { + let yaml = odrl_policy(policy_count); + let engine = OdrlEngine::from_yaml(&yaml).expect("policy"); + let resource = format!("reports/{}/q1", policy_count - 1); + group.bench_with_input( + BenchmarkId::new("constrained_last_target_hit", policy_count), + &policy_count, + |b, _| { + b.iter(|| { + black_box(engine.check_with_context( + black_box("agent:bench"), + black_box("read"), + black_box(&resource), + black_box(&context), + )) + }) + }, + ); + } + + let yaml = irrelevant_policy(1_000); + let engine = OdrlEngine::from_yaml(&yaml).expect("policy"); + group.bench_function("indexed_miss_1000_irrelevant_rules", |b| { b.iter(|| { - for _ in 0..1_000 { - let _ = black_box(engine.check_with_context( - black_box("agent:bench"), - black_box("read"), - black_box("reports/7/q1"), - black_box(&context), - )); - } + black_box(engine.check_with_context( + black_box("agent:bench"), + black_box("read"), + black_box("reports/missing/q1"), + black_box(&context), + )) }) }); + + group.finish(); } -criterion_group!(benches, bench_odrl_check_with_constraints); +criterion_group!(benches, bench_odrl_checks); criterion_main!(benches); diff --git a/crates/typesec-odrl/src/engine.rs b/crates/typesec-odrl/src/engine.rs index ffc6a53..f4ee608 100644 --- a/crates/typesec-odrl/src/engine.rs +++ b/crates/typesec-odrl/src/engine.rs @@ -2,8 +2,6 @@ mod index; -use std::collections::HashMap; - use tracing::debug; use typesec_core::{ ResourceId, SubjectId, @@ -16,7 +14,7 @@ use crate::{ model::{OdrlDocument, OdrlRuleType}, }; use index::{ - CompiledTarget, RuleIndex, RuleRef, WildcardActionIndex, build_rule_index, compile_targets, + CompiledTargets, RuleIndex, RuleRef, WildcardActionIndex, build_rule_index, compile_targets, }; struct RuleMatch { @@ -54,9 +52,9 @@ pub struct OdrlEngine { exact_rules: RuleIndex, /// Same-assignee wildcard action (`use`) rules. wildcard_action_rules: WildcardActionIndex, - /// Each rule's target glob, compiled once at load and keyed by + /// Each rule's target glob, compiled once at load and indexed by /// `(policy_index, rule_index)`. - compiled_targets: HashMap<(usize, usize), CompiledTarget>, + compiled_targets: CompiledTargets, /// Default context applied to every check (can be overridden per-check). default_context: ConstraintContext, } @@ -122,7 +120,7 @@ impl OdrlEngine { "odrl check" ); - let scan = self.scan_candidates(&candidates, action, resource, ctx); + let scan = self.scan_candidates(candidates, action, resource, ctx); build_decision(scan, subject, action, resource) } @@ -130,7 +128,7 @@ impl OdrlEngine { /// matching prohibition. Pure: emits no audit and renders no verdict. fn scan_candidates( &self, - candidates: &[RuleRef], + candidates: impl Iterator, action: &str, resource: &str, ctx: &ConstraintContext, @@ -144,10 +142,8 @@ impl OdrlEngine { let rule = &policy.rules[rule_ref.rule_index]; // Check target (glob) matches, using the pattern compiled at load. - let target_matches = self - .compiled_targets - .get(&(rule_ref.policy_index, rule_ref.rule_index)) - .is_some_and(|target| target.matches(resource)); + let target_matches = + self.compiled_targets[rule_ref.policy_index][rule_ref.rule_index].matches(resource); if !target_matches { continue; } @@ -208,28 +204,79 @@ impl OdrlEngine { } } - fn candidate_rules(&self, subject: &str, action: &str) -> Vec { - let mut candidates = Vec::new(); - - if let Some(exact) = self + fn candidate_rules<'a>(&'a self, subject: &str, action: &str) -> RuleCandidates<'a> { + let exact = self .exact_rules - .get(&(subject.to_owned(), action.to_owned())) - { - candidates.extend_from_slice(exact); - } + .get(subject) + .and_then(|actions| actions.get(action)) + .map(Vec::as_slice) + .unwrap_or_default(); + let wildcard = self + .wildcard_action_rules + .get(subject) + .map(Vec::as_slice) + .unwrap_or_default(); + RuleCandidates::new(exact, wildcard) + } +} - if let Some(wildcard) = self.wildcard_action_rules.get(subject) { - candidates.extend_from_slice(wildcard); +/// Allocation-free merge of exact-action and wildcard-action candidates. Both +/// slices are already in document order, so comparing ordinals preserves +/// deterministic ODRL evaluation without building and sorting a temporary vec. +struct RuleCandidates<'a> { + exact: &'a [RuleRef], + wildcard: &'a [RuleRef], + exact_index: usize, + wildcard_index: usize, +} + +impl<'a> RuleCandidates<'a> { + fn new(exact: &'a [RuleRef], wildcard: &'a [RuleRef]) -> Self { + Self { + exact, + wildcard, + exact_index: 0, + wildcard_index: 0, } + } +} + +impl Iterator for RuleCandidates<'_> { + type Item = RuleRef; - if candidates.len() > 1 { - candidates.sort_by_key(|rule_ref| rule_ref.ordinal); + fn next(&mut self) -> Option { + let exact = self.exact.get(self.exact_index); + let wildcard = self.wildcard.get(self.wildcard_index); + match (exact, wildcard) { + (Some(exact), Some(wildcard)) if exact.ordinal <= wildcard.ordinal => { + self.exact_index += 1; + Some(*exact) + } + (Some(_), Some(wildcard)) => { + self.wildcard_index += 1; + Some(*wildcard) + } + (Some(exact), None) => { + self.exact_index += 1; + Some(*exact) + } + (None, Some(wildcard)) => { + self.wildcard_index += 1; + Some(*wildcard) + } + (None, None) => None, } + } - candidates + fn size_hint(&self) -> (usize, Option) { + let remaining = + self.exact.len() - self.exact_index + self.wildcard.len() - self.wildcard_index; + (remaining, Some(remaining)) } } +impl ExactSizeIterator for RuleCandidates<'_> {} + /// Render an ODRL verdict and the full audit trail for a [`ScanResult`]. /// /// Pure (no logging) so the events are testable. Prohibition wins over diff --git a/crates/typesec-odrl/src/engine/index.rs b/crates/typesec-odrl/src/engine/index.rs index 9db6ece..b3f93da 100644 --- a/crates/typesec-odrl/src/engine/index.rs +++ b/crates/typesec-odrl/src/engine/index.rs @@ -8,9 +8,10 @@ use typesec_core::glob::GlobPattern; use crate::model::{OdrlDocument, RuleAction}; -pub(super) type RuleKey = (String, String); -pub(super) type RuleIndex = HashMap>; +pub(super) type ActionRuleIndex = HashMap>; +pub(super) type RuleIndex = HashMap; pub(super) type WildcardActionIndex = HashMap>; +pub(super) type CompiledTargets = Vec>; /// A rule's target, compiled once at load: the raw target string plus a /// [`GlobPattern`] over its `asset:`-stripped form. @@ -53,18 +54,18 @@ impl CompiledTarget { } } -/// Compile every rule's target once, keyed by `(policy_index, rule_index)`. -pub(super) fn compile_targets(doc: &OdrlDocument) -> HashMap<(usize, usize), CompiledTarget> { - let mut targets = HashMap::new(); - for (policy_index, policy) in doc.policies.iter().enumerate() { - for (rule_index, rule) in policy.rules.iter().enumerate() { - targets.insert( - (policy_index, rule_index), - CompiledTarget::compile(&rule.target), - ); - } - } - targets +/// Compile every rule's target once, indexed by `(policy_index, rule_index)`. +pub(super) fn compile_targets(doc: &OdrlDocument) -> CompiledTargets { + doc.policies + .iter() + .map(|policy| { + policy + .rules + .iter() + .map(|rule| CompiledTarget::compile(&rule.target)) + .collect() + }) + .collect() } /// A pointer into the parsed document identifying a single rule, plus the @@ -98,10 +99,9 @@ pub(super) fn build_rule_index(doc: &OdrlDocument) -> (RuleIndex, WildcardAction .push(rule_ref); } else { exact_rules - .entry(( - rule.assignee.clone(), - rule.action.as_permission_name().to_owned(), - )) + .entry(rule.assignee.clone()) + .or_default() + .entry(rule.action.as_permission_name().to_owned()) .or_default() .push(rule_ref); } diff --git a/crates/typesec-odrl/src/engine/tests.rs b/crates/typesec-odrl/src/engine/tests.rs index 054cd57..745096f 100644 --- a/crates/typesec-odrl/src/engine/tests.rs +++ b/crates/typesec-odrl/src/engine/tests.rs @@ -65,14 +65,16 @@ fn exact_rule_index_is_built_at_construction() { let e = engine(); assert_eq!( e.exact_rules - .get(&("agent:summarizer".to_owned(), "read".to_owned())) + .get("agent:summarizer") + .and_then(|actions| actions.get("read")) .expect("read rule indexed") .len(), 1 ); assert_eq!( e.exact_rules - .get(&("agent:summarizer".to_owned(), "ai:exfiltrate".to_owned())) + .get("agent:summarizer") + .and_then(|actions| actions.get("ai:exfiltrate")) .expect("exfiltrate rule indexed") .len(), 1 diff --git a/crates/typesec-rbac/benches/rbac_check.rs b/crates/typesec-rbac/benches/rbac_check.rs index 48c90b0..dbfcd8a 100644 --- a/crates/typesec-rbac/benches/rbac_check.rs +++ b/crates/typesec-rbac/benches/rbac_check.rs @@ -1,4 +1,4 @@ -use criterion::{Criterion, black_box, criterion_group, criterion_main}; +use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main}; use typesec_core::{PolicyEngine, ResourceId, SubjectId}; use typesec_rbac::RbacEngine; @@ -24,42 +24,72 @@ fn miss_policy() -> String { yaml } -fn bench_rbac_check_hit(c: &mut Criterion) { +fn policy_with_permissions(count: usize) -> String { + let permissions = (0..count) + .map(|idx| format!("action_{idx}")) + .collect::>() + .join(", "); + format!( + r#" +roles: + - name: scaled + permissions: [{permissions}] + resources: ["reports/*"] +assignments: + - subject: "agent:bench" + roles: [scaled] +"# + ) +} + +fn bench_rbac_checks(c: &mut Criterion) { + let mut group = c.benchmark_group("rbac_check"); + group.throughput(Throughput::Elements(1)); + let engine = RbacEngine::from_yaml(HIT_POLICY).expect("policy"); let subject = SubjectId::from("agent:bench"); let resource = ResourceId::from("reports/q1"); - c.bench_function("bench_rbac_check_hit", |b| { + group.bench_function("exact_hit", |b| { b.iter(|| { - for _ in 0..1_000 { - let _ = black_box(engine.check( - black_box(&subject), - black_box("read"), - black_box(&resource), - )); - } + black_box(engine.check(black_box(&subject), black_box("read"), black_box(&resource))) }) }); -} -fn bench_rbac_check_miss(c: &mut Criterion) { let yaml = miss_policy(); let engine = RbacEngine::from_yaml(&yaml).expect("policy"); - let subject = SubjectId::from("agent:bench"); - let resource = ResourceId::from("reports/q1"); - c.bench_function("bench_rbac_check_miss", |b| { + group.bench_function("unassigned_subject_miss", |b| { b.iter(|| { - for _ in 0..1_000 { - let _ = black_box(engine.check( - black_box(&subject), - black_box("write"), - black_box(&resource), - )); - } + black_box(engine.check( + black_box(&subject), + black_box("write"), + black_box(&resource), + )) }) }); + + for permission_count in [1, 16, 64] { + let policy = policy_with_permissions(permission_count); + let engine = RbacEngine::from_yaml(&policy).expect("scaled policy"); + let action = format!("action_{}", permission_count - 1); + group.bench_with_input( + BenchmarkId::new("last_permission_hit", permission_count), + &permission_count, + |b, _| { + b.iter(|| { + black_box(engine.check( + black_box(&subject), + black_box(&action), + black_box(&resource), + )) + }) + }, + ); + } + + group.finish(); } -criterion_group!(benches, bench_rbac_check_hit, bench_rbac_check_miss); +criterion_group!(benches, bench_rbac_checks); criterion_main!(benches); diff --git a/crates/typesec-rbac/src/engine.rs b/crates/typesec-rbac/src/engine.rs index e6e21db..43ae912 100644 --- a/crates/typesec-rbac/src/engine.rs +++ b/crates/typesec-rbac/src/engine.rs @@ -20,26 +20,82 @@ use flatten::flatten_role; /// - Effective permissions per role (with inheritance flattened). /// - Subject → role mappings. /// -/// Every `check()` call does O(roles × patterns) work — fast enough for -/// the sizes of policies used in AI agent deployments. +/// Exact-subject checks use a compact permission lookup followed by only that +/// permission's resource patterns. Wildcard-subject assignments are evaluated +/// separately because their subject globs necessarily depend on the request. pub struct RbacEngine { - /// Subject → set of effective (permission, resource_pattern) pairs. - subject_grants: HashMap>, + /// Subject → compact, permission-indexed compiled resource grants. + subject_grants: HashMap, /// Glob subject pattern → set of effective grants. - wildcard_subject_grants: Vec<(GlobPattern, Vec)>, + wildcard_subject_grants: Vec<(GlobPattern, CompiledGrants)>, } -/// A grant with its glob patterns validated and compiled once at load time. -/// -/// Compiling here (rather than per `check()`) both surfaces pattern typos as -/// load errors — a malformed pattern would otherwise silently never match, -/// i.e. silently deny — and avoids re-parsing the glob on every check. -#[derive(Debug, Clone)] +/// A permission and its resource patterns, all compiled at policy load. +#[derive(Debug)] struct CompiledGrant { permission: String, resource_patterns: Vec, } +/// Sorted effective grants. Tiny policies stay on a one-or-two-comparison +/// linear path; larger policies use binary search without a second hash lookup. +#[derive(Debug, Default)] +struct CompiledGrants { + grants: Vec, +} + +impl CompiledGrants { + const LINEAR_SEARCH_LIMIT: usize = 8; + + fn insert(&mut self, permission: String, patterns: Vec) { + if let Some(existing) = self + .grants + .iter_mut() + .find(|grant| grant.permission == permission) + { + existing.resource_patterns.extend(patterns); + } else { + self.grants.push(CompiledGrant { + permission, + resource_patterns: patterns, + }); + } + } + + fn extend(&mut self, other: Self) { + for grant in other.grants { + self.insert(grant.permission, grant.resource_patterns); + } + self.sort(); + } + + fn sort(&mut self) { + self.grants + .sort_unstable_by(|left, right| left.permission.cmp(&right.permission)); + } + + fn is_empty(&self) -> bool { + self.grants.is_empty() + } + + fn allows(&self, action: &str, resource: &str) -> bool { + let grant = if self.grants.len() <= Self::LINEAR_SEARCH_LIMIT { + self.grants.iter().find(|grant| grant.permission == action) + } else { + self.grants + .binary_search_by(|grant| grant.permission.as_str().cmp(action)) + .ok() + .map(|index| &self.grants[index]) + }; + grant.is_some_and(|grant| { + grant + .resource_patterns + .iter() + .any(|pattern| pattern.matches(resource)) + }) + } +} + impl RbacEngine { /// Build an engine from a validated [`RbacPolicy`]. /// @@ -59,34 +115,35 @@ impl RbacEngine { // Step 2: build subject → grants mapping, compiling patterns up front // so invalid globs fail the policy load instead of silently denying. - let mut subject_grants: HashMap> = HashMap::new(); - let mut wildcard_subject_grants: Vec<(GlobPattern, Vec)> = Vec::new(); + let mut subject_grants: HashMap = HashMap::new(); + let mut wildcard_subject_grants: Vec<(GlobPattern, CompiledGrants)> = Vec::new(); for assignment in &policy.assignments { - let mut all_grants: Vec = Vec::new(); + let mut all_grants = CompiledGrants::default(); for role_name in &assignment.roles { if let Some(grants) = effective_roles.get(role_name) { for grant in grants { - all_grants.push(CompiledGrant { - permission: grant.permission.clone(), - resource_patterns: grant + all_grants.insert( + grant.permission.clone(), + grant .resource_patterns .iter() .map(|p| GlobPattern::compile(p, "resource")) - .collect::>()?, - }); + .collect::, _>>()?, + ); } } } + all_grants.sort(); if is_glob_pattern(&assignment.subject) { wildcard_subject_grants.push(( GlobPattern::compile(&assignment.subject, "subject")?, all_grants, )); } else { - subject_grants + let subject = subject_grants .entry(assignment.subject.clone()) - .or_default() - .extend(all_grants); + .or_default(); + subject.extend(all_grants); } } @@ -109,22 +166,21 @@ impl PolicyEngine for RbacEngine { let resource = resource.as_str(); debug!(subject, action, resource, "rbac check"); - let exact_grants = self.subject_grants.get(subject).into_iter().flatten(); - let wildcard_grants = self - .wildcard_subject_grants - .iter() - .filter(|(pattern, _)| pattern.matches(subject)) - .flat_map(|(_, grants)| grants); - let mut matched_subject = false; - for grant in exact_grants.chain(wildcard_grants) { - matched_subject = true; - if grant.permission == action { - for pattern in &grant.resource_patterns { - if pattern.matches(resource) { - return PolicyResult::Allow; - } - } + if let Some(grants) = self.subject_grants.get(subject) { + matched_subject = !grants.is_empty(); + if grants.allows(action, resource) { + return PolicyResult::Allow; + } + } + + for (subject_pattern, grants) in &self.wildcard_subject_grants { + if !subject_pattern.matches(subject) { + continue; + } + matched_subject |= !grants.is_empty(); + if grants.allows(action, resource) { + return PolicyResult::Allow; } } From 020062bf8e1829cf0775d270f5b14e81b764c043 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 05:39:45 -0700 Subject: [PATCH 02/24] perf(memory): bound top-k ranking work --- CHANGELOG.md | 6 +++++ crates/typesec-memory/src/index.rs | 14 +++++----- crates/typesec-memory/src/store.rs | 25 ++++++++++++++++++ crates/typesec-memory/src/store/grust.rs | 13 ++-------- crates/typesec-memory/src/store/memory.rs | 13 ++-------- crates/typesec-memory/src/store/tests.rs | 31 +++++++++++++++++++++++ 6 files changed, 74 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3309ce..9bd6b9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ by release version, then by the date the logical change landed. ## Unreleased +- Memory stores and the keyword index now partition bounded top-k results in + linear time and sort only the retained results, while preserving deterministic + recency, score, and id ordering. Against 10,000 records, latest-10 queries + improve from about 1.277 milliseconds to 219 microseconds (82.8%), + case-insensitive filtered queries from 470 to 416 microseconds (11.4%), and + keyword top-10 search from 505 to 458 microseconds (9.3%). - Added per-operation Criterion coverage for core policy composition, RBAC grant scaling, indexed ODRL decisions, in-memory record queries, and keyword search so authorization and memory-path regressions are measured at realistic diff --git a/crates/typesec-memory/src/index.rs b/crates/typesec-memory/src/index.rs index a10a1cf..4f93462 100644 --- a/crates/typesec-memory/src/index.rs +++ b/crates/typesec-memory/src/index.rs @@ -175,12 +175,14 @@ impl SemanticIndex for KeywordIndex { .filter(|(score, _)| *score > 0) .collect(); // Best score first; ties broken by id for determinism. - scored.sort_by(|a, b| b.0.cmp(&a.0).then(a.1.cmp(b.1))); - Ok(scored - .into_iter() - .take(limit) - .map(|(_, id)| id.clone()) - .collect()) + let score_order = + |a: &(usize, &MemoryId), b: &(usize, &MemoryId)| b.0.cmp(&a.0).then(a.1.cmp(b.1)); + if limit < scored.len() { + scored.select_nth_unstable_by(limit, score_order); + scored.truncate(limit); + } + scored.sort_unstable_by(score_order); + Ok(scored.into_iter().map(|(_, id)| id.clone()).collect()) } } diff --git a/crates/typesec-memory/src/store.rs b/crates/typesec-memory/src/store.rs index e39ce57..6a7bcf6 100644 --- a/crates/typesec-memory/src/store.rs +++ b/crates/typesec-memory/src/store.rs @@ -147,6 +147,31 @@ fn contains_case_insensitive(haystack: &str, needle: &str) -> bool { haystack.to_lowercase().contains(&needle.to_lowercase()) } +pub(crate) fn query_records<'a>( + records: impl Iterator, + query: &StoreQuery, +) -> Vec { + if query.limit == Some(0) { + return Vec::new(); + } + + let mut matches = records + .filter(|record| query.matches(record)) + .collect::>(); + if let Some(limit) = query.limit + && limit < matches.len() + { + matches.select_nth_unstable_by(limit, recent_record_order); + matches.truncate(limit); + } + matches.sort_unstable_by(recent_record_order); + matches.into_iter().cloned().collect() +} + +fn recent_record_order(a: &&StoredRecord, b: &&StoredRecord) -> std::cmp::Ordering { + b.observed_at.cmp(&a.observed_at).then(b.id.cmp(&a.id)) +} + /// One write within an atomic [`apply_batch`](MemoryStore::apply_batch). #[derive(Debug, Clone, Serialize, Deserialize)] pub enum StoreBatchOp { diff --git a/crates/typesec-memory/src/store/grust.rs b/crates/typesec-memory/src/store/grust.rs index eb88843..ec8a743 100644 --- a/crates/typesec-memory/src/store/grust.rs +++ b/crates/typesec-memory/src/store/grust.rs @@ -23,7 +23,7 @@ use std::sync::{PoisonError, RwLock}; use chrono::{DateTime, Utc}; use grust::prelude::{Graph, Node, NodeId, Value}; -use super::{MemoryStore, StoreError, StoreQuery}; +use super::{MemoryStore, StoreError, StoreQuery, query_records}; use crate::record::StoredRecord; use crate::space::MemoryId; @@ -135,16 +135,7 @@ impl MemoryStore for GrustMemoryStore { fn query(&self, query: &StoreQuery) -> Result, StoreError> { let inner = self.read(); - let mut matches: Vec<&StoredRecord> = inner - .records - .values() - .filter(|record| query.matches(record)) - .collect(); - matches.sort_by(|a, b| b.observed_at.cmp(&a.observed_at).then(b.id.cmp(&a.id))); - if let Some(limit) = query.limit { - matches.truncate(limit); - } - Ok(matches.into_iter().cloned().collect()) + Ok(query_records(inner.records.values(), query)) } fn invalidate(&self, id: &MemoryId, at: DateTime) -> Result<(), StoreError> { diff --git a/crates/typesec-memory/src/store/memory.rs b/crates/typesec-memory/src/store/memory.rs index 3b38569..831b50c 100644 --- a/crates/typesec-memory/src/store/memory.rs +++ b/crates/typesec-memory/src/store/memory.rs @@ -10,7 +10,7 @@ use std::sync::{PoisonError, RwLock}; use chrono::{DateTime, Utc}; -use super::{MemoryStore, StoreError, StoreQuery}; +use super::{MemoryStore, StoreError, StoreQuery, query_records}; use crate::record::StoredRecord; use crate::space::MemoryId; @@ -58,16 +58,7 @@ impl MemoryStore for InMemoryStore { fn query(&self, query: &StoreQuery) -> Result, StoreError> { let guard = self.read(); - let mut matches: Vec<&StoredRecord> = guard - .values() - .filter(|record| query.matches(record)) - .collect(); - // Deterministic order for tests/ranking: newest observation first. - matches.sort_by(|a, b| b.observed_at.cmp(&a.observed_at).then(b.id.cmp(&a.id))); - if let Some(limit) = query.limit { - matches.truncate(limit); - } - Ok(matches.into_iter().cloned().collect()) + Ok(query_records(guard.values(), query)) } fn invalidate(&self, id: &MemoryId, at: DateTime) -> Result<(), StoreError> { diff --git a/crates/typesec-memory/src/store/tests.rs b/crates/typesec-memory/src/store/tests.rs index 7450aa4..b452908 100644 --- a/crates/typesec-memory/src/store/tests.rs +++ b/crates/typesec-memory/src/store/tests.rs @@ -120,3 +120,34 @@ fn in_memory_store_roundtrips_and_invalidates() { assert!(store.tombstone(&MemoryId::from_string("m2")).unwrap()); assert!(!store.tombstone(&MemoryId::from_string("nope")).unwrap()); } + +#[test] +fn in_memory_store_limit_preserves_rank_order() { + let store = InMemoryStore::new(); + for id in ["m1", "m4", "m2", "m3"] { + store.put(rec(id, Label::Public, id)).unwrap(); + } + + let limited = store + .query(&StoreQuery { + limit: Some(2), + ..Default::default() + }) + .unwrap(); + assert_eq!( + limited + .iter() + .map(|record| record.id.as_str()) + .collect::>(), + ["m4", "m3"] + ); + assert!( + store + .query(&StoreQuery { + limit: Some(0), + ..Default::default() + }) + .unwrap() + .is_empty() + ); +} From b364d7ab3e072850b954c58a6595368b32d9f203 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 05:53:32 -0700 Subject: [PATCH 03/24] bench(memory): cover keyword index selectivity --- crates/typesec-memory/benches/memory_paths.rs | 97 +++++++++++++++---- 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/crates/typesec-memory/benches/memory_paths.rs b/crates/typesec-memory/benches/memory_paths.rs index 8de2d6c..8488e3b 100644 --- a/crates/typesec-memory/benches/memory_paths.rs +++ b/crates/typesec-memory/benches/memory_paths.rs @@ -1,6 +1,7 @@ use criterion::{Criterion, Throughput, black_box, criterion_group, criterion_main}; use typesec_memory::{ - InMemoryStore, KeywordIndex, MemoryStore, SemanticIndex, StoreQuery, StoredRecord, + InMemoryStore, KeywordIndex, Label, MemoryId, MemoryStore, SemanticIndex, StoreQuery, + StoredRecord, }; const RECORD_COUNT: usize = 10_000; @@ -40,22 +41,23 @@ fn populated_store() -> InMemoryStore { fn populated_keyword_index() -> KeywordIndex { let index = KeywordIndex::new(); for record_index in 0..RECORD_COUNT { - let text = if record_index.is_multiple_of(10) { - format!("record {record_index} contains the target phrase") - } else { - format!("ordinary memory record {record_index}") - }; + let (id, text) = keyword_document(record_index); index - .index( - &typesec_memory::MemoryId::from_string(format!("bench-{record_index:05}")), - typesec_memory::Label::Internal, - &text, - ) + .index(&id, typesec_memory::Label::Internal, &text) .expect("index benchmark record"); } index } +fn keyword_document(index: usize) -> (MemoryId, String) { + let text = if index.is_multiple_of(10) { + format!("record {index} contains the target phrase") + } else { + format!("ordinary memory record {index}") + }; + (MemoryId::from_string(format!("bench-{index:05}")), text) +} + fn bench_store_queries(c: &mut Criterion) { let store = populated_store(); let latest = StoreQuery { @@ -87,17 +89,78 @@ fn bench_keyword_search(c: &mut Criterion) { let mut group = c.benchmark_group("keyword_index_search_10k"); group.sample_size(30); group.throughput(Throughput::Elements(RECORD_COUNT as u64)); - group.bench_function("target_phrase_limit_10", |b| { + for (name, query) in [ + ("sparse_target_phrase_limit_10", "target phrase"), + ("common_memory_record_limit_10", "memory record"), + ("missing_tokens_limit_10", "tokens absent everywhere"), + ] { + group.bench_function(name, |b| { + b.iter(|| { + black_box( + index + .search(black_box(query), black_box(10)) + .expect("search"), + ) + }) + }); + } + group.finish(); + + let id = MemoryId::from_string("bench-00000"); + let mut group = c.benchmark_group("keyword_index_mutation_10k"); + group.sample_size(30); + group.throughput(Throughput::Elements(1)); + group.bench_function("reindex_unchanged", |b| { b.iter(|| { - black_box( + index + .index( + black_box(&id), + black_box(Label::Internal), + black_box("updated target phrase memory record"), + ) + .expect("replace indexed record") + }) + }); + group.bench_function("replace_changed_tokens", |b| { + let mut use_alpha = false; + b.iter(|| { + use_alpha = !use_alpha; + let text = if use_alpha { + "alternating alpha memory record" + } else { + "alternating beta memory record" + }; + index + .index(black_box(&id), black_box(Label::Internal), black_box(text)) + .expect("replace indexed record") + }) + }); + group.finish(); +} + +fn bench_keyword_population(c: &mut Criterion) { + let documents = (0..RECORD_COUNT).map(keyword_document).collect::>(); + let mut group = c.benchmark_group("keyword_index_population"); + group.sample_size(20); + group.throughput(Throughput::Elements(RECORD_COUNT as u64)); + group.bench_function("build_10k", |b| { + b.iter_with_large_drop(|| { + let index = KeywordIndex::new(); + for (id, text) in &documents { index - .search(black_box("target phrase"), black_box(10)) - .expect("search"), - ) + .index(id, Label::Internal, text) + .expect("index benchmark record"); + } + index }) }); group.finish(); } -criterion_group!(benches, bench_store_queries, bench_keyword_search); +criterion_group!( + benches, + bench_store_queries, + bench_keyword_search, + bench_keyword_population +); criterion_main!(benches); From 8a699bd57554a8e5c1df3cee0411bf1f78a7adc9 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 06:01:08 -0700 Subject: [PATCH 04/24] perf(memory): index selective keyword queries --- CHANGELOG.md | 7 ++ crates/typesec-memory/src/index.rs | 142 ++++++++++++++++++++++++++--- 2 files changed, 136 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bd6b9d..6db6a04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ by release version, then by the date the logical change landed. ## Unreleased +- Keyword search now uses compact inverted postings for selective queries and + an adaptive document scan for dense queries, with stable internal document + keys and idempotent reindexing. Against 10,000 records, sparse top-10 search + improves from about 449 to 66 microseconds, dense search from 543 to 478 + microseconds, and a no-hit search from 497 microseconds to 216 nanoseconds. + Building the richer index rises from about 3.8 to 9.6 milliseconds and an + update that changes tokens from 271 to 624 nanoseconds. - Memory stores and the keyword index now partition bounded top-k results in linear time and sort only the retained results, while preserving deterministic recency, score, and id ordering. Against 10,000 records, latest-10 queries diff --git a/crates/typesec-memory/src/index.rs b/crates/typesec-memory/src/index.rs index 4f93462..41679ff 100644 --- a/crates/typesec-memory/src/index.rs +++ b/crates/typesec-memory/src/index.rs @@ -19,6 +19,9 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; +use std::collections::{BTreeSet, HashMap, HashSet}; +use std::sync::{Arc, RwLock}; + use crate::label::Label; use crate::space::MemoryId; @@ -125,8 +128,20 @@ pub trait SemanticIndex: Send + Sync { /// wiring and gives tests a stable ranking. #[derive(Default)] pub struct KeywordIndex { - entries: - std::sync::RwLock>>, + entries: RwLock, +} + +#[derive(Default)] +struct KeywordEntries { + documents: Vec>, + document_keys: HashMap, usize>, + vacant_keys: Vec, + postings: HashMap>, +} + +struct KeywordDocument { + id: Arc, + tokens: BTreeSet, } impl KeywordIndex { @@ -135,28 +150,97 @@ impl KeywordIndex { Self::default() } - fn tokens(text: &str) -> std::collections::BTreeSet { + fn tokens(text: &str) -> BTreeSet { text.split(|c: char| !c.is_alphanumeric()) .filter(|t| !t.is_empty()) .map(str::to_lowercase) .collect() } + + fn remove_posting(entries: &mut KeywordEntries, key: usize, token: &str) { + let remove_posting = entries.postings.get_mut(token).is_some_and(|keys| { + keys.remove(&key); + keys.is_empty() + }); + if remove_posting { + entries.postings.remove(token); + } + } + + fn remove_postings(entries: &mut KeywordEntries, key: usize, tokens: BTreeSet) { + for token in tokens { + Self::remove_posting(entries, key, &token); + } + } } impl SemanticIndex for KeywordIndex { fn index(&self, id: &MemoryId, _label: Label, text: &str) -> Result<(), IndexError> { - self.entries + let tokens = Self::tokens(text); + let mut entries = self + .entries .write() - .unwrap_or_else(std::sync::PoisonError::into_inner) - .insert(id.clone(), Self::tokens(text)); + .unwrap_or_else(std::sync::PoisonError::into_inner); + if let Some(&key) = entries.document_keys.get(id) { + let document = entries.documents[key] + .as_mut() + .expect("keyword index document key must be valid"); + if document.tokens == tokens { + return Ok(()); + } + let old_tokens = std::mem::take(&mut document.tokens); + for token in old_tokens.difference(&tokens) { + Self::remove_posting(&mut entries, key, token); + } + for token in tokens.difference(&old_tokens) { + entries + .postings + .entry(token.clone()) + .or_default() + .insert(key); + } + entries.documents[key] + .as_mut() + .expect("keyword index document key must be valid") + .tokens = tokens; + return Ok(()); + } + + let key = entries.vacant_keys.pop().unwrap_or(entries.documents.len()); + for token in &tokens { + entries + .postings + .entry(token.clone()) + .or_default() + .insert(key); + } + let id = Arc::new(id.clone()); + let document = KeywordDocument { + id: Arc::clone(&id), + tokens, + }; + entries.document_keys.insert(id, key); + if key == entries.documents.len() { + entries.documents.push(Some(document)); + } else { + entries.documents[key] = Some(document); + } Ok(()) } fn remove(&self, id: &MemoryId) -> Result<(), IndexError> { - self.entries + let mut entries = self + .entries .write() - .unwrap_or_else(std::sync::PoisonError::into_inner) - .remove(id); + .unwrap_or_else(std::sync::PoisonError::into_inner); + let Some((_, key)) = entries.document_keys.remove_entry(id) else { + return Ok(()); + }; + let document = entries.documents[key] + .take() + .expect("keyword index document key must be valid"); + Self::remove_postings(&mut entries, key, document.tokens); + entries.vacant_keys.push(key); Ok(()) } @@ -169,11 +253,43 @@ impl SemanticIndex for KeywordIndex { .entries .read() .unwrap_or_else(std::sync::PoisonError::into_inner); - let mut scored: Vec<(usize, &MemoryId)> = entries + let posting_visits = needle .iter() - .map(|(id, tokens)| (needle.intersection(tokens).count(), id)) - .filter(|(score, _)| *score > 0) - .collect(); + .filter_map(|token| entries.postings.get(token)) + .map(HashSet::len) + .sum::(); + let mut scored = if posting_visits >= entries.document_keys.len() { + entries + .documents + .iter() + .flatten() + .map(|document| { + ( + needle.intersection(&document.tokens).count(), + document.id.as_ref(), + ) + }) + .filter(|(score, _)| *score > 0) + .collect::>() + } else { + let mut scores = HashMap::::new(); + for token in &needle { + if let Some(keys) = entries.postings.get(token) { + for &key in keys { + *scores.entry(key).or_default() += 1; + } + } + } + scores + .into_iter() + .map(|(key, score)| { + let document = entries.documents[key] + .as_ref() + .expect("keyword index posting key must be valid"); + (score, document.id.as_ref()) + }) + .collect::>() + }; // Best score first; ties broken by id for determinism. let score_order = |a: &(usize, &MemoryId), b: &(usize, &MemoryId)| b.0.cmp(&a.0).then(a.1.cmp(b.1)); From e5d5a088cf7293f4650703463788ca6a864db27b Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 06:05:12 -0700 Subject: [PATCH 05/24] bench(memory): cover cognition digest scaling --- crates/typesec-memory/Cargo.toml | 4 + .../typesec-memory/benches/cognition_paths.rs | 123 ++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 crates/typesec-memory/benches/cognition_paths.rs diff --git a/crates/typesec-memory/Cargo.toml b/crates/typesec-memory/Cargo.toml index 5083522..67478db 100644 --- a/crates/typesec-memory/Cargo.toml +++ b/crates/typesec-memory/Cargo.toml @@ -54,3 +54,7 @@ trybuild = "1" [[bench]] name = "memory_paths" harness = false + +[[bench]] +name = "cognition_paths" +harness = false diff --git a/crates/typesec-memory/benches/cognition_paths.rs b/crates/typesec-memory/benches/cognition_paths.rs new file mode 100644 index 0000000..543ab88 --- /dev/null +++ b/crates/typesec-memory/benches/cognition_paths.rs @@ -0,0 +1,123 @@ +use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main}; +use typesec_memory::{ + CognitionBinding, CognitionProposal, Label, MemoryContent, MemoryDraft, MemoryId, MemoryKind, + Provenance, governed_source_draft_digest, +}; + +fn digest(fill: char) -> String { + format!("sha256:{}", fill.to_string().repeat(64)) +} + +fn binding(projection_count: usize) -> CognitionBinding { + CognitionBinding { + space_id: "memory/agent:bench/profile".to_owned(), + subject: "did:key:benchmark".to_owned(), + purpose: "benchmark".to_owned(), + governed_source_scope: None, + governed_scan_digest: digest('1'), + snapshot_digest: digest('2'), + plan_task_digest: digest('3'), + authorization_receipt_digest: digest('4'), + effective_projection: (0..projection_count) + .rev() + .map(|index| format!("field-{index:04}")) + .collect(), + source_manifest_digest: digest('5'), + typedid_request_digest: digest('6'), + } +} + +fn draft(text_bytes: usize) -> MemoryDraft { + MemoryDraft::new( + MemoryKind::Semantic, + MemoryContent::text("x".repeat(text_bytes)), + Provenance::Operator, + ) + .with_label(Label::Internal) +} + +fn proposal(draft_count: usize, text_bytes: usize) -> CognitionProposal { + let binding = binding(16); + CognitionProposal::new( + "benchmark-job", + binding.snapshot_digest.clone(), + binding.source_manifest_digest.clone(), + "marciana.benchmark", + "1", + vec![MemoryId::from_string("benchmark-source")], + Label::Internal, + ) + .with_drafts((0..draft_count).map(|_| draft(text_bytes)).collect()) + .with_binding(binding) +} + +fn bench_governed_draft_digest(c: &mut Criterion) { + let mut group = c.benchmark_group("governed_draft_digest"); + group.sample_size(30); + for text_bytes in [256, 65_536] { + let draft = draft(text_bytes); + let serialized_bytes = serde_json::to_vec(&draft) + .expect("serialize benchmark draft") + .len(); + group.throughput(Throughput::Bytes(serialized_bytes as u64)); + group.bench_with_input( + BenchmarkId::from_parameter(format_args!("{text_bytes}_text_bytes")), + &draft, + |b, draft| { + b.iter(|| { + black_box(governed_source_draft_digest(black_box(draft)).expect("draft digest")) + }) + }, + ); + } + group.finish(); +} + +fn bench_binding_digest(c: &mut Criterion) { + let mut group = c.benchmark_group("cognition_binding_digest"); + group.sample_size(30); + for projection_count in [4, 256] { + let binding = binding(projection_count); + let serialized_bytes = serde_json::to_vec(&binding) + .expect("serialize benchmark binding") + .len(); + group.throughput(Throughput::Bytes(serialized_bytes as u64)); + group.bench_with_input( + BenchmarkId::from_parameter(format_args!("{projection_count}_fields")), + &binding, + |b, binding| b.iter(|| black_box(binding.canonical_digest().expect("binding digest"))), + ); + } + group.finish(); +} + +fn bench_proposal_digest(c: &mut Criterion) { + let mut group = c.benchmark_group("cognition_proposal_digest"); + group.sample_size(30); + for (draft_count, text_bytes) in [(1, 256), (64, 1_024), (256, 1_024)] { + let proposal = proposal(draft_count, text_bytes); + let serialized_bytes = serde_json::to_vec(&proposal) + .expect("serialize benchmark proposal") + .len(); + proposal + .canonical_digest() + .expect("valid benchmark proposal"); + group.throughput(Throughput::Bytes(serialized_bytes as u64)); + group.bench_with_input( + BenchmarkId::new("drafts", draft_count), + &proposal, + |b, proposal| { + b.iter(|| black_box(proposal.canonical_digest().expect("proposal digest"))) + }, + ); + } + group.finish(); +} + +criterion_group!( + benches, + bench_governed_draft_digest, + bench_binding_digest, + bench_proposal_digest +); +criterion_main!(benches); From 82d903c3526a5d5021c5dca8473a0f5eff314225 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 06:11:40 -0700 Subject: [PATCH 06/24] perf(crypto): enable accelerated SHA-256 --- CHANGELOG.md | 4 ++++ Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6db6a04..98011b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ by release version, then by the date the logical change landed. ## Unreleased +- SHA-256 now enables its accelerated backend on supported targets. Production + benchmarks reduce a 64 KiB governed-draft digest from about 245 to 61 + microseconds and a 256-draft cognition-proposal digest from 1.421 + milliseconds to 593 microseconds, while retaining the portable fallback. - Keyword search now uses compact inverted postings for selective queries and an adaptive document scan for dense queries, with stable internal document keys and idempotent reindexing. Against 10,000 records, sparse top-10 search diff --git a/Cargo.toml b/Cargo.toml index af42139..079a024 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ glob = "0.3" ed25519-dalek = "2" x25519-dalek = { version = "2", features = ["static_secrets"] } chacha20poly1305 = "0.10" -sha2 = "0.10" +sha2 = { version = "0.10", features = ["asm"] } getrandom = "0.2" base64 = "0.22" jsonschema = { version = "0.26", default-features = false } From ba4c46f4ad1fc0088049e77edb037aa98ab4d567 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 06:19:51 -0700 Subject: [PATCH 07/24] perf(memory): stream borrowed cognition identities --- CHANGELOG.md | 4 + crates/typesec-memory/src/cognition.rs | 4 +- .../typesec-memory/src/cognition/canonical.rs | 6 + crates/typesec-memory/src/cognition/digest.rs | 107 +++++++++++++++--- .../src/cognition/tests/prepared_commit.rs | 17 ++- crates/typesec-memory/src/cognition/types.rs | 16 ++- .../typesec-memory/src/cognition/validate.rs | 8 +- 7 files changed, 129 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98011b7..40cfcc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ by release version, then by the date the logical change landed. benchmarks reduce a 64 KiB governed-draft digest from about 245 to 61 microseconds and a 256-draft cognition-proposal digest from 1.421 milliseconds to 593 microseconds, while retaining the portable fallback. +- Cognition identities now stream borrowed canonical binding and proposal + views instead of cloning protected draft payloads and digest strings. A + 256-field binding digest improves from about 28.4 to 11.1 microseconds and a + 256-draft proposal digest from 593 to 499 microseconds after SHA acceleration. - Keyword search now uses compact inverted postings for selective queries and an adaptive document scan for dense queries, with stable internal document keys and idempotent reindexing. Against 10,000 records, sparse top-10 search diff --git a/crates/typesec-memory/src/cognition.rs b/crates/typesec-memory/src/cognition.rs index e06101d..3d0b4b5 100644 --- a/crates/typesec-memory/src/cognition.rs +++ b/crates/typesec-memory/src/cognition.rs @@ -78,8 +78,8 @@ impl crate::CognitionProposal { impl CognitionBinding { /// Domain-separated canonical digest of governed authority evidence. pub fn canonical_digest(&self) -> Result { - self.validate()?; - digest::binding_digest(self) + let projection = self.validate_and_canonical_projection()?; + digest::binding_digest_with_projection(self, projection) } } diff --git a/crates/typesec-memory/src/cognition/canonical.rs b/crates/typesec-memory/src/cognition/canonical.rs index dd0e1eb..760af20 100644 --- a/crates/typesec-memory/src/cognition/canonical.rs +++ b/crates/typesec-memory/src/cognition/canonical.rs @@ -3,6 +3,12 @@ use super::limits::MAX_COGNITION_IDENTITY_BYTES; pub(super) use crate::canonical::is_canonical_sha256; +pub(super) fn canonical_projection(projection: &[String]) -> Vec<&str> { + let mut canonical = projection.iter().map(String::as_str).collect::>(); + canonical.sort_unstable(); + canonical +} + pub(super) fn is_canonical_text(value: &str) -> bool { !value.is_empty() && value.len() <= MAX_COGNITION_IDENTITY_BYTES diff --git a/crates/typesec-memory/src/cognition/digest.rs b/crates/typesec-memory/src/cognition/digest.rs index dc00c70..44629c7 100644 --- a/crates/typesec-memory/src/cognition/digest.rs +++ b/crates/typesec-memory/src/cognition/digest.rs @@ -1,14 +1,16 @@ use serde::Serialize; use sha2::{Digest, Sha256}; -use super::PreparedCognitionCommit; +use super::canonical::canonical_projection; use super::types::{ CognitionApplyError, CognitionBinding, CognitionSourceManifest, CognitionSourcePrecondition, }; +use super::{CognitionEffect, PreparedCognitionCommit}; use crate::index::IndexMutation; use crate::store::StoreBatchOp; use crate::{ - CognitionAuditEvidence, CognitionIdempotencyKey, CognitionProposal, Label, StoredRecord, + CognitionAuditEvidence, CognitionIdempotencyKey, CognitionProposal, ConsolidationPlan, + GovernedSourceScope, Label, MemoryDraft, MemoryId, StoredRecord, }; const RECORD_DOMAIN: &[u8] = b"typesec.marciana.source-record.v1\0"; @@ -71,22 +73,99 @@ pub(super) fn source_manifest( } pub(super) fn binding_digest(binding: &CognitionBinding) -> Result { - let mut canonical = binding.clone(); - canonical.effective_projection.sort(); - tagged_serialized_digest(BINDING_DOMAIN, &canonical) + binding_digest_with_projection(binding, canonical_projection(&binding.effective_projection)) +} + +pub(super) fn binding_digest_with_projection( + binding: &CognitionBinding, + projection: Vec<&str>, +) -> Result { + tagged_serialized_digest(BINDING_DOMAIN, &CanonicalBinding::new(binding, projection)) } pub(super) fn proposal_digest(proposal: &CognitionProposal) -> Result { - let mut canonical = proposal.clone(); - // Creation time is observational scheduler metadata, not mutation - // identity. A worker retry may regenerate the same inert proposal later; - // every authority, source, plan, draft, and evidence field remains bound - // below while the durable idempotency digest stays stable. - canonical.created_at = chrono::DateTime::::UNIX_EPOCH; - if let Some(binding) = &mut canonical.binding { - binding.effective_projection.sort(); + tagged_serialized_digest(PROPOSAL_DOMAIN, &CanonicalProposal::new(proposal)) +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct CanonicalBinding<'a> { + space_id: &'a str, + subject: &'a str, + purpose: &'a str, + #[serde(skip_serializing_if = "Option::is_none")] + governed_source_scope: Option<&'a GovernedSourceScope>, + governed_scan_digest: &'a str, + snapshot_digest: &'a str, + plan_task_digest: &'a str, + authorization_receipt_digest: &'a str, + effective_projection: Vec<&'a str>, + source_manifest_digest: &'a str, + typedid_request_digest: &'a str, +} + +impl<'a> CanonicalBinding<'a> { + fn new(binding: &'a CognitionBinding, effective_projection: Vec<&'a str>) -> Self { + Self { + space_id: &binding.space_id, + subject: &binding.subject, + purpose: &binding.purpose, + governed_source_scope: binding.governed_source_scope.as_ref(), + governed_scan_digest: &binding.governed_scan_digest, + snapshot_digest: &binding.snapshot_digest, + plan_task_digest: &binding.plan_task_digest, + authorization_receipt_digest: &binding.authorization_receipt_digest, + effective_projection, + source_manifest_digest: &binding.source_manifest_digest, + typedid_request_digest: &binding.typedid_request_digest, + } + } +} + +#[derive(Serialize)] +struct CanonicalProposal<'a> { + schema_version: u32, + effect: CognitionEffect, + job_id: &'a str, + input_snapshot: &'a str, + source_digest: &'a str, + algorithm: &'a str, + algorithm_version: &'a str, + source_ids: &'a [MemoryId], + joined_label: Label, + drafts: &'a [MemoryDraft], + plan: &'a ConsolidationPlan, + evidence: &'a [String], + created_at: chrono::DateTime, + #[serde(skip_serializing_if = "Option::is_none")] + binding: Option>, +} + +impl<'a> CanonicalProposal<'a> { + fn new(proposal: &'a CognitionProposal) -> Self { + Self { + schema_version: proposal.schema_version, + effect: proposal.effect, + job_id: &proposal.job_id, + input_snapshot: &proposal.input_snapshot, + source_digest: &proposal.source_digest, + algorithm: &proposal.algorithm, + algorithm_version: &proposal.algorithm_version, + source_ids: &proposal.source_ids, + joined_label: proposal.joined_label, + drafts: &proposal.drafts, + plan: &proposal.plan, + evidence: &proposal.evidence, + // Creation time is observational scheduler metadata, not mutation + // identity. A worker retry may regenerate the same inert proposal + // later while every authority, source, plan, draft, and evidence + // field remains bound. + created_at: chrono::DateTime::::UNIX_EPOCH, + binding: proposal.binding.as_ref().map(|binding| { + CanonicalBinding::new(binding, canonical_projection(&binding.effective_projection)) + }), + } } - tagged_serialized_digest(PROPOSAL_DOMAIN, &canonical) } pub(super) fn evidence_digest(evidence: &[String]) -> Result { diff --git a/crates/typesec-memory/src/cognition/tests/prepared_commit.rs b/crates/typesec-memory/src/cognition/tests/prepared_commit.rs index bd5a31e..e794059 100644 --- a/crates/typesec-memory/src/cognition/tests/prepared_commit.rs +++ b/crates/typesec-memory/src/cognition/tests/prepared_commit.rs @@ -123,14 +123,23 @@ fn preparation_rejects_a_type_sec_timestamp_after_preparation() { fn streaming_hashing_matches_the_versioned_canonical_profiles() { let fixture = prepared_fixture(prepared_at()); - let mut canonical_binding = fixture.binding.clone(); + let mut binding = fixture.binding.clone(); + binding.effective_projection.reverse(); + let mut canonical_binding = binding.clone(); canonical_binding.effective_projection.sort(); assert_eq!( - fixture.binding.canonical_digest().unwrap(), + binding.canonical_digest().unwrap(), legacy_digest(b"typesec.marciana.binding.v1\0", &canonical_binding) ); - let mut canonical_proposal = fixture.proposal.clone(); + let mut proposal = fixture.proposal.clone(); + proposal + .binding + .as_mut() + .expect("bound proposal") + .effective_projection + .reverse(); + let mut canonical_proposal = proposal.clone(); canonical_proposal.created_at = DateTime::::UNIX_EPOCH; canonical_proposal .binding @@ -139,7 +148,7 @@ fn streaming_hashing_matches_the_versioned_canonical_profiles() { .effective_projection .sort(); assert_eq!( - fixture.proposal.canonical_digest().unwrap(), + proposal.canonical_digest().unwrap(), legacy_digest(b"typesec.marciana.proposal.v2\0", &canonical_proposal) ); diff --git a/crates/typesec-memory/src/cognition/types.rs b/crates/typesec-memory/src/cognition/types.rs index ca4ef31..c7bd857 100644 --- a/crates/typesec-memory/src/cognition/types.rs +++ b/crates/typesec-memory/src/cognition/types.rs @@ -10,7 +10,7 @@ use crate::space::MemoryId; use crate::store::{MemoryStore, StoreError}; use super::PreparedCognitionCommit; -use super::canonical::{is_canonical_sha256, is_canonical_text}; +use super::canonical::{canonical_projection, is_canonical_sha256, is_canonical_text}; use super::limits::validate_projection_count; /// Immutable authority and input evidence a cognition proposal must echo. @@ -48,6 +48,12 @@ pub struct CognitionBinding { impl CognitionBinding { pub(crate) fn validate(&self) -> Result<(), CognitionApplyError> { + self.validate_and_canonical_projection().map(drop) + } + + pub(super) fn validate_and_canonical_projection( + &self, + ) -> Result, CognitionApplyError> { for (name, value) in [ ("spaceId", self.space_id.as_str()), ("subject", self.subject.as_str()), @@ -88,15 +94,13 @@ impl CognitionBinding { "effectiveProjection".to_owned(), )); } - let mut canonical = self.effective_projection.clone(); - canonical.sort(); - canonical.dedup(); - if canonical.len() != self.effective_projection.len() { + let canonical = canonical_projection(&self.effective_projection); + if canonical.windows(2).any(|pair| pair[0] == pair[1]) { return Err(CognitionApplyError::InvalidBinding( "effectiveProjection contains duplicates".to_owned(), )); } - Ok(()) + Ok(canonical) } } diff --git a/crates/typesec-memory/src/cognition/validate.rs b/crates/typesec-memory/src/cognition/validate.rs index c1cae8b..b196646 100644 --- a/crates/typesec-memory/src/cognition/validate.rs +++ b/crates/typesec-memory/src/cognition/validate.rs @@ -5,7 +5,7 @@ use typesec_core::policy::RequestContext; use typesec_core::{CanWrite, Capability, Resource}; use super::CognitionEffect; -use super::canonical::{is_canonical_sha256, is_canonical_text}; +use super::canonical::{canonical_projection, is_canonical_sha256, is_canonical_text}; use super::limits::{CognitionSourceBudget, MAX_COGNITION_SOURCE_COUNT, validate_proposal_budget}; use super::types::{CognitionApplyError, CognitionAuthorityEvidence, CognitionBinding}; use crate::CognitionProposal; @@ -214,12 +214,6 @@ pub(super) fn load_sources( Ok(records) } -fn canonical_projection(projection: &[String]) -> Vec<&str> { - let mut canonical: Vec<_> = projection.iter().map(String::as_str).collect(); - canonical.sort_unstable(); - canonical -} - fn validate_source_ids(source_ids: &[MemoryId]) -> Result<(), CognitionApplyError> { if source_ids.len() > MAX_COGNITION_SOURCE_COUNT { return Err(CognitionApplyError::LimitExceeded("source count")); From c2a7de3975af4b5af1b218904b099f66dfa79ae3 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 06:21:23 -0700 Subject: [PATCH 08/24] bench(memory): isolate cognition wire serialization --- .../typesec-memory/benches/cognition_paths.rs | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/crates/typesec-memory/benches/cognition_paths.rs b/crates/typesec-memory/benches/cognition_paths.rs index 543ab88..9d0f10a 100644 --- a/crates/typesec-memory/benches/cognition_paths.rs +++ b/crates/typesec-memory/benches/cognition_paths.rs @@ -4,6 +4,8 @@ use typesec_memory::{ Provenance, governed_source_draft_digest, }; +const PROPOSAL_CASES: [(usize, usize); 3] = [(1, 256), (64, 1_024), (256, 1_024)]; + fn digest(fill: char) -> String { format!("sha256:{}", fill.to_string().repeat(64)) } @@ -94,7 +96,7 @@ fn bench_binding_digest(c: &mut Criterion) { fn bench_proposal_digest(c: &mut Criterion) { let mut group = c.benchmark_group("cognition_proposal_digest"); group.sample_size(30); - for (draft_count, text_bytes) in [(1, 256), (64, 1_024), (256, 1_024)] { + for (draft_count, text_bytes) in PROPOSAL_CASES { let proposal = proposal(draft_count, text_bytes); let serialized_bytes = serde_json::to_vec(&proposal) .expect("serialize benchmark proposal") @@ -114,10 +116,34 @@ fn bench_proposal_digest(c: &mut Criterion) { group.finish(); } +fn bench_proposal_wire(c: &mut Criterion) { + let mut group = c.benchmark_group("cognition_proposal_wire"); + group.sample_size(30); + for (draft_count, text_bytes) in PROPOSAL_CASES { + let proposal = proposal(draft_count, text_bytes); + let serialized_bytes = serde_json::to_vec(&proposal) + .expect("serialize benchmark proposal") + .len(); + group.throughput(Throughput::Bytes(serialized_bytes as u64)); + group.bench_with_input( + BenchmarkId::new("serialize_to_sink", draft_count), + &proposal, + |b, proposal| { + b.iter(|| { + serde_json::to_writer(std::io::sink(), black_box(proposal)) + .expect("serialize proposal") + }) + }, + ); + } + group.finish(); +} + criterion_group!( benches, bench_governed_draft_digest, bench_binding_digest, - bench_proposal_digest + bench_proposal_digest, + bench_proposal_wire ); criterion_main!(benches); From fa1138719e09fa940f07e984513fb29d0bc86e3e Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 06:31:40 -0700 Subject: [PATCH 09/24] perf(memory): validate proposal identity in one pass --- CHANGELOG.md | 4 + crates/typesec-memory/src/cognition.rs | 6 +- crates/typesec-memory/src/cognition/apply.rs | 5 +- crates/typesec-memory/src/cognition/digest.rs | 93 ++++++++++++++++++- .../typesec-memory/src/cognition/identity.rs | 4 +- crates/typesec-memory/src/cognition/limits.rs | 40 +------- .../src/cognition/tests/prepared_commit.rs | 7 +- .../typesec-memory/src/cognition/validate.rs | 34 +++++-- 8 files changed, 137 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40cfcc6..3043b97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ by release version, then by the date the logical change landed. views instead of cloning protected draft payloads and digest strings. A 256-field binding digest improves from about 28.4 to 11.1 microseconds and a 256-draft proposal digest from 593 to 499 microseconds after SHA acceleration. +- Proposal validation now enforces the exact raw-wire byte ceiling while + streaming the canonical identity through one bounded buffered pass, then + carries that digest into commit preparation instead of serializing again. A + 256-draft digest improves further from about 499 to 372 microseconds. - Keyword search now uses compact inverted postings for selective queries and an adaptive document scan for dense queries, with stable internal document keys and idempotent reindexing. Against 10,000 records, sparse top-10 search diff --git a/crates/typesec-memory/src/cognition.rs b/crates/typesec-memory/src/cognition.rs index 3d0b4b5..9bb51ad 100644 --- a/crates/typesec-memory/src/cognition.rs +++ b/crates/typesec-memory/src/cognition.rs @@ -54,7 +54,7 @@ impl crate::CognitionProposal { proposal.schema_version, )); } - validate::validate_proposal_shape(&proposal)?; + validate::validate_decoded_proposal(&proposal)?; if let Some(binding) = &proposal.binding { binding.validate()?; } @@ -67,11 +67,11 @@ impl crate::CognitionProposal { /// is excluded, so a later worker retry of the same governed decision has /// the same identity without reimplementing TypeSec internals. pub fn canonical_digest(&self) -> Result { - validate::validate_proposal_shape(self)?; + let digest = validate::validate_proposal_identity(self)?; if let Some(binding) = &self.binding { binding.validate()?; } - digest::proposal_digest(self) + Ok(digest) } } diff --git a/crates/typesec-memory/src/cognition/apply.rs b/crates/typesec-memory/src/cognition/apply.rs index eb56916..e56a6cb 100644 --- a/crates/typesec-memory/src/cognition/apply.rs +++ b/crates/typesec-memory/src/cognition/apply.rs @@ -105,7 +105,7 @@ impl MemoryVault { let verifier = self .cognition_authority() .ok_or(CognitionApplyError::AuthorityVerifierUnavailable)?; - validate_proposal_for_application(proposal)?; + let proposal_digest = validate_proposal_for_application(proposal)?; let binding = proposal .binding .as_ref() @@ -121,7 +121,8 @@ impl MemoryVault { validate_authority(proposal, binding, &authority)?; let authority_revalidated_at = clock(); - let identity = CognitionCommitIdentity::from_validated(space, proposal, binding)?; + let identity = + CognitionCommitIdentity::from_validated(space, proposal, binding, proposal_digest)?; if let Some(recovered) = self .store() .recover_cognition(&identity.key, &identity.proposal_digest)? diff --git a/crates/typesec-memory/src/cognition/digest.rs b/crates/typesec-memory/src/cognition/digest.rs index 44629c7..a94b07e 100644 --- a/crates/typesec-memory/src/cognition/digest.rs +++ b/crates/typesec-memory/src/cognition/digest.rs @@ -20,6 +20,8 @@ const PROPOSAL_DOMAIN: &[u8] = b"typesec.marciana.proposal.v2\0"; const EVIDENCE_DOMAIN: &[u8] = b"typesec.marciana.evidence.v1\0"; const PREPARED_COMMIT_DOMAIN: &[u8] = b"typesec.marciana.prepared-commit.v5\0"; const AUTHORITY_SCOPE_DOMAIN: &[u8] = b"typesec.marciana.authority-scope.v1\0"; +// Coalesce serde's field-sized writes before the accelerated SHA backend. +const PROPOSAL_DIGEST_BUFFER_BYTES: usize = 32 * 1024; fn tagged_serialized_digest( domain: &[u8], @@ -83,8 +85,95 @@ pub(super) fn binding_digest_with_projection( tagged_serialized_digest(BINDING_DOMAIN, &CanonicalBinding::new(binding, projection)) } -pub(super) fn proposal_digest(proposal: &CognitionProposal) -> Result { - tagged_serialized_digest(PROPOSAL_DOMAIN, &CanonicalProposal::new(proposal)) +pub(super) fn proposal_digest_with_wire_limit( + proposal: &CognitionProposal, + max_wire_bytes: usize, +) -> Result { + // Canonicalization only reorders projection strings (which preserves byte + // length) and normalizes this timestamp. Adjusting for the two serialized + // timestamp lengths therefore enforces the exact noncanonical wire limit + // while hashing the canonical representation in the same bounded pass. + let canonical_time_bytes = serialized_len(&chrono::DateTime::::UNIX_EPOCH)?; + let observed_time_bytes = serialized_len(&proposal.created_at)?; + let canonical_limit = max_wire_bytes + .checked_sub(observed_time_bytes) + .and_then(|remaining| remaining.checked_add(canonical_time_bytes)) + .ok_or(CognitionApplyError::LimitExceeded("proposal bytes"))?; + + let mut digest = Sha256::new(); + digest.update(PROPOSAL_DOMAIN); + let mut writer = BoundedDigestWriter::new(&mut digest, canonical_limit); + let serialized = { + let mut buffered = + std::io::BufWriter::with_capacity(PROPOSAL_DIGEST_BUFFER_BYTES, &mut writer); + serde_json::to_writer(&mut buffered, &CanonicalProposal::new(proposal)) + .and_then(|()| std::io::Write::flush(&mut buffered).map_err(serde_json::Error::io)) + }; + if writer.exceeded { + return Err(CognitionApplyError::LimitExceeded("proposal bytes")); + } + serialized.map_err(|error| CognitionApplyError::Serialization(error.to_string()))?; + Ok(format!("sha256:{:x}", digest.finalize())) +} + +fn serialized_len(value: &impl Serialize) -> Result { + let mut writer = LengthWriter::default(); + serde_json::to_writer(&mut writer, value) + .map_err(|error| CognitionApplyError::Serialization(error.to_string()))?; + Ok(writer.written) +} + +#[derive(Default)] +struct LengthWriter { + written: usize, +} + +impl std::io::Write for LengthWriter { + fn write(&mut self, bytes: &[u8]) -> std::io::Result { + self.written = self + .written + .checked_add(bytes.len()) + .ok_or_else(|| std::io::Error::other("serialized length overflow"))?; + Ok(bytes.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +struct BoundedDigestWriter<'a> { + digest: &'a mut Sha256, + remaining: usize, + exceeded: bool, +} + +impl<'a> BoundedDigestWriter<'a> { + fn new(digest: &'a mut Sha256, limit: usize) -> Self { + Self { + digest, + remaining: limit, + exceeded: false, + } + } +} + +impl std::io::Write for BoundedDigestWriter<'_> { + fn write(&mut self, bytes: &[u8]) -> std::io::Result { + if bytes.len() > self.remaining { + self.exceeded = true; + return Err(std::io::Error::other( + "cognition proposal exceeds byte limit", + )); + } + self.remaining -= bytes.len(); + self.digest.update(bytes); + Ok(bytes.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } } #[derive(Serialize)] diff --git a/crates/typesec-memory/src/cognition/identity.rs b/crates/typesec-memory/src/cognition/identity.rs index 1316a09..de93f80 100644 --- a/crates/typesec-memory/src/cognition/identity.rs +++ b/crates/typesec-memory/src/cognition/identity.rs @@ -5,7 +5,7 @@ use std::collections::BTreeSet; use sha2::{Digest, Sha256}; use typesec_core::Resource; -use super::digest::{binding_digest, evidence_digest, proposal_digest}; +use super::digest::{binding_digest, evidence_digest}; use super::limits::proposal_output_count; use super::{ CognitionApplyError, CognitionAuditEvidence, CognitionBinding, CognitionEffect, @@ -40,8 +40,8 @@ impl CognitionCommitIdentity { space: &MemorySpace, proposal: &CognitionProposal, binding: &CognitionBinding, + proposal_digest: String, ) -> Result { - let proposal_digest = proposal_digest(proposal)?; let key = CognitionIdempotencyKey::for_authority( &binding.space_id, &binding.subject, diff --git a/crates/typesec-memory/src/cognition/limits.rs b/crates/typesec-memory/src/cognition/limits.rs index ea43e6a..c102cd2 100644 --- a/crates/typesec-memory/src/cognition/limits.rs +++ b/crates/typesec-memory/src/cognition/limits.rs @@ -42,7 +42,7 @@ pub(super) fn validate_projection_count(count: usize) -> Result<(), CognitionApp ) } -pub(super) fn validate_proposal_budget( +pub(super) fn validate_proposal_dimensions( proposal: &CognitionProposal, ) -> Result<(), CognitionApplyError> { enforce( @@ -84,14 +84,7 @@ pub(super) fn validate_proposal_budget( .checked_add(targets) .ok_or(CognitionApplyError::LimitExceeded("mutation count"))?; enforce(operations <= MAX_COGNITION_MUTATIONS, "mutation count")?; - validate_prepared_expansion(proposal, outputs)?; - - let mut writer = BoundedWriter::new(MAX_COGNITION_PROPOSAL_BYTES); - let serialized = serde_json::to_writer(&mut writer, proposal); - if writer.exceeded { - return Err(CognitionApplyError::LimitExceeded("proposal bytes")); - } - serialized.map_err(|error| CognitionApplyError::Serialization(error.to_string())) + validate_prepared_expansion(proposal, outputs) } pub(super) fn proposal_output_count( @@ -299,35 +292,6 @@ fn enforce(allowed: bool, limit: &'static str) -> Result<(), CognitionApplyError } } -struct BoundedWriter { - remaining: usize, - exceeded: bool, -} - -impl BoundedWriter { - fn new(limit: usize) -> Self { - Self { - remaining: limit, - exceeded: false, - } - } -} - -impl Write for BoundedWriter { - fn write(&mut self, bytes: &[u8]) -> io::Result { - if bytes.len() > self.remaining { - self.exceeded = true; - return Err(io::Error::other("cognition proposal exceeds byte limit")); - } - self.remaining -= bytes.len(); - Ok(bytes.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - struct MeasuringWriter { remaining: usize, written: usize, diff --git a/crates/typesec-memory/src/cognition/tests/prepared_commit.rs b/crates/typesec-memory/src/cognition/tests/prepared_commit.rs index e794059..c20f399 100644 --- a/crates/typesec-memory/src/cognition/tests/prepared_commit.rs +++ b/crates/typesec-memory/src/cognition/tests/prepared_commit.rs @@ -299,10 +299,13 @@ fn try_prepared_fixture_with_evidence( }), ) .with_binding(binding.clone()); - super::super::validate::validate_proposal_for_application(&proposal) + let proposal_digest = super::super::validate::validate_proposal_for_application(&proposal) .expect("valid cognition proposal"); let identity = super::super::identity::CognitionCommitIdentity::from_validated( - &space, &proposal, &binding, + &space, + &proposal, + &binding, + proposal_digest, ) .expect("commit identity"); let authority = authority_for(&binding); diff --git a/crates/typesec-memory/src/cognition/validate.rs b/crates/typesec-memory/src/cognition/validate.rs index b196646..06247fe 100644 --- a/crates/typesec-memory/src/cognition/validate.rs +++ b/crates/typesec-memory/src/cognition/validate.rs @@ -6,7 +6,11 @@ use typesec_core::{CanWrite, Capability, Resource}; use super::CognitionEffect; use super::canonical::{canonical_projection, is_canonical_sha256, is_canonical_text}; -use super::limits::{CognitionSourceBudget, MAX_COGNITION_SOURCE_COUNT, validate_proposal_budget}; +use super::digest::proposal_digest_with_wire_limit; +use super::limits::{ + CognitionSourceBudget, MAX_COGNITION_PROPOSAL_BYTES, MAX_COGNITION_SOURCE_COUNT, + validate_proposal_dimensions, +}; use super::types::{CognitionApplyError, CognitionAuthorityEvidence, CognitionBinding}; use crate::CognitionProposal; use crate::error::MemoryError; @@ -25,23 +29,39 @@ pub(super) fn required_purpose(context: &RequestContext) -> Result<&str, Cogniti .ok_or(CognitionApplyError::MissingPurpose) } -pub(super) fn validate_proposal_shape( +pub(super) fn validate_decoded_proposal( proposal: &CognitionProposal, ) -> Result<(), CognitionApplyError> { - validate_proposal(proposal, false) + validate_proposal_dimensions(proposal)?; + validate_proposal_structure(proposal, false) +} + +pub(super) fn validate_proposal_identity( + proposal: &CognitionProposal, +) -> Result { + validate_and_digest_proposal(proposal, false) } pub(super) fn validate_proposal_for_application( proposal: &CognitionProposal, -) -> Result<(), CognitionApplyError> { - validate_proposal(proposal, true) +) -> Result { + validate_and_digest_proposal(proposal, true) +} + +fn validate_and_digest_proposal( + proposal: &CognitionProposal, + require_mutation: bool, +) -> Result { + validate_proposal_dimensions(proposal)?; + let digest = proposal_digest_with_wire_limit(proposal, MAX_COGNITION_PROPOSAL_BYTES)?; + validate_proposal_structure(proposal, require_mutation)?; + Ok(digest) } -fn validate_proposal( +fn validate_proposal_structure( proposal: &CognitionProposal, require_mutation: bool, ) -> Result<(), CognitionApplyError> { - validate_proposal_budget(proposal)?; if ![ CognitionProposal::MIN_SCHEMA_VERSION, CognitionProposal::SCHEMA_VERSION, From 5f099c119553bc88ebd45a03d3b43cd3b9b3bc96 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 06:38:32 -0700 Subject: [PATCH 10/24] bench(integrations): cover DID and receipt hot paths --- CHANGELOG.md | 4 + crates/typesec-integrations/Cargo.toml | 5 + .../benches/integration_paths.rs | 405 ++++++++++++++++++ 3 files changed, 414 insertions(+) create mode 100644 crates/typesec-integrations/benches/integration_paths.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 3043b97..ed306dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ by release version, then by the date the logical change landed. ## Unreleased +- Added production Criterion coverage for TypeDID replay protection, Ed25519 + signing, X25519/ChaCha20-Poly1305 encryption, complete envelope seal/open and + references, and decision and cognition receipt issue/verification, including + replay-cache scaling and concurrent bursts. - SHA-256 now enables its accelerated backend on supported targets. Production benchmarks reduce a 64 KiB governed-draft digest from about 245 to 61 microseconds and a 256-draft cognition-proposal digest from 1.421 diff --git a/crates/typesec-integrations/Cargo.toml b/crates/typesec-integrations/Cargo.toml index 0de5113..4426c7d 100644 --- a/crates/typesec-integrations/Cargo.toml +++ b/crates/typesec-integrations/Cargo.toml @@ -33,5 +33,10 @@ thiserror = { workspace = true } tracing = { workspace = true } [dev-dependencies] +criterion = { workspace = true } opentelemetry_sdk = { version = "0.30", default-features = false, features = ["trace", "testing"] } trybuild = "1" + +[[bench]] +name = "integration_paths" +harness = false diff --git a/crates/typesec-integrations/benches/integration_paths.rs b/crates/typesec-integrations/benches/integration_paths.rs new file mode 100644 index 0000000..450c690 --- /dev/null +++ b/crates/typesec-integrations/benches/integration_paths.rs @@ -0,0 +1,405 @@ +use std::sync::Arc; + +use chrono::{TimeDelta, TimeZone, Utc}; +use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main}; +use ed25519_dalek::SigningKey; +use typesec_integrations::{ + CognitionCommitReceipt, CognitionCommitReceiptClaims, CognitionEffect, DecisionReceipt, Did, + DidEnvelope, DidKeyStore, DidMessageBody, Ed25519DidKey, Ed25519DidKeyStore, + InMemoryReplayStore, ReceiptIssuer, ReceiptVerifier, ReplayStore, StaticDidResolver, + TypeDidConversation, TypeDidGateway, TypeDidMode, TypeDidProfile, VerificationMethod, +}; + +const NOW: u64 = 1_800_000_000; +const EXPIRY: u64 = NOW + 300; +const PAYLOAD_SIZES: [usize; 2] = [256, 65_536]; + +struct DidFixture { + alice: Did, + agent: Did, + resolver: StaticDidResolver, + keys: Ed25519DidKeyStore, + alice_authentication: VerificationMethod, + alice_agreement_public: [u8; 32], + agent_agreement_public: [u8; 32], +} + +fn did_fixture() -> DidFixture { + let alice_key = Ed25519DidKey::from_seed(b"benchmark-alice-ed25519"); + let agent_key = Ed25519DidKey::from_seed(b"benchmark-agent-ed25519"); + let alice = Did::key(alice_key.signing_public()); + let agent = Did::key(agent_key.signing_public()); + let alice_document = alice_key.document(alice.clone()); + let agent_document = agent_key.document(agent.clone()); + let alice_authentication = alice_document.verification_method[0].clone(); + let alice_agreement_public = alice_key.agreement_public(); + let agent_agreement_public = agent_key.agreement_public(); + let resolver = StaticDidResolver::new() + .with_document(alice_document) + .with_document(agent_document); + let keys = Ed25519DidKeyStore::new() + .with_key(alice.clone(), alice_key) + .with_key(agent.clone(), agent_key); + DidFixture { + alice, + agent, + resolver, + keys, + alice_authentication, + alice_agreement_public, + agent_agreement_public, + } +} + +fn typedid_envelope(fixture: &DidFixture, payload: &[u8]) -> DidEnvelope { + DidEnvelope::typedid( + "benchmark-envelope", + fixture.alice.clone(), + fixture.agent.clone(), + DidMessageBody::agent_message("memory/benchmark", "secret") + .with_claim("purpose", "benchmark") + .with_claim("agent_id", "agent:benchmark"), + TypeDidConversation::new( + "benchmark-conversation", + TypeDidMode::RequestReply, + TypeDidProfile::ed25519_x25519_chacha20().id, + "a2a", + ), + payload, + &fixture.resolver, + &fixture.keys, + ) + .expect("seal benchmark envelope") +} + +#[derive(Debug)] +struct AcceptingReplayStore; + +impl ReplayStore for AcceptingReplayStore { + fn claim(&self, _: &str, _: u64, _: u64) -> Result { + Ok(true) + } +} + +fn populated_replay_store(entries: usize) -> Arc { + let store = Arc::new(InMemoryReplayStore::new()); + for index in 0..entries { + assert!( + store + .claim(&format!("active-envelope-{index}"), EXPIRY, NOW) + .expect("populate replay store") + ); + } + store +} + +fn bench_replay_store(c: &mut Criterion) { + let mut group = c.benchmark_group("did_replay_claim"); + group.sample_size(30); + for entries in [1, 1_000, 10_000] { + let store = populated_replay_store(entries); + group.throughput(Throughput::Elements(1)); + group.bench_with_input(BenchmarkId::new("active_hit", entries), &entries, |b, _| { + b.iter(|| { + black_box( + store + .claim(black_box("active-envelope-0"), EXPIRY, NOW) + .expect("check replay claim"), + ) + }) + }); + } + group.finish(); + + let store = populated_replay_store(10_000); + let mut concurrent = c.benchmark_group("did_replay_concurrent_burst"); + concurrent.sample_size(20); + for threads in [1, 8] { + const CLAIMS_PER_THREAD: usize = 128; + concurrent.throughput(Throughput::Elements((threads * CLAIMS_PER_THREAD) as u64)); + concurrent.bench_with_input( + BenchmarkId::from_parameter(threads), + &threads, + |b, &threads| { + b.iter(|| { + std::thread::scope(|scope| { + for _ in 0..threads { + let store = Arc::clone(&store); + scope.spawn(move || { + for _ in 0..CLAIMS_PER_THREAD { + black_box( + store + .claim("active-envelope-0", EXPIRY, NOW) + .expect("check concurrent replay claim"), + ); + } + }); + } + }); + }); + }, + ); + } + concurrent.finish(); +} + +fn bench_did_crypto(c: &mut Criterion) { + let fixture = did_fixture(); + let nonce = [7_u8; 12]; + let associated_data = b"typesec integration benchmark associated data"; + + let mut signing = c.benchmark_group("did_ed25519"); + signing.sample_size(30); + for payload_bytes in PAYLOAD_SIZES { + let payload = vec![b'x'; payload_bytes]; + let signature = fixture + .keys + .sign(&fixture.alice, &payload) + .expect("sign benchmark payload"); + signing.throughput(Throughput::Bytes(payload_bytes as u64)); + signing.bench_with_input( + BenchmarkId::new("sign", payload_bytes), + &payload, + |b, payload| { + b.iter(|| { + black_box( + fixture + .keys + .sign(&fixture.alice, black_box(payload)) + .expect("sign benchmark payload"), + ) + }) + }, + ); + signing.bench_with_input( + BenchmarkId::new("verify", payload_bytes), + &payload, + |b, payload| { + b.iter(|| { + fixture + .keys + .verify( + &fixture.alice_authentication, + black_box(payload), + black_box(&signature), + ) + .expect("verify benchmark payload") + }) + }, + ); + } + signing.finish(); + + let mut encryption = c.benchmark_group("did_x25519_chacha20poly1305"); + encryption.sample_size(30); + for payload_bytes in PAYLOAD_SIZES { + let payload = vec![b'x'; payload_bytes]; + let ciphertext = fixture + .keys + .encrypt_for( + &fixture.alice, + &fixture.agent_agreement_public, + &payload, + &nonce, + associated_data, + ) + .expect("encrypt benchmark payload"); + encryption.throughput(Throughput::Bytes(payload_bytes as u64)); + encryption.bench_with_input( + BenchmarkId::new("encrypt", payload_bytes), + &payload, + |b, payload| { + b.iter(|| { + black_box( + fixture + .keys + .encrypt_for( + &fixture.alice, + &fixture.agent_agreement_public, + black_box(payload), + &nonce, + associated_data, + ) + .expect("encrypt benchmark payload"), + ) + }) + }, + ); + encryption.bench_with_input( + BenchmarkId::new("decrypt", payload_bytes), + &ciphertext, + |b, ciphertext| { + b.iter(|| { + black_box( + fixture + .keys + .decrypt_for( + &fixture.agent, + &fixture.alice_agreement_public, + &nonce, + black_box(ciphertext), + associated_data, + ) + .expect("decrypt benchmark payload"), + ) + }) + }, + ); + } + encryption.finish(); +} + +fn bench_typedid(c: &mut Criterion) { + let fixture = did_fixture(); + let mut group = c.benchmark_group("typedid_envelope"); + group.sample_size(30); + + for payload_bytes in PAYLOAD_SIZES { + let payload = vec![b'x'; payload_bytes]; + let envelope = typedid_envelope(&fixture, &payload); + let gateway = TypeDidGateway::new( + Arc::new(fixture.resolver.clone()), + Arc::new(fixture.keys.clone()), + fixture.agent.clone(), + ) + .with_replay_store(Arc::new(AcceptingReplayStore)); + group.throughput(Throughput::Bytes(payload_bytes as u64)); + group.bench_with_input( + BenchmarkId::new("seal", payload_bytes), + &payload, + |b, payload| b.iter(|| black_box(typedid_envelope(&fixture, black_box(payload)))), + ); + group.bench_with_input( + BenchmarkId::new("open", payload_bytes), + &envelope, + |b, envelope| { + b.iter(|| { + black_box( + gateway + .open_message(black_box(envelope)) + .expect("open benchmark envelope"), + ) + }) + }, + ); + group.bench_with_input( + BenchmarkId::new("reference", payload_bytes), + &envelope, + |b, envelope| b.iter(|| black_box(black_box(envelope).reference())), + ); + } + group.finish(); +} + +fn digest(fill: char) -> String { + format!("sha256:{}", fill.to_string().repeat(64)) +} + +fn cognition_receipt(affected_ids: usize) -> CognitionCommitReceipt { + let authority = Utc.with_ymd_and_hms(2026, 8, 5, 11, 59, 0).unwrap(); + let prepared = Utc.with_ymd_and_hms(2026, 8, 5, 12, 0, 0).unwrap(); + CognitionCommitReceipt::new( + CognitionCommitReceiptClaims { + effect: CognitionEffect::Mutated, + subject: "did:key:benchmark-agent".into(), + resource: "memory/did:key:benchmark-agent/research".into(), + job_id: "benchmark-job".into(), + governed_source_scope: Some("lakecat:warehouse/benchmark".into()), + typedid_request_digest: digest('1'), + proposal_digest: digest('2'), + governed_scan_digest: digest('3'), + input_snapshot_digest: digest('4'), + policy_decision_digest: digest('5'), + authorization_receipt_digest: digest('6'), + prior_version: "version-before".into(), + resulting_version: "version-after".into(), + affected_ids: (0..affected_ids) + .map(|index| format!("memory-{index:04}")) + .collect(), + backend_commit_id: "commit-benchmark".into(), + authority_revalidated_at: authority, + prepared_at: prepared, + committed_at: prepared + TimeDelta::seconds(1), + issued_at: prepared + TimeDelta::seconds(2), + }, + TimeDelta::minutes(5), + ) + .expect("construct benchmark cognition receipt") +} + +fn bench_receipts(c: &mut Criterion) { + let now = Utc.with_ymd_and_hms(2026, 8, 5, 12, 0, 3).unwrap(); + let issuer = ReceiptIssuer::new(SigningKey::from_bytes(&[11_u8; 32])); + let verifier = ReceiptVerifier::new(issuer.verifying_key()); + let decision = DecisionReceipt::new( + "did:key:benchmark-agent", + "memory:remember", + "memory/did:key:benchmark-agent/research", + now, + TimeDelta::minutes(5), + ) + .for_tool_call("remember", Some("call-benchmark")); + let decision_token = issuer.issue(&decision); + + let mut decisions = c.benchmark_group("decision_receipt"); + decisions.sample_size(30); + decisions.bench_function("issue", |b| { + b.iter(|| black_box(issuer.issue(black_box(&decision)))) + }); + decisions.bench_function("verify", |b| { + b.iter(|| { + black_box( + verifier + .verify(black_box(&decision_token), now) + .expect("verify benchmark decision receipt"), + ) + }) + }); + decisions.finish(); + + let mut cognition = c.benchmark_group("cognition_receipt"); + cognition.sample_size(30); + for affected_ids in [2, 256] { + let receipt = cognition_receipt(affected_ids); + let token = issuer + .issue_cognition(&receipt, now) + .expect("issue benchmark cognition receipt"); + cognition.throughput(Throughput::Elements(affected_ids as u64)); + cognition.bench_with_input( + BenchmarkId::new("issue", affected_ids), + &receipt, + |b, receipt| { + b.iter(|| { + black_box( + issuer + .issue_cognition(black_box(receipt), now) + .expect("issue benchmark cognition receipt"), + ) + }) + }, + ); + cognition.bench_with_input( + BenchmarkId::new("verify", affected_ids), + &token, + |b, token| { + b.iter(|| { + black_box( + verifier + .verify_cognition(black_box(token), now) + .expect("verify benchmark cognition receipt"), + ) + }) + }, + ); + } + cognition.finish(); +} + +criterion_group!( + benches, + bench_replay_store, + bench_did_crypto, + bench_typedid, + bench_receipts +); +criterion_main!(benches); From adc01766d4e720f54ca787a4a4af683e1c54d59a Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 06:40:47 -0700 Subject: [PATCH 11/24] fix(bench): use a canonical governed scope --- crates/typesec-integrations/benches/integration_paths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/typesec-integrations/benches/integration_paths.rs b/crates/typesec-integrations/benches/integration_paths.rs index 450c690..e0568bc 100644 --- a/crates/typesec-integrations/benches/integration_paths.rs +++ b/crates/typesec-integrations/benches/integration_paths.rs @@ -304,7 +304,7 @@ fn cognition_receipt(affected_ids: usize) -> CognitionCommitReceipt { subject: "did:key:benchmark-agent".into(), resource: "memory/did:key:benchmark-agent/research".into(), job_id: "benchmark-job".into(), - governed_source_scope: Some("lakecat:warehouse/benchmark".into()), + governed_source_scope: Some(digest('a')), typedid_request_digest: digest('1'), proposal_digest: digest('2'), governed_scan_digest: digest('3'), From 9dc3fe9a99c49dbc3c253217bca63b8c28a52c8a Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 06:49:24 -0700 Subject: [PATCH 12/24] perf(integrations): prune replay claims by expiry --- CHANGELOG.md | 6 ++ crates/typesec-integrations/src/did/replay.rs | 72 +++++++++++++++++-- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed306dd..2a9c53e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ by release version, then by the date the logical change landed. ## Unreleased +- In-memory DID replay protection now prunes claims through an expiry-ordered + queue instead of scanning every active claim while holding its mutex. At + 10,000 active claims, replay hits improve from about 14.1 microseconds to + 25.9 nanoseconds, while an eight-thread burst improves from about 60,300 to + 3.86 million claims per second; the one-entry path rises from 24.2 to 25.9 + nanoseconds. - Added production Criterion coverage for TypeDID replay protection, Ed25519 signing, X25519/ChaCha20-Poly1305 encryption, complete envelope seal/open and references, and decision and cognition receipt issue/verification, including diff --git a/crates/typesec-integrations/src/did/replay.rs b/crates/typesec-integrations/src/did/replay.rs index 18e36ca..f00b5c4 100644 --- a/crates/typesec-integrations/src/did/replay.rs +++ b/crates/typesec-integrations/src/did/replay.rs @@ -1,7 +1,8 @@ //! Replay-claim authority for DID and TypeDID gateways. -use std::collections::HashMap; -use std::sync::{Mutex, PoisonError}; +use std::cmp::Reverse; +use std::collections::{BinaryHeap, HashMap}; +use std::sync::{Arc, Mutex, PoisonError}; /// Atomically records authenticated envelope identities until they expire. /// @@ -18,7 +19,31 @@ pub trait ReplayStore: Send + Sync { /// Process-local replay authority used by default. #[derive(Debug, Default)] pub struct InMemoryReplayStore { - seen: Mutex>, + claims: Mutex, +} + +#[derive(Debug, Default)] +struct ReplayClaims { + seen: HashMap, u64>, + expirations: BinaryHeap)>>, +} + +impl ReplayClaims { + fn remove_expired(&mut self, now: u64) { + while self + .expirations + .peek() + .is_some_and(|Reverse((expiry, _))| *expiry < now) + { + let Reverse((expiry, key)) = self + .expirations + .pop() + .expect("peeked replay expiration must remain present"); + if self.seen.get(key.as_ref()) == Some(&expiry) { + self.seen.remove(key.as_ref()); + } + } + } } impl InMemoryReplayStore { @@ -30,12 +55,45 @@ impl InMemoryReplayStore { impl ReplayStore for InMemoryReplayStore { fn claim(&self, key: &str, expires_at: u64, now: u64) -> Result { - let mut seen = self.seen.lock().unwrap_or_else(PoisonError::into_inner); - seen.retain(|_, expiry| *expiry >= now); - if seen.contains_key(key) { + let mut claims = self.claims.lock().unwrap_or_else(PoisonError::into_inner); + claims.remove_expired(now); + if claims.seen.contains_key(key) { return Ok(false); } - seen.insert(key.to_owned(), expires_at); + let key: Arc = Arc::from(key); + claims.seen.insert(Arc::clone(&key), expires_at); + claims.expirations.push(Reverse((expires_at, key))); Ok(true) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn active_claims_are_rejected_through_the_expiry_second() { + let store = InMemoryReplayStore::new(); + assert!(store.claim("envelope", 20, 10).unwrap()); + assert!(!store.claim("envelope", 20, 19).unwrap()); + assert!(!store.claim("envelope", 20, 20).unwrap()); + } + + #[test] + fn expired_claims_can_be_reclaimed() { + let store = InMemoryReplayStore::new(); + assert!(store.claim("envelope", 20, 10).unwrap()); + assert!(store.claim("envelope", 40, 21).unwrap()); + assert!(!store.claim("envelope", 40, 21).unwrap()); + } + + #[test] + fn expiration_pruning_preserves_later_active_claims() { + let store = InMemoryReplayStore::new(); + assert!(store.claim("early", 20, 10).unwrap()); + assert!(store.claim("late", 40, 10).unwrap()); + assert!(store.claim("new", 50, 21).unwrap()); + assert!(!store.claim("late", 40, 21).unwrap()); + assert!(store.claim("early", 50, 21).unwrap()); + } +} From f65610afc804b2eed1c80b9868a6f2c77e2bead4 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 06:55:49 -0700 Subject: [PATCH 13/24] perf(integrations): accelerate envelope hex decoding --- CHANGELOG.md | 5 ++ crates/typesec-integrations/src/did/crypto.rs | 47 +++++++++++++++---- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a9c53e..69a0f6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ by release version, then by the date the logical change landed. ## Unreleased +- DID hexadecimal decoding now uses one validated lookup per nibble while + retaining mixed-case input compatibility and canonical lowercase output. A + 64 KiB X25519/ChaCha20-Poly1305 envelope decrypt improves from about 684 to + 297 microseconds, reducing complete TypeDID open time from about 1.023 + milliseconds to 632 microseconds. - In-memory DID replay protection now prunes claims through an expiry-ordered queue instead of scanning every active claim while holding its mutex. At 10,000 active claims, replay hits improve from about 14.1 microseconds to diff --git a/crates/typesec-integrations/src/did/crypto.rs b/crates/typesec-integrations/src/did/crypto.rs index e1de088..cb8b046 100644 --- a/crates/typesec-integrations/src/did/crypto.rs +++ b/crates/typesec-integrations/src/did/crypto.rs @@ -58,18 +58,49 @@ pub(super) fn hex_decode(value: &str) -> Result, DidError> { } let mut out = Vec::with_capacity(value.len() / 2); for chunk in value.as_bytes().chunks_exact(2) { - let high = hex_nibble(chunk[0])?; - let low = hex_nibble(chunk[1])?; + let high = HEX_VALUES[chunk[0] as usize]; + let low = HEX_VALUES[chunk[1] as usize]; + if high | low > 0x0f { + return Err(DidError::InvalidHex); + } out.push((high << 4) | low); } Ok(out) } -fn hex_nibble(byte: u8) -> Result { - match byte { - b'0'..=b'9' => Ok(byte - b'0'), - b'a'..=b'f' => Ok(byte - b'a' + 10), - b'A'..=b'F' => Ok(byte - b'A' + 10), - _ => Err(DidError::InvalidHex), +const HEX_VALUES: [u8; 256] = { + let mut values = [u8::MAX; 256]; + let mut digit = 0; + while digit < 10 { + values[b'0' as usize + digit] = digit as u8; + digit += 1; + } + let mut letter = 0; + while letter < 6 { + values[b'a' as usize + letter] = letter as u8 + 10; + values[b'A' as usize + letter] = letter as u8 + 10; + letter += 1; + } + values +}; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn hexadecimal_round_trip_uses_canonical_lowercase() { + let bytes = [0x00, 0x01, 0x09, 0x0a, 0x10, 0xab, 0xcd, 0xef, 0xff]; + let encoded = hex_encode(&bytes); + assert_eq!(encoded, "0001090a10abcdefff"); + assert_eq!(hex_decode(&encoded).unwrap(), bytes); + assert_eq!(hex_decode("0001090A10AbCdEfFf").unwrap(), bytes); + } + + #[test] + fn hexadecimal_decode_rejects_odd_and_invalid_inputs() { + assert!(matches!(hex_decode("0"), Err(DidError::InvalidHex))); + assert!(matches!(hex_decode("0g"), Err(DidError::InvalidHex))); + assert!(matches!(hex_decode("💩"), Err(DidError::InvalidHex))); } } From ff76a1e80870bb585159454f4c2d5471fa011975 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 07:03:56 -0700 Subject: [PATCH 14/24] perf(integrations): stream signed envelope references --- CHANGELOG.md | 7 + crates/typesec-integrations/src/did/auth.rs | 125 +++++++++++++----- crates/typesec-integrations/src/did/crypto.rs | 6 - .../typesec-integrations/src/did/envelope.rs | 22 ++- .../typesec-integrations/src/did/gateway.rs | 9 +- 5 files changed, 120 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69a0f6f..bcfd8c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ by release version, then by the date the logical change landed. ## Unreleased +- TypeDID canonical transcripts now share one sink-agnostic encoder for byte + vectors, exact length counting, and direct SHA-256 hashing. Envelope seal and + open reuse the authenticated header, while signed references no longer build + and copy nested ciphertext-sized vectors. A 64 KiB reference improves from + about 138.5 to 72.4 microseconds; after accelerated hex decoding, complete + open time improves further from about 632 to 576 microseconds (1.023 + milliseconds before both changes). - DID hexadecimal decoding now uses one validated lookup per nibble while retaining mixed-case input compatibility and canonical lowercase output. A 64 KiB X25519/ChaCha20-Poly1305 envelope decrypt improves from about 684 to diff --git a/crates/typesec-integrations/src/did/auth.rs b/crates/typesec-integrations/src/did/auth.rs index 0fe7824..4feee3f 100644 --- a/crates/typesec-integrations/src/did/auth.rs +++ b/crates/typesec-integrations/src/did/auth.rs @@ -2,6 +2,7 @@ use super::envelope::DidEnvelope; use super::typedid::TypeDidMode; +use sha2::Digest as _; /// Wire identifier for the only accepted envelope authentication protocol. pub const DID_ENVELOPE_AUTH_V2: &str = "typesec.did-envelope-auth.v2"; @@ -10,30 +11,48 @@ const HEADER_DOMAIN: &str = "typesec.did-envelope-auth.v2/header"; const SIGNATURE_DOMAIN: &str = "typesec.did-envelope-auth.v2/signature"; const REFERENCE_DOMAIN: &str = "typesec.did-envelope-auth.v2/reference"; +#[cfg(test)] #[derive(Clone, Copy)] pub(super) enum TranscriptKind { Header, Signature, - Reference, } /// Produce one length-framed transcript family for AEAD, signatures, and /// stable references. Signature and reference transcripts nest the exact bytes /// from the preceding stage so the authenticated header has one definition. +#[cfg(test)] pub(super) fn canonical_transcript(envelope: &DidEnvelope, kind: TranscriptKind) -> Vec { - let header = authenticated_header(envelope); + let mut transcript = Vec::new(); match kind { - TranscriptKind::Header => header, - TranscriptKind::Signature => signature_transcript(envelope, &header), - TranscriptKind::Reference => { - let signature = signature_transcript(envelope, &header); - reference_transcript(envelope, &signature) - } + TranscriptKind::Header => write_authenticated_header(envelope, &mut transcript), + TranscriptKind::Signature => write_signature_transcript(envelope, &mut transcript), } + transcript +} + +pub(super) fn authenticated_header(envelope: &DidEnvelope) -> Vec { + let mut header = Vec::new(); + write_authenticated_header(envelope, &mut header); + header +} + +pub(super) fn signature_transcript_from_header(envelope: &DidEnvelope, header: &[u8]) -> Vec { + let mut signature = Vec::new(); + let mut transcript = Transcript::new(&mut signature, SIGNATURE_DOMAIN); + transcript.bytes("authenticatedHeader", header); + transcript.string("ciphertext", &envelope.ciphertext); + signature } -fn authenticated_header(envelope: &DidEnvelope) -> Vec { - let mut transcript = Transcript::new(HEADER_DOMAIN); +pub(super) fn reference_sha256(envelope: &DidEnvelope) -> [u8; 32] { + let mut hasher = sha2::Sha256::new(); + write_reference_transcript(envelope, &mut hasher); + hasher.finalize().into() +} + +fn write_authenticated_header(envelope: &DidEnvelope, sink: &mut S) { + let mut transcript = Transcript::new(sink, HEADER_DOMAIN); transcript.string("authVersion", &envelope.auth_version); transcript.string("id", &envelope.id); transcript.string("messageType", &envelope.message_type); @@ -56,30 +75,39 @@ fn authenticated_header(envelope: &DidEnvelope) -> Vec { transcript.optional_conversation(envelope.typedid.as_ref()); transcript.string("kid", &envelope.kid); transcript.string("nonce", &envelope.nonce); - transcript.finish() } -fn signature_transcript(envelope: &DidEnvelope, header: &[u8]) -> Vec { - let mut transcript = Transcript::new(SIGNATURE_DOMAIN); - transcript.bytes("authenticatedHeader", header); +fn write_signature_transcript(envelope: &DidEnvelope, sink: &mut S) { + let header_bytes = encoded_len(|counter| write_authenticated_header(envelope, counter)); + let mut transcript = Transcript::new(sink, SIGNATURE_DOMAIN); + transcript.nested("authenticatedHeader", header_bytes, |sink| { + write_authenticated_header(envelope, sink); + }); transcript.string("ciphertext", &envelope.ciphertext); - transcript.finish() } -fn reference_transcript(envelope: &DidEnvelope, signature: &[u8]) -> Vec { - let mut transcript = Transcript::new(REFERENCE_DOMAIN); - transcript.bytes("signedEnvelope", signature); +fn write_reference_transcript(envelope: &DidEnvelope, sink: &mut S) { + let signature_bytes = encoded_len(|counter| write_signature_transcript(envelope, counter)); + let mut transcript = Transcript::new(sink, REFERENCE_DOMAIN); + transcript.nested("signedEnvelope", signature_bytes, |sink| { + write_signature_transcript(envelope, sink); + }); transcript.string("signature", &envelope.signature); - transcript.finish() } -struct Transcript { - bytes: Vec, +fn encoded_len(write: impl FnOnce(&mut ByteCount)) -> usize { + let mut counter = ByteCount::default(); + write(&mut counter); + counter.0 +} + +struct Transcript<'a, S> { + sink: &'a mut S, } -impl Transcript { - fn new(domain: &str) -> Self { - let mut transcript = Self { bytes: Vec::new() }; +impl<'a, S: TranscriptSink> Transcript<'a, S> { + fn new(sink: &'a mut S, domain: &str) -> Self { + let mut transcript = Self { sink }; transcript.string("domain", domain); transcript } @@ -89,8 +117,14 @@ impl Transcript { } fn bytes(&mut self, name: &str, value: &[u8]) { - frame(&mut self.bytes, name.as_bytes()); - frame(&mut self.bytes, value); + frame(self.sink, name.as_bytes()); + frame(self.sink, value); + } + + fn nested(&mut self, name: &str, value_len: usize, write: impl FnOnce(&mut S)) { + frame(self.sink, name.as_bytes()); + write_len(self.sink, value_len); + write(self.sink); } fn u64(&mut self, name: &str, value: u64) { @@ -126,10 +160,6 @@ impl Transcript { } } } - - fn finish(self) -> Vec { - self.bytes - } } fn mode_name(mode: TypeDidMode) -> &'static str { @@ -139,7 +169,36 @@ fn mode_name(mode: TypeDidMode) -> &'static str { } } -fn frame(output: &mut Vec, value: &[u8]) { - output.extend_from_slice(&(value.len() as u64).to_be_bytes()); - output.extend_from_slice(value); +trait TranscriptSink { + fn write(&mut self, bytes: &[u8]); +} + +impl TranscriptSink for Vec { + fn write(&mut self, bytes: &[u8]) { + self.extend_from_slice(bytes); + } +} + +impl TranscriptSink for sha2::Sha256 { + fn write(&mut self, bytes: &[u8]) { + self.update(bytes); + } +} + +#[derive(Default)] +struct ByteCount(usize); + +impl TranscriptSink for ByteCount { + fn write(&mut self, bytes: &[u8]) { + self.0 += bytes.len(); + } +} + +fn frame(output: &mut impl TranscriptSink, value: &[u8]) { + write_len(output, value.len()); + output.write(value); +} + +fn write_len(output: &mut impl TranscriptSink, value_len: usize) { + output.write(&(value_len as u64).to_be_bytes()); } diff --git a/crates/typesec-integrations/src/did/crypto.rs b/crates/typesec-integrations/src/did/crypto.rs index cb8b046..1fe226c 100644 --- a/crates/typesec-integrations/src/did/crypto.rs +++ b/crates/typesec-integrations/src/did/crypto.rs @@ -11,12 +11,6 @@ pub(super) fn unix_time() -> u64 { .unwrap_or_default() } -/// SHA-256 digest of canonical protocol bytes. -pub(super) fn sha256(data: &[u8]) -> [u8; 32] { - use sha2::Digest; - sha2::Sha256::digest(data).into() -} - /// Domain-separated SHA-256: `SHA-256(domain || 0x00 || data)`. pub(super) fn sha256_tagged(domain: &[u8], data: &[u8]) -> [u8; 32] { use sha2::Digest; diff --git a/crates/typesec-integrations/src/did/envelope.rs b/crates/typesec-integrations/src/did/envelope.rs index 6264df2..49839ad 100644 --- a/crates/typesec-integrations/src/did/envelope.rs +++ b/crates/typesec-integrations/src/did/envelope.rs @@ -3,8 +3,10 @@ use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -use super::auth::{DID_ENVELOPE_AUTH_V2, TranscriptKind, canonical_transcript}; -use super::crypto::{hex_encode, random_nonce, sha256, unix_time}; +use super::auth::{ + DID_ENVELOPE_AUTH_V2, authenticated_header, reference_sha256, signature_transcript_from_header, +}; +use super::crypto::{hex_encode, random_nonce, unix_time}; use super::document::DidResolver; use super::error::DidError; use super::gateway::{VerifiedDidPrompt, VerifiedTypeDidMessage}; @@ -203,7 +205,8 @@ impl DidEnvelope { let aad = envelope.associated_data(); envelope.ciphertext = key_store.encrypt_for(&envelope.from, &recipient_public, plaintext, &nonce, &aad)?; - envelope.signature = key_store.sign(&envelope.from, &envelope.signing_input())?; + envelope.signature = + key_store.sign(&envelope.from, &envelope.signing_input_from_header(&aad))?; Ok(envelope) } @@ -322,10 +325,9 @@ impl DidEnvelope { /// Stable reference to this signed envelope for reply binding. pub fn reference(&self) -> DidMessageReference { - let transcript = canonical_transcript(self, TranscriptKind::Reference); DidMessageReference { id: self.id.clone(), - digest: format!("sha256:{}", hex_encode(&sha256(&transcript))), + digest: format!("sha256:{}", hex_encode(&reference_sha256(self))), } } @@ -334,15 +336,21 @@ impl DidEnvelope { /// The length-framed v2 header includes routing, timing, policy-visible /// body and claims, TypeDID conversation, reply binding, key id, and nonce. pub(super) fn associated_data(&self) -> Vec { - canonical_transcript(self, TranscriptKind::Header) + authenticated_header(self) } /// Canonical bytes the sender signs and the recipient verifies. /// /// The signature transcript nests the exact AEAD header and appends the /// ciphertext as one additional length-framed field. + #[cfg(test)] pub(super) fn signing_input(&self) -> Vec { - canonical_transcript(self, TranscriptKind::Signature) + let header = self.associated_data(); + self.signing_input_from_header(&header) + } + + pub(super) fn signing_input_from_header(&self, header: &[u8]) -> Vec { + signature_transcript_from_header(self, header) } pub(super) fn effective_expires_at(&self) -> u64 { diff --git a/crates/typesec-integrations/src/did/gateway.rs b/crates/typesec-integrations/src/did/gateway.rs index 494e1a1..b4b078d 100644 --- a/crates/typesec-integrations/src/did/gateway.rs +++ b/crates/typesec-integrations/src/did/gateway.rs @@ -339,8 +339,12 @@ impl DidMessageGateway { let sender_document = self.resolver.resolve(&envelope.from)?; let sender_key = sender_document.authentication_key(&envelope.kid)?; - self.key_store - .verify(sender_key, &envelope.signing_input(), &envelope.signature)?; + let aad = envelope.associated_data(); + self.key_store.verify( + sender_key, + &envelope.signing_input_from_header(&aad), + &envelope.signature, + )?; // Semantic routing is meaningful only after `message_type` has been // authenticated. Reject cross-protocol envelopes before key agreement, // decryption, or replay-store consumption. @@ -353,7 +357,6 @@ impl DidMessageGateway { // sender document. let sender_agreement_keys = sender_document.key_agreement_keys()?; let nonce = hex_decode(&envelope.nonce)?; - let aad = envelope.associated_data(); let mut plaintext = None; for sender_agreement_key in sender_agreement_keys { match self.key_store.decrypt_for( From a271dbdfed033a384b623f2c653b7819a12d2bdf Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 07:07:57 -0700 Subject: [PATCH 15/24] perf(integrations): reuse sealed receipt validation --- CHANGELOG.md | 6 +++++ crates/typesec-integrations/src/receipt.rs | 31 +++++++++++++--------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bcfd8c7..ffb01a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ by release version, then by the date the logical change landed. ## Unreleased +- Receipt issuance now writes both base64url segments into one exactly sized + token allocation, verification decodes fixed-size signatures on the stack, + and sealed cognition receipt values avoid redundant semantic rescans after + their validating constructor or deserializer. With 256 affected IDs, + cognition receipt issue improves from about 49.7 to 43.4 microseconds and + verification from 77.4 to 72.3 microseconds, with byte-identical tokens. - TypeDID canonical transcripts now share one sink-agnostic encoder for byte vectors, exact length counting, and direct SHA-256 hashing. Envelope seal and open reuse the authenticated header, while signed references no longer build diff --git a/crates/typesec-integrations/src/receipt.rs b/crates/typesec-integrations/src/receipt.rs index 283fb81..be02edc 100644 --- a/crates/typesec-integrations/src/receipt.rs +++ b/crates/typesec-integrations/src/receipt.rs @@ -140,7 +140,6 @@ impl ReceiptIssuer { receipt: &CognitionCommitReceipt, now: DateTime, ) -> Result { - receipt.validate()?; validate_window(receipt.issued_at(), receipt.expires_at(), now)?; Ok(self.issue_claims(receipt)) } @@ -149,11 +148,15 @@ impl ReceiptIssuer { let claims = serde_json::to_vec(receipt) .expect("receipt serialization cannot fail: all fields are JSON-safe"); let signature = self.key.sign(&claims); - format!( - "{}.{}", - B64.encode(&claims), - B64.encode(signature.to_bytes()) - ) + let claims_len = base64::encoded_len(claims.len(), false) + .expect("serialized receipt length must fit in memory"); + let signature_len = base64::encoded_len(Signature::BYTE_SIZE, false) + .expect("fixed-size signature length cannot overflow"); + let mut token = String::with_capacity(claims_len + 1 + signature_len); + B64.encode_string(&claims, &mut token); + token.push('.'); + B64.encode_string(signature.to_bytes(), &mut token); + token } } @@ -185,7 +188,6 @@ impl ReceiptVerifier { now: DateTime, ) -> Result { let receipt: CognitionCommitReceipt = self.verify_claims(token)?; - receipt.validate()?; validate_window(receipt.issued_at(), receipt.expires_at(), now)?; Ok(receipt) } @@ -197,11 +199,16 @@ impl ReceiptVerifier { let claims = B64 .decode(claims_b64) .map_err(|err| ReceiptError::Malformed(format!("claims are not base64url: {err}")))?; - let signature_bytes: [u8; 64] = B64 - .decode(signature_b64) - .map_err(|err| ReceiptError::Malformed(format!("signature is not base64url: {err}")))? - .try_into() - .map_err(|_| ReceiptError::Malformed("signature is not 64 bytes".into()))?; + if signature_b64.len() != base64::encoded_len(Signature::BYTE_SIZE, false).unwrap() { + return Err(ReceiptError::Malformed("signature is not 64 bytes".into())); + } + let mut signature_bytes = [0_u8; Signature::BYTE_SIZE]; + let decoded_signature_len = B64 + .decode_slice(signature_b64, &mut signature_bytes) + .map_err(|err| ReceiptError::Malformed(format!("signature is not base64url: {err}")))?; + if decoded_signature_len != signature_bytes.len() { + return Err(ReceiptError::Malformed("signature is not 64 bytes".into())); + } self.key .verify(&claims, &Signature::from_bytes(&signature_bytes)) .map_err(|_| ReceiptError::BadSignature)?; From 6fbf415647ad8153cf467882bca96f2163d6e0f9 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sat, 8 Aug 2026 21:28:30 -0700 Subject: [PATCH 16/24] ci: pin reviewed Grust dependency --- .github/workflows/ci.yml | 6 ++++-- CHANGELOG.md | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d08c96..5349083 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,8 +30,10 @@ jobs: # bump deliberately when the typesec/Grust contract changes. If # querygraph/grust is private, also pass a token with read access: # token: ${{ secrets.GRUST_CHECKOUT_TOKEN }} - # typesec 0.12 (Torcello) tracks Grust 0.12 (Lobster), on main. - ref: main + # TypeSec 0.13.1 tracks the reviewed Grust 0.12.1 release candidate. + # Pin the commit so a moving or older `main` cannot silently change + # this cross-repository build contract. + ref: a178c30de9b5c194fae68c9bed37c6665e1096ad - name: Show toolchain (pinned by rust-toolchain.toml) working-directory: typesec diff --git a/CHANGELOG.md b/CHANGELOG.md index ffb01a6..f3022eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ by release version, then by the date the logical change landed. ## Unreleased +- Pin the CI sibling checkout to the reviewed Grust 0.12.1 revision, matching + TypeSec's path-dependency contract instead of resolving against the older + 0.12.0 package versions on Grust's moving `main` branch. - Receipt issuance now writes both base64url segments into one exactly sized token allocation, verification decodes fixed-size signatures on the stack, and sealed cognition receipt values avoid redundant semantic rescans after From ddd70cf91876a7f6de9d1ef59aad01a11af47240 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sun, 9 Aug 2026 03:07:59 -0700 Subject: [PATCH 17/24] docs(grust): align current adapter versions --- docs/book/typesec.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/book/typesec.md b/docs/book/typesec.md index f427011..17ed079 100644 --- a/docs/book/typesec.md +++ b/docs/book/typesec.md @@ -342,7 +342,7 @@ The root workspace uses Rust 2024. Common dependencies are declared in `x25519-dalek`, `chacha20poly1305`, `sha2`, `getrandom`). Grust is published on crates.io (`grust-graph`, `grust-cypher`, and `grust-sail` -are at `0.12.0`, codename Lobster). The workspace pins each dependency with both a +are at `0.12.1`). The workspace pins each dependency with both a `version` and a local `path`, so a checkout that has a sibling `../grust` builds against that working copy (the `path` wins locally), while the `version` resolves against crates.io when Typesec is published or built without the @@ -350,15 +350,22 @@ sibling checkout: ```toml # workspace Cargo.toml -grust-graph = { version = "0.12.0", path = "../grust/crates/grust", features = ["typed-zod-rs"] } -grust-cypher = { version = "0.12.0", path = "../grust/crates/grust-cypher" } -grust-sail = { version = "0.12.0", path = "../grust/crates/grust-sail" } +grust-graph = { version = "0.12.1", path = "../grust/crates/grust", features = ["typed-zod-rs"] } +grust-cypher = { version = "0.12.1", path = "../grust/crates/grust-cypher" } +grust-sail = { version = "0.12.1", path = "../grust/crates/grust-sail" } ``` To build the Cypher company-graph example purely from crates.io, drop the `path` keys and keep the `version`; to develop Typesec and Grust together, keep the sibling `../grust` checkout. +Typesec intentionally does not maintain a second Sail source revision. It +compiles against the released Grust adapter contract; the composing QueryGraph +or Marciana release owns the exact Sail executable pin and live compatibility +gate. This keeps authorization semantics independent of a moving execution +engine while still exercising the company-graph integration through +`grust-sail`. + The package is named `grust-graph`, while its library is imported as `grust`. The facade re-exports the core graph API, while `grust-sail` exposes the Sail adapter types directly. The `typed-zod-rs` feature lets Typesec route policy YAML From 7fd62a023b1fc771b7b210a0f189e667b03df87a Mon Sep 17 00:00:00 2001 From: Alexy Date: Sun, 9 Aug 2026 03:13:26 -0700 Subject: [PATCH 18/24] docs(grust): refresh company graph adapter version --- docs/company-graph-grust-sail.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/company-graph-grust-sail.md b/docs/company-graph-grust-sail.md index 1c8c3fe..b0ff5bf 100644 --- a/docs/company-graph-grust-sail.md +++ b/docs/company-graph-grust-sail.md @@ -37,7 +37,7 @@ same graph. Rules can then test graph predicates such as: - target employee level is not `Executive`. - a proposed `REPORTS_TO` edge would not create a cycle. -The loader now routes YAML and JSON graph policies through Grust 0.9 typed graph +The loader now routes YAML and JSON graph policies through Grust 0.12.1 typed graph support and Zod schemas before the authorization engine sees a `Graph`. The same company graph schema is used when examples write to Grust typed backends. The schema example also applies Grust Cypher DDL constraints through the portable From 0b606f6d6748ff138849bdba5aded224fc951fba Mon Sep 17 00:00:00 2001 From: Alexy Date: Sun, 9 Aug 2026 04:04:16 -0700 Subject: [PATCH 19/24] fix(example): authorize scoped graph persistence --- CHANGELOG.md | 4 +++ crates/typesec-rbac/src/graph_policy/tests.rs | 28 +++++++++++++++++++ docs/company-graph-grust-sail.md | 5 ++++ policies/graph-corporate-example.yaml | 2 +- 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3022eb..d46d104 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ by release version, then by the date the logical change landed. ## Unreleased +- Correct the company-graph example's aggregate persistence grant to the + least-privilege `company/*/org-graph` shape. Regression tests now prove that + a graph administrator can persist a tenant org graph without gaining an + unrelated `company//payroll` write. - Pin the CI sibling checkout to the reviewed Grust 0.12.1 revision, matching TypeSec's path-dependency contract instead of resolving against the older 0.12.0 package versions on Grust's moving `main` branch. diff --git a/crates/typesec-rbac/src/graph_policy/tests.rs b/crates/typesec-rbac/src/graph_policy/tests.rs index 471258e..4bc0e3a 100644 --- a/crates/typesec-rbac/src/graph_policy/tests.rs +++ b/crates/typesec-rbac/src/graph_policy/tests.rs @@ -71,6 +71,8 @@ graph_policy: no_cycle: true "#; +const COMPANY_YAML: &str = include_str!("../../../../policies/graph-corporate-example.yaml"); + fn engine() -> GraphPolicyEngine { GraphPolicyEngine::from_yaml(YAML).expect("graph policy should load") } @@ -95,6 +97,32 @@ fn role_can_write_non_executive_employee_node() { ); } +#[test] +fn executive_graph_admin_can_persist_a_tenant_org_graph() { + let engine = GraphPolicyEngine::from_yaml(COMPANY_YAML).expect("company policy should load"); + assert_eq!( + engine.check( + &SubjectId::from("agent:executive-chief"), + "write", + &ResourceId::from("company/acme/org-graph"), + ), + PolicyResult::Allow + ); +} + +#[test] +fn executive_graph_admin_does_not_gain_unrelated_company_writes() { + let engine = GraphPolicyEngine::from_yaml(COMPANY_YAML).expect("company policy should load"); + assert!(matches!( + engine.check( + &SubjectId::from("agent:executive-chief"), + "write", + &ResourceId::from("company/acme/payroll"), + ), + PolicyResult::Deny(_) + )); +} + #[test] fn role_cannot_write_executive_employee_node() { assert!(matches!( diff --git a/docs/company-graph-grust-sail.md b/docs/company-graph-grust-sail.md index b0ff5bf..ebebb6f 100644 --- a/docs/company-graph-grust-sail.md +++ b/docs/company-graph-grust-sail.md @@ -56,6 +56,11 @@ checks: - Cypher DDL can install company-graph uniqueness and required-property constraints without bypassing the Typesec policy gate. +The aggregate persistence capability is scoped to `company/*/org-graph`. +The single-segment wildcard selects one tenant, while the literal final segment +prevents the graph-administrator role from acquiring unrelated company writes +such as `company/acme/payroll`. + You can check the graph policy directly: ```sh diff --git a/policies/graph-corporate-example.yaml b/policies/graph-corporate-example.yaml index 26b3e9c..cbc8905 100644 --- a/policies/graph-corporate-example.yaml +++ b/policies/graph-corporate-example.yaml @@ -88,7 +88,7 @@ graph_policy: rules: - subject_has_role: role:executive_graph_admin action: write - resource: company/* + resource: company/*/org-graph - subject_has_role: role:executive_graph_admin action: read_sensitive From a45ecd868b0179542a6ee0e2dbb522602a3919c6 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sun, 9 Aug 2026 04:35:46 -0700 Subject: [PATCH 20/24] docs(sail): record production company graph gate --- CHANGELOG.md | 5 +++++ docs/book/typesec.md | 9 +++++++++ docs/company-graph-grust-sail.md | 9 +++++++++ 3 files changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d46d104..c4d0d0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ by release version, then by the date the logical change landed. least-privilege `company/*/org-graph` shape. Regression tests now prove that a graph administrator can persist a tenant org graph without gaining an unrelated `company//payroll` write. +- Pass the company-graph live gate against QueryGraph's exact optimized + graph-enabled Sail `c5309365` artifact: both expected authorization denials + remain enforced and the permitted typed write persists 5 nodes and 4 edges. + The gate also drove regression coverage for Grust's schema-declared node + identity mapping without introducing a second Typesec-owned Sail pin. - Pin the CI sibling checkout to the reviewed Grust 0.12.1 revision, matching TypeSec's path-dependency contract instead of resolving against the older 0.12.0 package versions on Grust's moving `main` branch. diff --git a/docs/book/typesec.md b/docs/book/typesec.md index 17ed079..7a87fcf 100644 --- a/docs/book/typesec.md +++ b/docs/book/typesec.md @@ -2012,6 +2012,15 @@ graph and to write the graph through the Sail adapter when a Sail SparkConnect server is available at `127.0.0.1:50051`. If Sail is not running, the example still demonstrates the Typesec decisions and prints the graph. +In the 2026-08-09 cross-stack release gate, QueryGraph supplied its exact +optimized graph-enabled Sail `c5309365` executable. The live path preserved the +HR executive-node and employee sensitive-network denials, authorized only the +tenant org-graph aggregate resource, and wrote all 5 nodes and 4 edges. That +gate also exposed and verified the Grust fix that maps a schema-declared string +`id` onto the one structural typed-table column instead of creating a duplicate +unqualified field. Typesec records this evidence without maintaining a second +Sail source pin. + The import shape is: ```rust diff --git a/docs/company-graph-grust-sail.md b/docs/company-graph-grust-sail.md index ebebb6f..e398d01 100644 --- a/docs/company-graph-grust-sail.md +++ b/docs/company-graph-grust-sail.md @@ -78,6 +78,15 @@ company graph schema and writes the graph through `SailGraphStore::put_typed_graph`; otherwise it still validates the graph against that schema and demonstrates the security checks. +The 2026-08-09 cross-stack release gate supplied QueryGraph's exact optimized +graph-enabled Sail `c5309365` executable. The live example preserved the HR +executive-node and employee sensitive-network denials, granted only +`company/acme/org-graph`, and wrote all 5 employee nodes and 4 `REPORTS_TO` +edges. This exercise also caught and now covers a Grust adapter defect: an +explicit string `id` in `GraphSchema` must reuse the structural typed-table +column, not generate a second unqualified `id`. Typesec records the result but +does not duplicate the composing QueryGraph/Marciana Sail source pin. + The Python examples share `company_graph_core.py`, which owns the in-memory graph, employee fixture data, and `TypesecGate`. The gate tries the Rust-backed `typesec_native` module first and falls back to the workspace CLI, so examples From d158b6446e53b33e88a0a353a5ac06bcf0ee7c22 Mon Sep 17 00:00:00 2001 From: Alexy Date: Sun, 9 Aug 2026 04:37:40 -0700 Subject: [PATCH 21/24] docs(book): rebuild Typesec release artifacts --- docs/book/dist/VERSION.md | 24 ++++---- .../assets/19461a35b786-diagram-2.png | Bin 0 -> 119317 bytes .../assets/2c67e7d95538-diagram-1.png | Bin 0 -> 59474 bytes .../assets/3d747fe2144a-diagram-4.png | Bin 53359 -> 0 bytes .../assets/6b0bc060003a-diagram-6.png | Bin 0 -> 16722 bytes .../assets/6dc72828200f-diagram-5.png | Bin 89288 -> 0 bytes .../assets/7a086c098325-diagram-2.png | Bin 121395 -> 0 bytes .../assets/7f82fe1bb0ac-diagram-6.png | Bin 17032 -> 0 bytes .../assets/9d1167336141-diagram-4.png | Bin 0 -> 55158 bytes .../assets/a7f9654f1bae-diagram-3.png | Bin 0 -> 49326 bytes .../assets/c8edc2ccf59e-diagram-3.png | Bin 51565 -> 0 bytes .../assets/d2676d91b2eb-diagram-1.png | Bin 62838 -> 0 bytes .../assets/d5ab1f8c38f7-diagram-5.png | Bin 0 -> 89519 bytes .../dist/typesec-chapters/chapter-001.html | 2 +- .../dist/typesec-chapters/chapter-002.html | 2 +- .../dist/typesec-chapters/chapter-003.html | 2 +- .../dist/typesec-chapters/chapter-004.html | 2 +- .../dist/typesec-chapters/chapter-005.html | 17 ++---- .../dist/typesec-chapters/chapter-006.html | 27 +++++---- .../dist/typesec-chapters/chapter-007.html | 2 +- .../dist/typesec-chapters/chapter-008.html | 2 +- .../dist/typesec-chapters/chapter-009.html | 2 +- .../dist/typesec-chapters/chapter-010.html | 5 +- .../dist/typesec-chapters/chapter-011.html | 2 +- .../dist/typesec-chapters/chapter-012.html | 2 +- .../dist/typesec-chapters/chapter-013.html | 2 +- .../dist/typesec-chapters/chapter-014.html | 2 +- .../dist/typesec-chapters/chapter-015.html | 2 +- .../dist/typesec-chapters/chapter-016.html | 11 +++- .../dist/typesec-chapters/chapter-017.html | 2 +- .../dist/typesec-chapters/chapter-018.html | 2 +- .../dist/typesec-chapters/chapter-019.html | 2 +- .../dist/typesec-chapters/chapter-020.html | 2 +- .../dist/typesec-chapters/chapter-021.html | 2 +- docs/book/dist/typesec-chapters/index.html | 4 +- docs/book/dist/typesec.epub | Bin 2492418 -> 2486527 bytes docs/book/dist/typesec.html | 52 +++++++++++------- docs/book/dist/typesec.mobi | Bin 830441 -> 828231 bytes docs/book/dist/typesec.pdf | Bin 2928476 -> 2943046 bytes 39 files changed, 98 insertions(+), 76 deletions(-) create mode 100644 docs/book/dist/typesec-chapters/assets/19461a35b786-diagram-2.png create mode 100644 docs/book/dist/typesec-chapters/assets/2c67e7d95538-diagram-1.png delete mode 100644 docs/book/dist/typesec-chapters/assets/3d747fe2144a-diagram-4.png create mode 100644 docs/book/dist/typesec-chapters/assets/6b0bc060003a-diagram-6.png delete mode 100644 docs/book/dist/typesec-chapters/assets/6dc72828200f-diagram-5.png delete mode 100644 docs/book/dist/typesec-chapters/assets/7a086c098325-diagram-2.png delete mode 100644 docs/book/dist/typesec-chapters/assets/7f82fe1bb0ac-diagram-6.png create mode 100644 docs/book/dist/typesec-chapters/assets/9d1167336141-diagram-4.png create mode 100644 docs/book/dist/typesec-chapters/assets/a7f9654f1bae-diagram-3.png delete mode 100644 docs/book/dist/typesec-chapters/assets/c8edc2ccf59e-diagram-3.png delete mode 100644 docs/book/dist/typesec-chapters/assets/d2676d91b2eb-diagram-1.png create mode 100644 docs/book/dist/typesec-chapters/assets/d5ab1f8c38f7-diagram-5.png diff --git a/docs/book/dist/VERSION.md b/docs/book/dist/VERSION.md index 18d61eb..18ba5e5 100644 --- a/docs/book/dist/VERSION.md +++ b/docs/book/dist/VERSION.md @@ -2,23 +2,23 @@ title: Typesec subtitle: Type-Level Security for Agentic AI title_stem: typesec edition: full -version: 0.13.0 -version_stamp: 0.13.0-1926f18c -source_commit: 1926f18c -built_at: 2026-08-06T06:29:46Z -toolchain_lock: ../firstpair/publishing/toolchain.lock.json +version: 0.13.1 +version_stamp: 0.13.1-a45ecd86 +source_commit: a45ecd86 +built_at: 2026-08-09T11:35:57Z +toolchain_lock: ../../src/firstpair/publishing/toolchain.lock.json primary_format: typst -kindle_name: typesec (0.13.0) -kindle_link: typesec (0.13.0).epub +kindle_name: typesec (0.13.1) +kindle_link: typesec (0.13.1).epub pdf_file: typesec.pdf epub_file: typesec.epub html_file: typesec.html html_chapters_dir: typesec-chapters html_title: Typesec -pdf_link: typesec (0.13.0-1926f18c).pdf -epub_link: typesec (0.13.0-1926f18c).epub -html_link: typesec (0.13.0-1926f18c).html -html_chapters_link: typesec (0.13.0-1926f18c)-chapters +pdf_link: typesec (0.13.1-a45ecd86).pdf +epub_link: typesec (0.13.1-a45ecd86).epub +html_link: typesec (0.13.1-a45ecd86).html +html_chapters_link: typesec (0.13.1-a45ecd86)-chapters mobi_file: typesec.mobi pdf_file_typst: typesec.pdf -pdf_link_typst: typesec (0.13.0-1926f18c).pdf +pdf_link_typst: typesec (0.13.1-a45ecd86).pdf diff --git a/docs/book/dist/typesec-chapters/assets/19461a35b786-diagram-2.png b/docs/book/dist/typesec-chapters/assets/19461a35b786-diagram-2.png new file mode 100644 index 0000000000000000000000000000000000000000..5e1780a5cffe184b8d1050b28a8dcd5aa4ba390e GIT binary patch literal 119317 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

!SIYEqp%&pyZlYF==dR`5=)g_!!7Z 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 a{2}vfv+QXPT`B(0ABu7pWizF(J^o+h-0UX+ literal 0 HcmV?d00001 diff --git a/docs/book/dist/typesec-chapters/assets/2c67e7d95538-diagram-1.png b/docs/book/dist/typesec-chapters/assets/2c67e7d95538-diagram-1.png new file mode 100644 index 0000000000000000000000000000000000000000..46f1ad1a997f8f8180ad75bdc6d81501620897a2 GIT binary patch literal 59474 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 literal 0 HcmV?d00001 diff --git a/docs/book/dist/typesec-chapters/assets/3d747fe2144a-diagram-4.png b/docs/book/dist/typesec-chapters/assets/3d747fe2144a-diagram-4.png deleted file mode 100644 index 1c3fed1c74d66cce64339c42964feefd05276cbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53359 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 J2UH4ZU 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 diff --git a/docs/book/dist/typesec-chapters/assets/6b0bc060003a-diagram-6.png b/docs/book/dist/typesec-chapters/assets/6b0bc060003a-diagram-6.png new file mode 100644 index 0000000000000000000000000000000000000000..ef84d7c6faf00314df730510a9bd61f91c4c0201 GIT binary patch literal 16722 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 Sx&ps}l9g1FC>JyO^nU=;;wdoz literal 0 HcmV?d00001 diff --git a/docs/book/dist/typesec-chapters/assets/6dc72828200f-diagram-5.png b/docs/book/dist/typesec-chapters/assets/6dc72828200f-diagram-5.png deleted file mode 100644 index 1be9c63bab621974b9e19cfd3f7213f3f613534d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89288 zcmeFZXH=6>*DVSvU;|V{6hu^{D@A&Ziiq?M0s_)|4Lv|mR0IW7nv{Uli1ZE#MWy#n zfCM5SorF$k31{=Z-x=fnxaa=5Kaa!Vcm^TK^X$F$TyxDeml4{U%Jk=1&r?xR(W^Xv zs!K&hdz*^tbl}-j;3prnudPy1U7}KX`dHsTb#?Mws>a-G+eTZ%8q9ZGwMxG;;mNu2 z>K`BYIt?oX?!1e8n|X;ZuB=NCcIQdL>S2RWSm|*iQEver;%7(1CCRpS@6}np`4PY#$K_inwjZCCoQ;ulKWf#P8#~ubydDje38TR41MZRTDOpE4n%KB3N>;XaJtC(d5-5|2-t3G7lVkmZDvt7bzFxzgpPtC^_~=v;sA1(+nQ(T|kc;jATkIo@f``Bl8H&eGs) z57e$J{SWw#qPuyUiR!Y>ds7BbEqUz+VbmV7iy?~37gf^zUwhrZWcrUknSU+V(T)+1 zcH3C`8qa(Gj-lzpCI7Gg&gEBjBktWG$atc&d9@$9CcLz#d<&`j6`VI{msyL`2)cb4 zN-_63D0;)ElIVfWQBACI7{9oZh!CN23x^_$i2DmqB07^UhK@a@$$r9^jsHdBw5nEP zDRw8XyxdS0jTM}(5;%H=x|+vCF5gUjO_#3HoH|PzB)tt|rHaYahifT^*iU$-(**e(>F}Q~Y~c{M#jt?G?=IxV>|VlwhZ6 z>8szVet3e7)obWNZyni}j$G}EwPVuoT^+l2b@=H(3iTy;Jnt7-i-wBJ6iGK6FOyzH zL3a|9O;>`HR+_$v_h>=HPa}9XbU~skQHWmNb0}9_OrzYcGF60KrtW*SeP3Gh)~;A! zrFlL7B&xmver(QkgTMOIjjh6|eCew~Y587rx-{pr8yC`CIG+Ut%ylw{9Xlw~U++I$ zNQVoHIIK-gwnWbL!?D%wB437)T9SxclPDh%5n^HWgpi3?AJqp2)P#M@~b&vJhv&Ta=+_{U-@-g2G@)Kfiku?fUnDOw& zt^KWqNg)J;qhJK>zmX|Azd6@MJh#34m8&s$XT&~7b#7#2D*xzGT9$H*+@T9X6JfGa zpByGi87s}|Jln9B855B$YOe`DCa+^G;N#7*Yjs1VM#X;6xlU)R{?7O=@B7>MGTRFp z_oCQg<$sDbX`#-0d*WZY)T(Ide`=&i{H8kl4Korl+uFF(v{T*}D1YRk6HKe|>#FdQ zMf_#3R4K}YvyjvGfGtDrG}ROdvwXwiphJR@;`?nlq0)~&bkE^m zy9I9gi^7^JR7}{a*`H+75*aTnQUpJC-&|-s{QH}XqWdrH)S)dW8^j0Y@W7_zm(D2wsH)hjZX|8V-qngc^?~f=ThJ ziGt+!^eeQCl&2PA^lTE6U$WJm{{Cu6PKmIHTf4}iQ1ko?j3XdBGvcv9{;2=K5^d*Q z=iwjrck^JR5ShLm8hbZ-j>c!(DH-l~Mj3Da46By5A!Oexsx#_FhieTf{&Su2oXQM6 z$>Kiq-F&TjI;GkfnLf*652+o-H|Jcj5-dXID2D+nZj@tX&NNqV-)?aU>-2b)T@%TFLi3kB8@;y`q5_I~=?AC)c|IA!yl`bhXSR}Z?|ub$wl0=8P21ro+BO_e8WYhKlwjDx$}wsx(s(a!3)D0E&O6N!-VdE(c* zR$u*A^(9eI$H(Y+Fy|7%ys+;L4YVTMXPDopDECR6c|B=rX0FR<)NOw`zi*H4BJOo> zs@|iABuJTx@-Nh`!jOG511ct+6-U?!en@_gFPqEKkq^6}mWaC9n!L z3QqG^5DPZ#p8@P=qUN7ox3up{2wwlY7J03HoWIr?qlwbzR{7ezS7_65c(}th_+ucJ zl{m7(UVLEehO&_Ncx6HF01IbepRJ608gV6Fko+BEs+lGy;y!gTIOC>5kg$C(j^_N; zK_6LzpZdLL4v0g{=BH6sSa;q$qvE{t*L%ej8g5s(`w?*o_f!U}TrGTr{CZO@0D@&* zsDx!F_)Px^AOsxx2DkBv;7~rXe{S~}&LY+>Kp2Z+U{4Mr0ldY|JZJZ_&wldD3|+O* z{-r!{XX4=CMcF?|Lc$xGk5bHSMP_ITIORTBqTfb_c;FVeoF|hUf$5I9CBNCm@lpJE z67Bb|%dc8BFrME)Bk5tzoHD(=qz52rxKiy@a_VBb|;EMwDFlqr4usLac}+i#GQ@9Tg)D&!#{M4j2y|4=8YkRqPj+} z$aYgTo@VbaCh5}-w2hLGT1GqPm|7<+%`CkUo{g+mu9W$296d0VaGN}cv3pVH&u50% z=E~t1MBTUPjN|ftTX=YvNAuD%!T|8kur<*Gxw(uErv#F!<27+Cc|C zR>H9|;{4EgbU65McdTREz`5}Yr#KW+JobV9?6*tRQ8%FFh6|iA`ol4D|`FQ!D(EWIIv``IX)@XLTNrgjENC5T=F@d4dX#^7#aP5C@!4+h>ozoju@lI(LU**}>KKfg7s(!3Tay8sR2NQ#h z;1u~m8dV<0oVVlexDV(~9_P_&`EjrE9nH4r!a5nv&aYf6-ydh;#Cye<2$%fUjC{*F zVp$eVN5<1*qEn#ECCPewcjs7d)1!ip1eI!ywYF) zkgtEB@_aQ#d2lmVYob)|Ue6%Mll1lKZ88D)q)!fC{b*8wB{ zY<9n+2;GcIe3umUzqNpFKJT@Ooh+e-#jN!B7+6S1cxTeOqrr zLb@q-Bb|#2HP;G_0b5&*gCF5_51~gLJn4eQW!-UnvpY~@wvoz}eCT{ZiBd5WPqb0N z3mheMw0HQysA4#SRCP0ZibP?t-h#;N{*@7izHcJ2#D9y*jS}SnTN4*piYoEwgnF~$ zQ;(`#q`d_cs|yf`tL(QPXwKFr4^n*~edW=j9Bm1O>=?jp7uV`Brtpakl*c$n8GjB| zl`A1L{rmUbfX#pST4+k)Ql8B{a2vhFTY_d2W7t0ju0P+-fh^KvPa+~Xg4W-2I}iQ~ zz^~}l`8&#%ShrQR)2dsY<}S<*A%> zCPrev?B027qMD;>P~l)UxPxrCrWPOg$l3Pejfv?P2*sx9eGezhqdrx}XK>eN#_hv& zKc<4B*PZ<)K>}%zpTc!5m>}VxZ4izX-D2_Kc{x{lM^OPobegDW<$xbqUw|AuD_4>Y z&T*1oLkUzfbT&uKKD6sjm0asdHbn821@1%&qe-I*I(d0+liUaAN6q{QP_lo2cj5zV z+VU*vZ#)huH%ke5zJdoOkyzliBx}Eq z79_=InpMK(dy%wIUBAa@0py9%SZSGUSCMnepLfvJoz7BU!ZJ@9uXFfLdF}HrRtJ|A ztXuDCA8vb7I(_n|y_9hnp zD(|CRszxE6;ZG^P#|4!k8x-`TqU?AXj z#3k82l5K^OU9k-^t`k<|Ys0qB8}~mgkV*;Kh7ey_zmN`pVlMw$fACT-0?U5dCdy^`ufm-9}sGsALEC31we3<>(_Nw!Qfj4nWaLgAXM? zEf|LB{jRiVyya_*4-zFFuJJfmZxiJ`R>ziz(l6@+4J5@rEmUtVkI15ZRGD^Po9mZPeSjy6IaK<=5&X#WedaZ@2P}dw?VZDx z{RlZ~m*wPn?0ey{alCS==BYdgzT@-m$si}Q_Qm)>(Eo;tx3m=Yz2-VyIiG#PR23VS zW1l@o4KDMb5xE*En#=+UZgNKYhx9qe`k^9};K#g+M!ME+qY11l_c3`lZSrSWwZv1? zLk@cVO`^tMsadFGJ=6Fm>u1{-VzK0G+w}gluPO}M@^tfWpeO&EcbLI!P&v)E^$pH1 z+CPf8A{qNzOJT{ai+^jra2bEh7OVl^vpj|zauNC+|p@4Mv+)EV^ra_cA%A zSRC(Qiqb=p9UIfOb8^Su*J@9ufjw3VXK-&I`)VPg-0KE3I4k=(LTYL|WQM$n0nB{X z6wC)Q`Fnw$t=Z|@2REg?Y81m0cKtTP7!$B1mI#eRZ|T9r-U~u?1zMyxG|mLSAv%t? zrn>E4IFUun=9ouh6mf8FzVb<8LBJMexX;cE5x9G_9RraNGA=WhWV^~Z?iODcVu$Ta zi%iGa(lPU2!L)JdJFf z-`lOKOE%&-aP)NqcfW8q!o;$5 zdWej^>B1*WA)9HtaeZJdERY;caxy1+5KGsv)mW;Ut;I|m7`vCnEu?0>vEH-B0kHCK zU^7Si7i5|`9j1aw^I6h6q9%Uq-90akE|Bx{KNBy?#^z`uKvq4x-p4otIPT#~mf5!o z#G5#HFSC^6pv|;~wfmi`yxQ%~bw&R`RpLQ8++W~GO*E+tY^fy_qzw8jAHgQ4(0+*# zAJQ!@(X--Q-c{RnaiHG8qlLxjE=b`oP@8x6oTsT*jpv{J)R%tj#?~>;s&bN-+XSkh z_->4bKQc3c@w{JZ>{B)P&WIl&u`&j&EOPAp)YeG$@5p=hM^_h7ELVrKHB#m~9U_^# zL|iA%Y^|MsBzwHsbzL?}p|`h90=9e8bpp5A=hhNwdtgR5eq&hh!m080RA9bxo-U)* ztk0y!a)N}j@7B^F>i4U|NzpVzhOPOY;YUNc59;iGWVeznzD1PMBJSD38##|LNk{%`b8~N7YNp{) zuWJ~oaw8+v5=qV&x5cAYdK)!F(86#YQ>z}TcYl8OTqo7;|fV3CU4L-gmrs&SosVFJ#w#QdnU%@-tr`51>>vb3p6d+?;Ony>HVu$+kpmRf48sWY0y*Vs{KKr7uK~p=TE{>vIhfdu{<#x z5-xw|d)Ovt$$Y52eVXa*3$oDpI0p8q3cgPbf%;cU=;yq3} z6^{+42ILiyiF#%ktD*HR^_ESIm8q!-9p4PiFQ{O2FS)}ucQ-h(URRbu#kM%(*u-L{{s)}~&czhz zBI0LUMtb2ABdpO#GO}qUw8Q_FVD6*GBsT96A3vEQG#aqI{7QZTFKH*54f7D*n5OFg} z^!Sj?+>afnwYt&cnC!|X6|Ul!XjnmLUe(yT?a2XO_TOj5*n2bd+TQ*?!1J_Y0g}3eY*3%~{ zVfB7%B<7XHXXG%(YcEmWVZ>JD*#sH(I6zQZ+H5peVk(_U_cU*|t}XFa2zGoEDW~>O z2I3|nq~UnI>BB%)<5K^$2KMbwpqUW#9tNLfP*~~yy|nxSe@du+n6G<@pf~a-%c8zY zlAb9ibZLEB@w~&Qg>%~q+|bM@P>MB?_cRMrC|iNg(!7aBUo{e^U~AT{i3H}uG+5cY zw1?^x_+v4bv6m~w90y^v!I?ia@fMM(nyEj4+J~0{(rUGu_e7g3D4jJDBbfy@T3GNC z5)9UD(W_&n@h}QFw3^Qs^tE<-YArTF-Psj)F3Z}iB|t`Hm7&&~ulZ@Ls6C~SgT)+a zast&liR|l_y-%&{H3ZSnUc7#5UX4$0s!lDCkW3Qq%yVMR)2iNDF;Sx8Kx~V<9i^V) zeqc3PkT=(9P^QtrDiJh_J7tp4$&Q++cAI>`0#|xvQn8^wu{qf){UpS^l-`Qz6nC?V zX4}}oox@!$d!6|R`yWvAO(?HNvyq(9zI|FL64L-7eYqV*mYF9#E1OVF-#I!_>8aw* zRqcke+rKAyh1Ltt_S7zUQi41djeH&-FCmjui(O(e^pKRyP(Ie`VZ(@rl50)wBpoEi z@qEa}%sVQMjlXd>aauj6J&=y01@R9*01arldNT$xk(O=oVco2kJQcK0H2my&B4EA- zGFSTHeh(!@*6)4DGd8USZ=D)XCs^piG}xp9cfR(t2$$6S{MOpk(GDi36$#Y(vD_P~ zJ?4PEFkLo_t#92srqRjiZ0vhW`4>w(Ahoc_F1H0o-;`z(bI8SFs%VRdcCs2psaPIB z^>#fQC!g;8l^OAP@z~2U&^Yc?iWQLqG0Y zaIy%dR-d*sq@22B<~=?@AKK6O&LdDrS8DFont`YIHg5G-kr_7l2-TY+c|02f$xG?6 zZVPdit?6e;2-a4t7-IKSGUEu@>y6`sU=0UbhX$q>(itzTA1o~}vz4Al1aWGXv0JY^ z882V3Cmt*8eJ@75I@%lXeYG+QcX4MqsLx+<(bhf$R5f_BBe7RB#+BqB>7RN_{&d{E zj-H#7=|yjj@R9wgY^&yTXLvpgNDgiFH9Ejv>=CMsxlO8vYjN=XIiv!&fMG#4`yS9( zG+w3lTr~TA{TE{PHyy`73l67lzdRO7SwgZs+Y`hp{lLN8J)z}0+dbzWt170NyB}3M z49ForrWTn&qK9DycKyj0Z~AYYFD@)Wl)Oi(#xL($o)s{>zcRk%TD&Z6?)N8#UDk>Y z=Yt4J;|Fc||M~(z&&_*dMro_DCwCQLKId#+8+L4Q>0s9z5|t6K1-E`k$|9zSA0EGI z51|oo_d=>I^pZ`H-SuudvNf8&uF8mC&?DjkT<`C-u+$UuXqx`5eohZzbv;$(G~#6n zJNQl4rBu^={ZM@7jC$__0jlaZGuE?9G&si=7ik)5EFxX67$5Ll=Ub`;h6r1*EW<3k zyRg82Ad-e=t^QFKBlr@uIYiPVZk!0ee$DM)8r4&!`UIpto;nfs41jJza+#=@^8Hkp zUILV?ak2$q`4hb_eOR`S_O}k^CUP}I&3fqQS*5L-_Y4co`Cjg&`K%ZUnW26;8jn^u zs+pcXuEdxF;i{O>w^4522Z}EipJlmu`*@fnR=l8So{9U@5YF3rT%taD)9`KWRiwS~ z;eEL_J+1haDRNI!I3v(GgXcQ&u8f>j)p-s$T^eg2 z1mI#=ee;scR;NH8R(WBOHmnDS4?rd&R%;iQd4h^%-N;sfoHPg8Klg>b zNfvX^?h!ly+MVCB*MY~;o=D**;^OWKrrejHjM#@CZLnDSHqY+u8B`rgO*xVEFYy@DJz=Yl%7Ljtmvy-#!5)Xkd{%T2cJx_ zH@pk?sb0`2O=f6y&zJBg_*OvoG3y4hJb>yoXnfpG`C8$6xEjqa>HJ`c_EEK4G4@Sp zgN92nyEK$?sB#1ls2A$>L_jCgd$v^)%O1mVOkOE&EXc3l@J5Sx&cravc~lRnCZEJ8rKJFhH3c=~D4EZad53r9GeQdsA^GmQYwqwIbb`(=IAS1~h8alOC@4{!X-r zE;1#Fm<6G|9rKU9ANaB=X(0~O$Oo6Vg_m=bK1!T_FZSJ~D|&!EtiP~~vywT3r{4*a zH}rgto)k7F;qn40rg1D?y;3NNUv;$4}YHtlLI26zLWr zq$@tNb3xC4;qFuw#0b zgQG1={?-+`d<`dDBKKruJ7}^U)~_|<$H_?UTT<)TiAv6*m)3HS6$GX5L5{FR&;|i? z8$Yer=cvZ-?=Or4ok&}Be>R4z>ij1b)7u05ONr#g0sPqfxvEA3d)6Fla9&%gjEl_c ztAZ;&KM^oZRL#KR;cFjFYaT9rP z^f$-a$mGSo-#cE%WXAFMjg8OZLiDV1qM&0D-*dG=ZnIsU_+S#KgTc+ZopF2s1a`Vb z#dp4bRVFW_spFk{v(7bTKPr4#3!8KokyNaItRO>(1bHPz5?}BeIX)P6&O>df{HTS6 z)1=z1pi6(e>>WXAtU({O9ad;UhTVB!uuOeOB|iCK1P&vm`AwMmFHP0smq!G|s&%s7 zFGEO`R-mKVEBYqRlrQpN7hC)Z$!z|uuX#AxU;g2r6D1>M?~pTKGle>-AuN^QJc9m2 zg3`2K(3$N!$w0uQ(6-2(M!0U;sMl2YY6(-$-Y;(tEq^w5mYj@fX*ZlGFs&}F=gH%M z*TWj!k;5^2b6t`G#h_a2N|+kSQij;OF%%QGpZMt&c9A6UpP(`4$lo*DfrynBwCPCB zm+Gi3&8zEP>3YO=cp}B)4=C<=7`ykxrzJoKy>P9-=a#W+{idpYaR+GmReMaEO!j!- zpA4APZ|k-JB~2!F+*DG*1-ly)Z2gwK;nWAZRdJqf0ma=_Kj|1FzqH1s7IL?bSy0@K z2QNyvokx%1-@g%g`qJug`;~=ivD`y`%^xn$BF_E_o*c?Y8RiE~fm918R|?d5cbM^Y zm^olrwC6fU%!5jszCY%)?=zp)LfOcJE-%VKz;`3?)ephg7z%o zNIjl-nTn6^8OWAR@59cgRQMd2xml>jauc*5JzkQg+B4Py^83d$89g9vyz~9wIx_de zApf;*Tzw@`J5|ziMh;CmkQjDx9xWjCL6oQ9jny0a!#-N8Aj~qGY%l>^^HIc&2F2Lo z23C2Sc9O5LuUh5%Mt(`lzv3?fMnz*q&1pe{uwJUWE#|IQxHb*k71LMtw~Vkt>?wjvS2EJu8Y!q@ zl`mq#cHLrFsfh>MsXIQoLY2D&yvH$0B8}}HN{NuR3CKd}>7JD8-DOM%NojE9)ZF2l zEODK@W^+|D3#SHu*eBshgbYwq4~-k(-~DH<8#Zj%Ec0h zf8G~<%TqwHUFo2M$E^mh)wumw9*h&Q=H_6$E1YIWLs7rR_Cq}rU5WbgS=O(?rsGe8 z2SOSecuc8Bl?dSco~6n7=wgEWp61{~V7sd*Z@#B^Z6eophc!Xu4vOSJ zQ@H45K#&{?TXZy%Z&Xo#Sz$FVXx|Fl`ye6Vmb`+z_hM-DbI^6?JZvAnz9(Mhz4Qj< z!-4T5p?qKf1CQso)Iy}USJ44O_9|APFC4KGf5-9cMU!_detLTrNcZNbCHfL3(m+#) z!$Rhuvfx6)V8AS$nUc@r(RW68h791zVDeSPTlMv%6=P1u=kevX0Ar~q@@3; z=|1MesuvPV>+gmVQyMg(vndXD!~KDPXKMDrRO@14z`ZC8^+py8Bp#GNowFgx>;pg6Ik{Wsbw+}#_X zSAG#%_avuZ$g!nvw5Km@B`0WK8Jt0+zvn<^t@(}$IzY^3mHqC6WQK>pC@y=H~C#3sf=<=s)S(7k`LTByD>dDlr)e%nAl^9gA=@OYF8^b2)^ec2KiVXtVYUd`e12kGJCZgbf6>D{(y;L)D37R1c4|GU<~&S7V>GT>r2#GMw=Yr9^k z94Zg{gMYENe7^_ncY?OZh2lfDW+iaDNBe7_;z-g+mJ<&?cv>v@{L;kt$H7~30_(Fe zqM4<3)S+Y6K$HYhT6I&FvKA^wtG(89_Pt)d!_nT_q>w?uo`11h=PVwG*}%3inOrgi*A{S;UTZUtmp%`~g5GPzy~f9mhSsh^{|!>4!cM0LX%=BPn_ zV0YeKXj@*;Sq$$7Eu9!LIhy(dYrLO%V4n56^D*%cOz+fP>lxqzPDGB7u|_krq+MTH z?%?QX;V}?h6u`y<;@veFMn}Bqy&3h52_~~oyZDc-ChFAcKek_miahua45WBbE)%2^ctgd z3E>U3TmF`Pk=yY~_h~H~G2lfOyK#l(ep2AjV60IwPMFFns+^~2^#!y_edHqThnBB7 z&tI&5sYppc)CKONz?*UE3$B==myzm+?-j4LrkGxL6t2;g^${<~Y_ zyVF`Vg8V4=xyq~QKJ718uergUr6xv%bO;wbqJkDY%G{>UWU!7%UJ#+1_QPb6S*?im zzl^Lyp-D4-vs261X$fh+&CU$OLVAz_EbT5Iy&NcVhu¥8_axQ(Rdz*=wyrzs2*r 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