0.4.0¶
Released 2026-06-10.
The correctness and LLM-querying release. A full audit of the server drove
0.4.0 end to end: the correctness lot that makes "the log is the source of
truth" hold under failure, then a product lane that turns the MCP surface into
a precise, budget-aware query layer — three new tools, edge-aware traversal,
bounded results — plus tenant security and an ingestion you can finally watch
on /metrics.
Not a wire-contract break: a 0.3.x OTLP producer keeps working unchanged, and there is no data migration. A few behaviors got sharper (timeline-tool defaults, startup validation, 404 on unknown tenants) — see the 0.3 → 0.4 migration guide.
Added¶
graph_diff— the net difference of the graph between two instants: entities and relations created, deleted, changed (with the union of changed keys), and a first-class transient bucket for flapping — heartbeats and intermediate churn collapse away. Ask "what is different now compared to this morning?" instead of paging events.find_path— shortest relation path between two entities, each hop carrying the relation type and direction.reachable: falseis a real answer ("these are not connected within the cap"), not an error.telemetry_keys— the graph-to-observability pivot: for one entity, the exact OTel resource attributes that locate its metrics and logs in your backends — its own keys plus those inherited from direct neighbors (a listener gains its host'shost.idviaruns_on), each with the Prometheus-style flattened label spelling and usage caveats (ephemeral pids, name-vs-identity).- Result budgets on the timeline tools.
recent_changesandentity_historyexclude heartbeats by default, takechange_type/include_heartbeats/limit, and return a digest (total,truncated,heartbeats_excluded, per-type counts).get_neighborsnow says how each entity was reached (via_relation,direction,depth). Every tool call runs under a 30-second budget. - Ingest counters on
/metrics: export outcomes, per-record results, tenant rejections, auth failures — a stalled or erroring producer is visible immediately, not when the liveness sweep starts deleting its entities. - Tenant security:
TOISE_TENANT_TOKENSbinds a token to its tenant (HTTP 403 / gRPCPermissionDeniedelsewhere — the per-ResourceLogstenant.idoverride cannot bypass it);tenant_auto_create,tenant_allowlistandmax_tenantsbound tenant creation; reading an unknown tenant is a 404 and never creates a store. toise-server checkpoint— consistent per-tenant cold backups, with a new Backups page.
Fixed¶
- Ingest integrity: batched commits apply to the graph and notify subscribers only after the durable append; contract-violating records are rejected per record (their valid siblings land); removing an already-cascaded relation is a no-op instead of a poison pill that failed every later export from that producer.
- Restart integrity: snapshots no longer resurrect deleted entities; replay after retention pruning rebuilds the identity indexes (no more permanent duplicates).
- Retryability: export failures carry
InvalidArgument(permanent) orUnavailable(retry) instead ofUnknown, so spec-compliant exporters retry exactly what should be retried. - Lifecycle: maintenance loops are joined before the stores close; a dead
OTLP receiver takes the process down instead of serving a green
/readyzover a dead ingest; deploys exit clean with connected streaming clients.
Changed¶
- Maintenance (heartbeat coalescing, retention pruning) scans on a Pebble snapshot off the append mutex — it no longer pauses ingestion.
toise_entities_by_typecaps at the top 50 types plusother.- Configurations that would silently misbehave (half-set TLS, retention without compaction, unknown log level) are rejected at startup.