Changelog
A high-level history of obserae, newest first. obserae is in alpha (pre-1.0): it moves fast and every feature is open during the alpha. Dates are release dates; binaries and Docker images for each version are on the releases page. This is a bird’s-eye view, not an exhaustive commit log.
[Unreleased] —
-
New authenticated overview endpoint (
GET /api/overview): a single JSON snapshot of the daemon for external supervision — build version & uptime, flow/session/rule counts, an alert roll-up (by status, by severity, plus 1h/24h windows), parquet-ingestion timing, storage usage (DuckDB file size, free/total disk on the database mount, parquet-buffer and backup directory sizes), runtime memory/goroutines and the audit-integrity verdict. It is the authenticated counterpart to the public/healthzliveness probe and is protected by an API token carrying the newmonitoring:readpermission. A matching built-in monitoring group ships with just that permission, so you can create a dedicated, least-privilege supervision user (admins hold the permission automatically). Reads the cockpit’s cached health snapshot, so polling it adds no database load. -
Cartography alert count now agrees with the Detection page (fix): hovering a host showed e.g. “5 medium ssh” while the Detection list looked empty. Two causes, both fixed: the hover counts a 30-day window (now spelled out in the tooltip: “N active alerts · last 30d”) while Detection defaulted to 24h, so the host’s older alerts were simply out of view; and the “Triggers”/rule links from a host now open Detection on that same 30-day window. On top of that, filtering Detection by an IP (the Filter by entity key box, or a link from a host) now also finds alerts from rules that don’t group by entity — like ssh detected — whose address lives in the sample rows rather than the entity key. Previously those were invisible when filtered by IP.
-
OPNsense DHCP: Kea and Dnsmasq support: the Devices connector now reads DHCP leases from whichever backend your firewall runs — Kea, Dnsmasq or the legacy ISC dhcpd — automatically, instead of only ISC. If more than one backend answers (a misconfiguration — only one should be active), obserae ingests the highest-priority one (Kea › Dnsmasq › ISC) and flags the device row with a yellow ⚠; hover it for the explanation. As part of this, each device is polled on its own, so one unreachable firewall no longer holds up the others.
-
Removed the one-time 0.25.0 upgrade shims (internal): the boot-time
DATA_VERSION→data_versionfile rename and the legacysecrets.key/auditlog.key→masterkey.binunification are gone now that they have done their job. Upgrades must come from 0.25.0 or later — an instance still on those legacy layouts must boot 0.25.0 once before upgrading.
[0.25.0] — 2026-06-30
-
CSRF tokens survive restarts and redeploys (fix): the recurring “csrf token missing or invalid” error — which forced you to open a private browser window after an obserae change — is gone. The CSRF token is now a signed value bound to your session (an HMAC derived from the master key), so it is the same before and after a restart, the same across browser tabs, and self-heals if the browser drops or desyncs the cookie. Security is higher, not lower (the token can no longer be forged by setting a cookie). No action needed; already-open tabs may need one reload right after the upgrade.
-
Data epoch file lowercased (internal): the data-format epoch authority is now
data/data_version(wasDATA_VERSION), in step with the rest of the data dir. Upgrade is automatic: the daemon renames the file in place once at the first boot of this version. This one-time rename is removed in the next release. -
Single master key (new): obserae now keeps one at-rest key,
masterkey.bin, instead of two separate files (secrets.keyandauditlog.key). Everything else is derived from it with HKDF — the AES-256-GCM cipher that protects stored secrets (alert credentials, device API secrets, session keys) and the HMAC key that signs the audit-log seals. You can now export the master key (base64) to your secret manager and import it back, from Config I/O → Master key in the GUI orobserae-cli masterkey export|import. Importing a different key rotates it: every secret is re-encrypted and every audit seal re-signed live — no restart, no downtime. Offline audit verification takes the master directly:verify-auditlog --master-key-file masterkey.bin(the standalone Python verifier too). Upgrade is automatic: an instance with the old two key files is unified undermasterkey.binat the first boot of this version (the old files are re-keyed, then deleted) — back up the new key. Legacy support for the old files is only in this version and will be removed next release. -
OPNsense Devices connector (new): a Connectors → Devices page (admin-only) where you register your OPNsense firewalls (name, base URL, API key/secret — the secret is encrypted at rest and never shown again, plus skip-TLS / Root-CA options). obserae then polls each device every ~10 minutes (or on demand via the per-row Refresh button) for its ARP table, DHCP leases and interface overview, with a per-device OK/error status pill. The ARP and DHCP observations become two new NFQL tables —
arpanddhcp— that you can query and equi-join/PIVOT againstflows.ip/sessions.iplike any other source: the authoritative IP↔MAC↔hostname ground truth the NetFlow pipeline alone cannot see. The same data enriches the cartography: the DHCP hexagon drawer shows the firewall’s hostname/MAC/manufacturer for a lease, IP Discovery lists ARP-seen IPs first with anarptag, and Network Discovery proposes the firewall’s interface CIDRs as candidate subnets. Network and host names come from the firewall too: a subnet detected from traffic that matches an interface is suggested with that interface’s name (WAN,LAN, …) instead of a generic slug, and adopting a discovered IP names the new host after its ARP/DHCP hostname (falling back to the?<ip>placeholder when none is known or the name is taken). Devices are part of the Config I/O bundle (export/import); theapi_secretis exported in its encrypted form (never in clear text) — re-importable on the same instance. Adding a device now collects it immediately (its data appears in the drawer without reloading the page), and the DHCP lease panel was made legible. -
Alert rules no longer self-disable during parquet compaction (fix): an alert rule could be quarantined with
IO Error: Cannot open file …sessions-*.parquet: No such file or directorywhenever the background compactor merged an hour’s session files at the exact moment the rule’s query was reading them. The query engine now retries that transient “file vanished mid-read” race (the same guard the cartography and health screens already used), so it never surfaces. The fix covers every parquet reader that lacked it: interactive NFQL queries, the alert evaluator, the matcher, network-discovery aggregation, and the rule match view. -
Monitoring page (new): a Settings → Monitoring screen for sysadmins and SOC engineers. It surfaces parquet ingestion throughput and import timing (files and records written, flush last/avg/max), pipeline saturation (channel fill + UDP drops), memory (heap in-use, RSS ceiling, goroutines, GC, sessions in RAM), and database activity shown permanently — the in-flight operations plus a recent-operations ring (like
obserae-cli ps), not just whatever happens to be running at the instant you look. The DB-activity panel was removed from the Cockpit (which stays focused on product use); when there is a real database or ingestion problem a warning icon appears in the top bar, from any page, linking to Monitoring. -
Move a whole multi-selection in the cartography (fix): in edit mode, selecting several hosts/networks (shift+click or box-select) and then dragging only moved the node under the cursor — the rest of the selection stayed behind. Dragging any selected node now translates the entire selection together and persists each node’s new position.
[0.24.0] — 2026-06-26
-
No more silent session loss under storage pressure (fix): when the disk or parquet writer fell behind, the sessionizer could mark a batch as flushed while only part of it had actually been written, losing the rest without a trace — and the final batch at shutdown could vanish entirely. Flushing now blocks until the writer catches up (rather than dropping records on a timeout), the shutdown drain reliably persists the last batch, and the rare residual loss (a genuinely wedged disk) is counted and surfaced in the cockpit as a “Session data loss” banner instead of being invisible.
-
Human-readable memory limit (config, breaking):
storage.memory_limit_mbis renamed tostorage.memory_limitand now accepts a size (512MB,4GB), a percentage of physical RAM (50%), a bare number (= MB), or0/""for DuckDB’s default. The shipped configs default to50%. Percentages are resolved against physical RAM at boot (DuckDB has no%unit). Action required: rename the key in your config — the oldmemory_limit_mbis no longer read and would be silently ignored, reverting the cap to DuckDB’s ≈80%-of-RAM default. -
Cockpit stays fast on long-running instances (perf): the live cockpit health panel refreshes every 2 seconds, and several of its counters look at the rule matches. Those lookups used to scan the entire match history on every refresh, so on an instance left running for a day or two the CPU climbed and memory grew without bound. They now only read the recent time window (the same partition pruning already used elsewhere), keeping the cost flat regardless of uptime.
-
Automatic data migration on upgrade (OBS-MIG): obserae no longer loses your data when the schema changes between versions. The whole data directory (DuckDB + parquet stores + JSONL journals) now carries a single version stamp (
DATA_VERSION), and deploying a newer build converts the previous version’s data to the new format automatically at startup — across all three storage formats, not just SQL. The conversion is gated by a selective on-disk backup (migration_backup/, only the data a given migration actually rewrites, never your keys) with a disk-space pre-check that refuses loudly rather than running out of room half-way, and a crash marker that stops the daemon booting on a half-finished migration. Additive changes (a new column/field) cost no copy at all.obserae-cli statusshows the current data version;obserae migrate statusandobserae migrate restoreinspect and roll back from the command line. See Data migrations. -
Interactive query path extracted to a testable service (OBS-AUD-012): the NFQL execution logic behind the Investigation page (snapshot lock, as-of anchoring, bounded scan, truncation) moved out of the HTTP handler into a pure
query/interactiveservice, unit-tested without an HTTP stack. No behaviour change — a refactor that makes the security-sensitive query path easier to review and verify. -
CLI actions record the OS user (OBS-AUD-011): on Linux, admin actions made through the control socket now carry the connecting process’s UID/GID (read via SO_PEERCRED) in the audit log, giving a finer trail than the single “cli” principal on a multi-admin host. Other events are unchanged.
-
Interrupted restores are detected at boot (OBS-AUD-009): a restore writes a marker before swapping the database and its on-disk stores, and removes it only once both are in place. If the daemon dies mid-swap, the next start refuses to boot with an actionable message instead of silently running on a possibly inconsistent database/stores pair — re-run the restore or clear the marker after verifying.
-
CSRF protection on GUI mutations (OBS-AUD-005): every state-changing request made with the session cookie now requires a double-submit token (an
obserae_csrfcookie echoed in theX-CSRF-Tokenheader or acsrf_tokenform field). The GUI wires this automatically for HTMX, islandfetch, and native forms; API-token (Bearer) clients are unaffected. A forged cross-site POST can no longer trigger config import, backup, output or user changes. -
Interactive NFQL queries bounded at the engine (OBS-AUD-007): a broad query typed in the Investigation page without a
LIMITis now capped at the SQL level (DuckDB stops scanning at the display cap) instead of loading the whole result set into memory before truncating. Programmatic queries (detection engines, CLI) and queries with an explicitLIMITare unaffected. -
Write-lock contention is now observable (OBS-AUD-008): when a bulk writer (enrichment refresh, config import) has to wait on long-running NFQL reads to finish, that wait is counted and — past the DB-wait threshold — logged as a warning, instead of being silent. Helps explain a sporadically slow admin action under heavy query load.
-
XSS defence pinned by tests (OBS-AUD-006): the strict Content-Security-Policy keeps
'unsafe-eval'(required by Alpine.js), so server-sidehtml/templateauto-escaping is the primary defence. A new test stores a<script>payload in an operator-controlled field and proves the rendered HTML escapes it, alongside the existing test that forbids'unsafe-inline'onscript-src. The remaining'unsafe-eval'is documented as accepted tech debt. -
Docs reflect the real auth posture (OBS-AUD-010): stale comments and docs that wrongly implied the GUI was unauthenticated / assumed a single operator are corrected — the GUI requires a login backed by users, groups, RBAC and API tokens. A guard test fails the build if such a claim reappears.
-
Audit source IP no longer spoofable (OBS-AUD-004): the
X-Forwarded-For/X-Real-IPheaders are now honoured for the audit log’s source IP only when the request’s immediate peer is a configured trusted proxy (web.trusted_proxies, CIDRs or bare IPs). A direct client can no longer forge its IP in the journal. The real client is taken as the rightmost non-proxy hop, so a spoofed leftmost value is ignored. Default is to trust no proxy header.
[0.23.0] - 2026-06-24
-
Signed releases with SBOM and provenance: every release now ships keyless (Sigstore/cosign) signatures, a per-archive SBOM, and a SLSA build-provenance attestation for both the tarballs and the Docker images. Because obserae is closed-source, these artifacts let you prove a download’s integrity, authenticity and origin before running it. No key to manage — verification uses the public Rekor transparency log. See the new Verify a Release guide.
-
Secrets encrypted at rest: alert-output credentials (Slack/Telegram/SMTP/ webhook tokens, Splunk/PagerDuty/Elasticsearch keys) and the session-signing key are no longer stored in clear text in the database. On first boot the daemon generates a 32-byte master key (
<data_dir>/secrets.key, mode0400, configurable viasecrets.master_key_file) and seals those columns with AES-256-GCM. Existing clear-text values are migrated automatically at the next startup. Back upsecrets.keyoffline alongside the database — losing it makes encrypted credentials unrecoverable and invalidates all sessions. Password and API-token hashes are unchanged (already one-way). -
Rule Sets — per-rule disable now survives config import: disabling an individual rule inside a pack used to be lost the moment you imported any config bundle that also carried an Alerting section — the export right after showed every rule re-enabled. The alerting import now leaves pack-owned rules untouched (it only ever owned your own queries and rules), so a per-rule enable/disable choice round-trips through export/import and persists across later imports of other sections. Rebuild the database after upgrading.
-
Rule Sets — packs auto-install on config import: a
rule_setssection that references the bundled community pack now installs it automatically during config import, so restoring a configuration no longer requires installing the pack by hand first. Operator-uploaded packs that are not present still warn (“upload it first”) because their content is not part of the config bundle. -
Community pack — four new vendor-neutral detections (
std.community0.2.0): iot-to-remote-admin (an IoT device opening SSH/RDP/WinRM/VNC/Telnet sessions — lateral movement), dns-tunneling-volume (high-volume DNS to one Internet destination — tunnelling/exfiltration), ssh-bruteforce-or-scan (a burst of SSH sessions against one host — brute-force/scan), and iot-internet-connection-burst (an IoT device fanning out to many Internet destinations — beaconing/C2). All thresholds are tunable. -
Cartography read-only is now truly read-only: when the map is read-only (you haven’t taken the edit lease, or another admin holds it), dragging a node no longer moves it on screen and the Edit buttons on documentation are hidden. Previously a node would shift during the drag and only snap back after a round-trip, and the documentation editor could be opened (the save was refused by the server, but only after the fact). Both actions are now gated up front. No database change.
[0.22.0] — 2026-06-22
-
Flow Matrix — clearer interface/service mismatch error: scoping a rule to an interface that doesn’t carry the chosen service used to fail with a vague “service resolves to no interface”. The live preview now names the interface and where the service actually binds — e.g. service “https” is not bound to interface “eth1” (bound on eth0) — so the fix is obvious without saving.
-
Flow Matrix — interface qualifier in the entity picker: scoping a rule to one NIC of a multi-homed host is now a single, discoverable action. The separate Interface field is gone; instead the src/dst entity picker suggests interface-qualified refs (
host:web-01:eth0,host:web-01:eth1…) as you type a host name — pick one and the rule targets just that interface’s IP. Rules saved with the older two-field shape still open and edit correctly. No database change. -
Interface-scoped queries are now discoverable: the engine has always resolved
"host:NAME:IFACE"(e.g."host:dns:eth0") to a single interface’s IP, but nothing surfaced the syntax. The Investigation page’s schema sidebar now has an Interfaces section listing every host’s named interfaces — click one to drop the"host:NAME:IFACE"token at the caret and scope a query to one NIC of a multi-homed host. No database change. -
Cartography edit lock (one editor at a time): when several admins are logged in, the cartography no longer lets them silently overwrite each other. The page is read-only by default; click Edit to take the edit lease (an Editing badge) and Done to release it — changes save as you go. Everyone else is then read-only with a banner naming the current editor, disabled controls and a Request edit button. Only one editing session can be open at a time, including the same admin in two windows: the second window’s Edit is refused until the first clicks Done — so you can’t reproduce the double-edit problem by opening two tabs. The lease expires after 90 s if a tab crashes, and the rule is enforced on the server too (a carto change from a non-holder is refused). No database change.
-
Docker data-volume permissions: the images now create
/var/lib/obserae/dataandchownthe whole/var/lib/obseraetree to the non-root user (UID 65532) at build time, so the daemon can write its database, parquet store and cache out of the box — no manualchownon the host bind mount before the first start. -
Alert outputs — eleven new destinations: alerts can now be delivered far beyond webhook/Gotify. Messaging: Slack, Mattermost and Telegram (bot token + API). SIEM: Syslog (RFC5424 over UDP/TCP/TLS, as JSON, CEF for ArcSight or LEEF for QRadar), Splunk HEC, and Elasticsearch/OpenSearch (basic or API-key auth). Incident: PagerDuty (Events API v2) and Opsgenie (US/EU), both de-duplicating on the rule name. Email: SMTP with STARTTLS / implicit TLS and optional auth. Every type rides the existing reliable outbox (retry with backoff, delivery audit) and the SSRF egress guard — now extended to the raw syslog/SMTP connections too — with secrets redacted on read as before. New destinations are picked from the type dropdown on the Outputs page; Send test works for each.
-
Richer alert payloads: deliveries now also carry the rule’s tags, a threshold rule’s observed value, and a group-by rule’s key — included only when the rule produced them. They flow into the webhook JSON, Splunk events, Elasticsearch documents, syslog JSON, and PagerDuty/Opsgenie details, and map to native fields where it helps (Opsgenie tags; CEF/LEEF carry the observed value and tag list). Message templates expose
{{.RuleTags}},{{.ObservedValue}}and{{.KeyJSON}}.⚠️ Database wipe required. This release adds columns to the output delivery outbox (DuckDB schema change). Delete the DuckDB database file and let the daemon recreate it on next start. Your YAML config (cartography, rules, alerting, outputs, …) is unaffected and re-imports cleanly.
[0.21.0] — 2026-06-21
-
Rule sets (rule packs): install ready-made, vendor-neutral detection bundles. A rule set adds a standard vocabulary to the cartography —
zone/environmenton networks,roleon hosts,purposeon services — and ships rules written against it, so the same pack works on any deployment regardless of your naming. These attributes are queryable in NFQL (zone:dmz,role:workstation, andport_proto == "purpose:std.dns"for the port/protocol-basedpurpose). A new Rule Sets page installs packs (with a dry-run preview), enables/disables a whole pack, and shows a full impact screen before deletion; packs can depend on one another with version constraints. Pack rules land on the Alerting page as read-only (enable/disable or Duplicate to customise). Ships with the community pack: ten common detections (cleartext protocols, exposed RDP, DNS hygiene, direct database access, …). Config export records which packs are installed and their enabled-state — never the pack contents.⚠️ Database wipe required. This release changes the DuckDB schema (new rule-pack tables, plus
zone/environment/role/purposecolumns on the cartography). Delete the DuckDB database file and let the daemon recreate it on next start. Your YAML config (cartography, rules, alerting, …) is unaffected and re-imports cleanly — export it first if needed, then re-import after the wipe. -
Cartography discovery funnel: build the map straight from observed traffic in two stages. Network Discovery (new) proposes candidate subnets clustered from non-routable (private) flows —
/24per LAN, widening to/23–/16on contiguous ranges — and + Declare pre-fills the network form. IP Discovery (the renamed Orphan IPs drawer) then surfaces the individual IPs to add as hosts. Internal / external separation is preserved: Network Discovery is private-only; routable peers stay oninternet4/internet6via IP Discovery. -
Self-documented cartography: every host, network and group can now carry its own free-form Markdown documentation — runbooks, ownership notes, escalation steps, whatever the entity needs. The drawer renders it as formatted, sanitized HTML with an Expand full-screen view and an Edit button to update it inline. The documentation lives with the entity in the cartography, so it travels through config export/import (a
documentationfield in the YAML) like the rest of your map.
[0.20.0] — 2026-06-17
- Append-only alerts: alerts are now persisted as an append-only JSONL journal (same model as the audit log); the alerts view is folded event-sourced and has its own retention.
- Tamper-evident audit log: every journal line carries a
seq+prevSHA-256 hash chain, and closed files are anchored by HMAC seals in a separate registry. The format is verifiable from Go, the CLI (verify-auditlog) and a standalone Python tool. - Performance: a series of ingest- and tick-path optimisations (slow-tick and DB-growth fixes) for steadier throughput at high traffic.
- Accordion sidebar: pages are now grouped under collapsible themes — Network, Analysis, Connectors and Settings — with Cockpit and Audit log as direct links. The group for the page you’re on opens automatically, and your expand/collapse choices are remembered.
- Lifecycle split: the old single Lifecycle page is now three pages under Settings — Storage, Retention and Backup.
- Removed the Flow Simulator and the empty Settings placeholder page.
- Public documentation overhaul:
docs-web/reorganised (landing README +docs/), a comprehensive Configuring Exporters guide, and a Licensing & transparency page. - Web-GUI hardening guidance (reverse-proxy TLS, secure-cookie behaviour).
[0.19.0] — 2026-06-16
- IPFIX ingestion alongside NetFlow v5/v9.
- NFQL statistics engine (SPEC-ENGINE-01): time bucketing, aggregates and metric thresholds for detection.
- RAM-first sessionizer: open sessions live in memory, closed sessions go straight to parquet — bounded RAM, a far smaller DuckDB, steadier ingest.
- Security-audit remediation (egress / SSRF hardening, test-API gating) and a slow-tick fix.
[0.18.0] — 2026-06-10
- Users & access management (RBAC): accounts, groups, API tokens.
- Audit log: append-only, tamper-evident journal of sensitive actions, with its own retention.
- High-traffic crash fixes and lifecycle hardening.
[0.17.0] — 2026-06-06
- Memory: fixed an ingest-path leak; default memory cap at 80%; memory observability.
- NFQL:
JOINonip == ip, plusDROPandRENAMEoperators. - Coherent on-disk layout (per-table parquet directories).
[0.16.0] — 2026-06-05
- CLI overhaul: full configuration management from the terminal and operational parity with the GUI (help registry, per-phase commands, docs).
[0.15.0] — 2026-06-04
- Single consolidated import/export of the whole configuration as one YAML.
- Higher session ceilings; modal/UX fixes.
[0.14.0] — 2026-06-04
- Outputs: send alerts to Gotify and webhooks (custom CA / skip-TLS options).
- Host clone in cartography; lifecycle/storage improvements.
[0.13.0] — 2026-06-03
- Parquet partitioning v2: Hive-style partitions with pruning; concurrency and backup fixes.
[0.12.0] — 2026-06-02
- Hive partitioning of the parquet stores; consolidated sessions moved to parquet.
- Retention and cartography-performance improvements.
[0.11.0] — 2026-06-02
- Cartography polish: snap-to-grid, no more unwanted auto-zoom; ICMP fixes.
[0.10.0] — 2026-06-01
- Observability and performance improvements; DB-activity panel fix.
[0.9.0] — 2026-06-01
- Cartography rendered with Sigma.js (WebGL): smoother zoom/pan, better groups, icons and network shapes.
[0.8.0] — 2026-05-31
- Retention rework; ~200 MDI icons and OS badges for nodes; version in the footer.
[0.7.0] — 2026-05-31
- Alerting: turn saved NFQL queries into alert rules (cadence + cooldown).
- Import/export of rules and saved queries.
[0.6.0] — 2026-05-30
- Lifecycle & backups: DuckDB-snapshot backups with a timeline; data split by source; orphan-parquet recovery at startup.
- NFQL cookbook in the GUI; JSON/CSV export; rule-match NFQL table.
- Matcher and rule-expansion performance.
[0.5.0] — 2026-05-24
- Tags and rule-overlap (relations) detection.
- Sessions page improvements; rematching on imported rules.
[0.4.0] — 2026-05-23
- More protocols in sessions: IGMP, GRE, AH, ESP, OSPF, SCTP.
- DHCP-aware nodes (
.static/.dhcp). - Major ingest/correlation performance work (removed an O(n²) path) and stability.
[0.3.0] — 2026-05-22
- IPv6 support (NetFlow v9), including the flow matrix.
- Persistent NetFlow v9 templates; DuckDB pinned to a checkpoint-safe build.
[0.2.0] — 2026-05-20
- Multi-source session correlation: per-exporter aggregation, a consolidated view, and coherence scoring on the flow clock.
- In-memory incremental sessionizer (open-session cap, crash recovery, gauges).
- IP enrichment reworked (threat-intel vs cloud, on by default).
[0.1.1] — 2026-05-20
- Packaging fix (older glibc compatibility).
[0.1.0] — 2026-05-19
Initial release — the whole foundation landed at once:
- Ingestion pipeline: NetFlow v5/v9 over UDP → in-RAM buffer → parquet → DuckDB.
- Cartography: name your hosts, networks and groups in one global namespace, with a graph editor (auto-layout, undo/redo, import/export).
- NFQL: a pipeline query language with cartography-name resolution, pivot / anti-pivot, joins and syntactic sugar.
- Sessions: a bidirectional sessionizer with NFQL on sessions, plus a rule matcher for connectivity policy.
- Web GUI: cockpit, cartography, investigation, flow matrix, sessions.
- Flow simulation for testing without live traffic.
- IP enrichment (AWS / Azure / Google ranges).
- CLI and Unix control socket; Docker images and release tarballs; EULA and user documentation.
Pre-1.0: a minor version can include breaking changes. The terms that ship with your version are yours to keep — see Licensing & transparency.