Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6184167
perf: accelerate policy and memory hot paths
Aug 8, 2026
020062b
perf(memory): bound top-k ranking work
Aug 8, 2026
b364d7a
bench(memory): cover keyword index selectivity
Aug 8, 2026
8a699bd
perf(memory): index selective keyword queries
Aug 8, 2026
e5d5a08
bench(memory): cover cognition digest scaling
Aug 8, 2026
82d903c
perf(crypto): enable accelerated SHA-256
Aug 8, 2026
ba4c46f
perf(memory): stream borrowed cognition identities
Aug 8, 2026
c2a7de3
bench(memory): isolate cognition wire serialization
Aug 8, 2026
fa11387
perf(memory): validate proposal identity in one pass
Aug 8, 2026
5f099c1
bench(integrations): cover DID and receipt hot paths
Aug 8, 2026
adc0176
fix(bench): use a canonical governed scope
Aug 8, 2026
9dc3fe9
perf(integrations): prune replay claims by expiry
Aug 8, 2026
f65610a
perf(integrations): accelerate envelope hex decoding
Aug 8, 2026
ff76a1e
perf(integrations): stream signed envelope references
Aug 8, 2026
a271dbd
perf(integrations): reuse sealed receipt validation
Aug 8, 2026
6fbf415
ci: pin reviewed Grust dependency
Aug 9, 2026
ddd70cf
docs(grust): align current adapter versions
Aug 9, 2026
7fd62a0
docs(grust): refresh company graph adapter version
Aug 9, 2026
0b606f6
fix(example): authorize scoped graph persistence
Aug 9, 2026
a45ecd8
docs(sail): record production company graph gate
Aug 9, 2026
d158b64
docs(book): rebuild Typesec release artifacts
Aug 9, 2026
a5fb4f8
Fix Python graph gate smoke resource
Aug 17, 2026
669e105
Format Python graph gate smoke test
Aug 18, 2026
3c5e0b1
Bind semantic decisions to signed receipts
Aug 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
80 changes: 80 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,86 @@ by release version, then by the date the logical change landed.

## Unreleased

- Add a closed semantic decision vocabulary and signed, immutable-model-bound
receipts for publication, consumption, field access, metric execution,
semantic queries, and AI-context access.

- Align the Python graph-gate smoke test with the least-privilege
`company/*/org-graph` persistence grant used by the company policy.
- 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/<tenant>/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.
- 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
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
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
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
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
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.
- 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
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
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
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,
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
51 changes: 27 additions & 24 deletions crates/typesec-core/benches/policy_check.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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<CanRead, GenericResource> =
mint_capability(&engine, black_box("agent:bench"), black_box(&resource))
.expect("allow");
black_box(cap);
}
let cap: Capability<CanRead, GenericResource> =
mint_capability(&engine, black_box("agent:bench"), black_box(&resource))
.expect("allow");
black_box(cap);
})
});
group.finish();
}

fn bench_lattice_promotion(c: &mut Criterion) {
Expand All @@ -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) {
Expand All @@ -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!(
Expand Down
5 changes: 5 additions & 0 deletions crates/typesec-integrations/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading
Loading