Skip to content

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: false is 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's host.id via runs_on), each with the Prometheus-style flattened label spelling and usage caveats (ephemeral pids, name-vs-identity).
  • Result budgets on the timeline tools. recent_changes and entity_history exclude heartbeats by default, take change_type / include_heartbeats / limit, and return a digest (total, truncated, heartbeats_excluded, per-type counts). get_neighbors now 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_TOKENS binds a token to its tenant (HTTP 403 / gRPC PermissionDenied elsewhere — the per-ResourceLogs tenant.id override cannot bypass it); tenant_auto_create, tenant_allowlist and max_tenants bound 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) or Unavailable (retry) instead of Unknown, 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 /readyz over 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_type caps at the top 50 types plus other.
  • Configurations that would silently misbehave (half-set TLS, retention without compaction, unknown log level) are rejected at startup.