v0.9.1
[0.9.1] - 2026-07-03
Correctness and hardening from a full engineering review. A patch release that
closes a silent time-travel data bug, an audit-attribution bug, and a cluster of
durability, tenant-lifecycle, and security residuals, and completes the same_as
identity-belief path end to end. Every change is additive and backward compatible:
existing producers, consumers, and deployments keep working unchanged; no wire-contract
break, no data migration. The producer SDK moves to pkg/emit/v0.4.0.
Added
same_asconfidence and basis, end to end (SDKpkg/emit/v0.4.0). A producer
can now assert an identity belief — "these two nodes are the same real thing,
confidence 0.95, basisifPhysAddress" — viaRelationship.Confidence/.Basison
the SDK andconfidence/basison thesame_asdescriptor at ingest. The read-time
canonical overlay (ADR 0020) collapses those beliefs; until now it had no way to be
fed and was inert. Belief attributes ride only onsame_asedges; other embedded
edges stay attribute-free. The conformance kit advises on asame_asedge whose
confidence is missing or out of[0,1].
Fixed
- As-of queries silently dropped live entities past the retention horizon. After
pruning, an as-of fold for an instant between the retention horizon and now could omit
a still-live entity whose only surviving event was a recent heartbeat — returning a
graph missing real infrastructure, with no error, to LLM and GraphQL callers alike.
Retention now re-materializes a baseline event at the horizon for such entities
(self-cleaning, no unbounded growth). ADR 0013 amended. - Operator writes were audited under the wrong tenant. Every
annotate_entitywas
recorded as tenantdefault(and a derive-only scoped token's write was misattributed)
because the resolved tenant was never stamped into the request context. Fixed at the
tenant router, so the audit trail attributes every write to the tenant it targeted. - A gapped or overlapping shipped log was replayed silently. Log restore now
validates segment contiguity and hard-errors on a gap or overlap instead of rebuilding
a wrong graph; a marshal error on ship is surfaced, and the cursor cache is invalidated
on a failed put. - Tenant lifecycle.
MaxTenantsis enforced atomically under concurrent first-use
(no over-mint past the cap), anddelete-tenantrefuses to run against a live server
(it takes the pebble lock) instead of removing an open store's files. - A mass expiry no longer stalls ingestion. When a producer dies and its whole
subtree lapses at once, the sweep commits every expiry in one durable batch (one
fsync) instead of one per entity and edge. - The conformance kit rejected the AnyValue
entity.descriptionToise itself emits
since 0.9.0, and a producer-guide snippet told producers to retry a permanent
PartialError. Both corrected.
Security
- OIDC/JWT role claim. A configured-but-absent, empty, or unrecognized role claim is
now a hard reject instead of a silent grant of the full role. ingest_mtls_only. A configuration that would leave the read surface open (no read
authenticator, orderive-onlytenancy a client certificate cannot carry) is refused
at startup rather than silently serving reads unauthenticated.
Install
# Linux amd64 (adjust os/arch: darwin/linux, amd64/arm64)
curl -fsSL -o toise.tar.gz https://github.com/toise-dev/toise/releases/download/v0.9.1/toise_v0.9.1_linux_amd64.tar.gz
tar xzf toise.tar.gz && ./toise_v0.9.1_linux_amd64/toise-server --help
# Container
docker pull ghcr.io/toise-dev/toise:v0.9.1
# Producer SDK
go get github.com/toise-dev/toise/pkg/emit@v0.4.0Producer SDK: pkg/emit/v0.4.0 (adds same_as identity beliefs). Docs: https://toise.dev/docs