Changelog¶
All notable changes to this project are documented below. This project uses Semantic Versioning and Conventional Commits. This page is generated from the repository CHANGELOG.md.
5.2.1 (2026-10-21)¶
Bug Fixes¶
- deps: enforce Go 1.27.3 and distrusted CA bundles (862bd1e)
- deps: update module github.com/knadh/koanf/v2 to v2.4.0 (#719) (7160cfe)
- deps: update module github.com/prometheus/prometheus to v0.315.1 (#730) (e2dabdf)
- deps: update module modernc.org/sqlite to v1.61.0 (#729) (d8c7975)
5.2.0 (2026-10-13)¶
Features¶
- config: acknowledge the flow store at rest; skip perm advisory on kubelet RO mounts (45d541f)
- nodemetrics: curate sampled Service throughput with scoped dashboard (3393e3c)
- probe: inspect OTLP HTTP acknowledgements safely (d5f023f)
- settings: emit bounded route-selection modes and preserve absent values (84ab7ca)
Bug Fixes¶
- alerts: exempt devices that cannot self-update from auto-update coverage (a7123cf)
- alerts: scope auto-update posture rule; surface config advisories in Loki (98d4f39)
- ci: provision existing just tool for client-library tests (9bb62a0)
- deps: update module github.com/klauspost/compress to v1.20.3 (#708) (a4c9e68)
- deps: update module github.com/oschwald/maxminddb-golang/v2 to v2.8.0 (#707) (453e9c8)
- deps: update module github.com/prometheus/common to v0.72.1 (#706) (627a537)
- deps: update module golang.org/x/sys to v0.49.0 (#699) (c854778)
- docs: gate README overview capability counts (c071d91)
- grafana: anchor empty fleet summaries to observed inventory sources (373608d)
- grafana: consolidate current cardinality and overflow views (8ce801c)
- grafana: count distinct metric families across reporters (01f65be)
- grafana: distinguish missing cardinality reports from healthy zeros (0ee91ed)
- grafana: distinguish missing exporter telemetry from healthy zeros (2cd8d44)
- grafana: enforce applicable selectors across dashboard queries (00a9936)
- grafana: label route mode as historical observations (2480a1f)
- grafana: make OS pie legend readable with expanded navigation (963635c)
- grafana: scope node metrics by tailnet and provider (67c5bf0)
- grafana: show neutral missing process telemetry on runtime stats (6f1797b)
- ingress: bound permanent rejection retries and count data loss (c30c532)
- review: require complete finding totals to match events (50cb41a)
- scripts: report CodeRabbit finding counts in sharded review summary (02f11c2)
- telemetry: attribute runtime traces and correct dashboard ownership (760fda5)
- telemetry: bind delivery-health diagnostics in every provider (7977987)
- telemetry: decouple ingress WAL completion from metric collection (3f2b465)
- telemetry: distrust malformed HTTP response classification (07acc0e)
- telemetry: log only bounded classes in export failure diagnostics (303616b)
- telemetry: report hung ingress exports as retrying (df6cd72)
5.1.0 (2026-10-08)¶
Features¶
- dashboards: add fleet and security visual views (48731fd)
- dashboards: add flow topology views (4065d0e)
- dashboards: add specialist panel primitives (f2ee3d4)
- dashboards: add state and cost visualisations (25971a7)
- dashboards: diversify dashboard visualisations (bc2fd2a)
- dashboards: track visualisation diversity audit (6872e54)
Bug Fixes¶
- deps: update go dependencies to v0.37.1 (#652) (2617306)
- deps: update module github.com/grafana/otel-profiling-go to v0.7.0 (#687) (6880dbd)
- deps: update module github.com/grafana/pyroscope-go to v1.4.3 (#673) (1076aa4)
- deps: update module github.com/knadh/koanf/providers/env/v2 to v2.0.2 (#682) (7fa38fa)
- deps: update module github.com/knadh/koanf/v2 to v2.3.7 (#654) (7ea4916)
- deps: update module github.com/knadh/koanf/v2 to v2.3.8 (#689) (d4298fb)
- deps: update module github.com/oschwald/maxminddb-golang/v2 to v2.7.0 (#669) (d7c4afe)
- deps: update module github.com/prometheus/common to v0.72.0 (#664) (c885c40)
- deps: update module go.opentelemetry.io/proto/otlp to v1.11.1 (#671) (324e504)
- deps: update module modernc.org/sqlite to v1.60.1 (#668) (cc1bab7)
- deps: update opentelemetry to v1.47.0 and stable logs v1 (677a905)
- portservice: refresh the IANA service registry (b4faa1d), closes #678
5.0.4 (2026-09-18)¶
Bug Fixes¶
- alerts: close the severity contract - validate it, and document
advisory(8f04a03) - deps: pin google.golang.org/grpc to v1.83.2 (CVE-2026-84445) (f58018e)
5.0.3 (2026-09-18)¶
Bug Fixes¶
- deps: update go dependencies (#618) (cd0b961)
- deps: update module github.com/oschwald/maxminddb-golang/v2 to v2.6.0 (#616) (56334cc)
- deps: update module google.golang.org/grpc to v1.84.0 (#635) (951443e)
- deps: update module modernc.org/sqlite to v1.59.0 (#632) (9b87e46)
- wal: allow complete batched metric flushes before retrying (423c3ae)
5.0.2 (2026-09-07)¶
⚠ BREAKING CHANGES¶
- helm: stop version-varying labels on the checkpoint claim template
Bug Fixes¶
- helm: pin volumeMode on the checkpoint claim template (d24ef9c)
- helm: stop version-varying labels on the checkpoint claim template (3658371)
Documentation¶
- helm: chart 0.36.0 needs a one-time StatefulSet delete with persistence enabled (9416f6a)
5.0.1 (2026-09-07)¶
Bug Fixes¶
- app: stop the ingress WAL startup drain blacking out a promoted leader (9e72581)
5.0.0 (2026-09-06)¶
⚠ BREAKING CHANGES¶
- config: Enabled non-loopback streaming and webhook receivers now fail startup unless every legacy or routed endpoint has its required token or secret. Credential-free loopback listeners remain supported for local-only use and warn about local injection risk. Go consumers must use github.com/rknightion/tailscale2otel/v5.
Features¶
- admin: harden Wave 3 storage and access (6d9c23c)
- alerts: cover coordination leadership health (74a8c92)
- alerts: watch five signals that nothing alerted on (7841543)
- app: wire wave 1 runtime controls (1de673f)
- checkpoint: persist cursors in Kubernetes (ed38f70)
- collectors: configure dedup capacities (1209ff3)
- collectors: quiet expiry warning cadence (72fb042)
- config: add fleet discovery and operator forecasts (882b4cf)
- config: freeze PAM tailnet and session-log configuration seams (7f4cbfa)
- config: freeze wave 1 configuration (f54548a)
- config: freeze Wave 3 configuration seams (992c3e3)
- config: require credentials for network receivers (69ca527)
- console: adopt design system v2 (05a1c9c)
- coordination: add Kubernetes Lease leadership (1195f4b)
- coordination: label the leader pod and let standbys be Ready (06522af)
- dashboards: regroup operational surfaces (1ea4b8b)
- devices: bound posture attribute cardinality (06e7fc7)
- dev: shard CodeRabbit pre-commit review (322f1e8)
- headscale: honor retry and rate limits (7292f5a)
- helm: add extraContainers for sidecars alongside the exporter (31b7c31)
- helm: per-replica persistent state for coordinated replicas (5d966fe)
- helm: route leader-only Services by the role label (522f662)
- helm: support coordinated replicas (aea526d)
- logstream: expose bounded destination configuration per log type (dbaeeb4)
- node-metrics: support per-tag port overrides (e4c9e46)
- observability: complete Wave 2 lifecycle coverage (fa6a465)
- pam: add Border0 telemetry collector (9994c0a)
- pam: opt-in per-session log record behind pii_filter (c94ba92)
- pam: select the tailnet runtime that hosts PAM telemetry (076ac92)
- resilience: harden Wave 3 ingestion and runtime (f35b6ab)
- snapshot: freeze Wave 2 snapshot and config seams (27c92b4)
- telemetry: apply per-tailnet cardinality limits (175e3ce)
Bug Fixes¶
- alerts: bound a dead leader's vote in the coordination rules (2c40439)
- alerts: emit the absolute deploy/alerts README link from the generator (76a0b8f)
- alerts: match Grafana runtime status shape (f2e221e)
- alerts: verify post-publication evaluations (eb5c7fd)
- app,tsapi: close flow stores on failed construction and pin the org path segment (2167354)
- app: bound concurrent flow store shutdown (2d84e51)
- app: emit the scope-preflight metric from the heartbeat (8634816)
- audit: classify new configuration audit values (102333f)
- audit: classify PAM configuration changes (f339e17)
- auth: implement workload identity exchange contract (5b55617)
- auto-rc: restore checks:read — reusable permissions validate at startup (86c3e84)
- checkpoint: reconcile markerless rollback writes (0513e63)
- checkpoint: reconcile rollback-era legacy writes (47f16b8)
- checkpoint: restart after uncertain Kubernetes writes (976cc00)
- checkpoint: shard Kubernetes checkpoint state (2901c12)
- ci: give the tailnet-join workflows their own WIF secret (810ef36)
- ci: make clientlib drift verdicts explicit (37c941b)
- ci: repin rknightion/.github refs to v1.9.7 so Renovate can track them (35ddeb1)
- ci: unbreak the release pipeline and stop :main freezing on infra failure (daf81d8)
- config: make secret source conflicts explicit (1513eb1)
- config: reject oversized Kubernetes checkpoints (b0eb87a)
- coordination: deduplicate handover observations (fe3c3cc)
- coordination: expose standby process metrics (15e4777)
- coordination: self-fence on lease replacement (8477683)
- coordination: validate retry jitter bound (0e212ab)
- deploy: close starter and verification gaps (d3af40f)
- deps: update go dependencies (#600) (3ae7cb8)
- deps: update go dependencies (#610) (7809c8b)
- deps: update module github.com/rknightion/tailscale2otel/v4 to v4.0.1 (#584) (274dafe)
- deps: update module modernc.org/sqlite to v1.58.0 (#606) (50f4e77)
- deps: update v5 self-module matcher (ef9f5ea)
- docs: gate alert panel-link counts (f9a9ad4)
- flowstore: keep legacy flow database usable (22a023b)
- headscale: classify configured tailnet prefixes (1fbb579)
- helm: default coordination to release namespace (ff444ba)
- helm: give kubeconform the CRD schemas for ServiceMonitor (4f60b87)
- helm: restore the doubled braces in the CRD schema URL (7c680b6)
- ingest: close cancellation races (16f25e1)
- observability: address Wave 2 review findings (a18a5dd)
- observability: scope the dedup overlap horizon to the poll path (e3caac4)
- stream: restore flow capture delay telemetry (f825e5d)
- telemetry: guard stable instrumentation scope (86f4b5e)
- tooling: select Grafana verification context (630b1d7)
4.0.1 (2026-08-27)¶
Bug Fixes¶
- acl: persist revision provenance (8b510f6)
- ci: follow GitSync dashboard path (e0d20a2)
- dashboards: repair live signal accuracy (d00c0ce)
- release: stream the latest-release response instead of buffering 64 KiB (59bae17)
- state: separate evidence durability from poll cursors (66fcb05)
4.0.0 (2026-08-27)¶
⚠ BREAKING CHANGES¶
- improve first-run delivery experience
- move the Go module path to /v4 ahead of the 4.0.0 release
- flowstore: rename flows.store.path to directory and surface backend health
Features¶
- admin: add a bounded audit and webhook event explorer (8b655e9), closes #300
- admin: add a per-tailnet selector to the status page (306a161), closes #325
- admin: add defensive HTTP headers to every admin response (7d4aa8f), closes #322
- admin: export the complete effective redacted configuration (fffa889), closes #320
- admin: generate a privacy-safe support bundle (a7b49a6), closes #321
- admin: list active configuration advisories on the status page and API (8491a31), closes #319
- admin: make both embedded UIs keyboard-operable and screen-reader-legible (66ac88d), closes #327
- admin: make UI polling single-flight, visibility-aware and backoff-capable (1b3176a), closes #328
- admin: report actual OTLP delivery state instead of a collector proxy (5c38fd2), closes #317
- admin: show update availability on the status page (e736ba2), closes #330
- alerts: canonical recording rules, SLO burn-rate alerts, and approval-workflow alerts (623240e), closes #406 #398 #410
- alerts: close the notification gap on object-store, receiver, drop and posture faults (99c1226), closes #399 #401 #402 #404 #405
- alerts: enable ConfigInvalid by default, and record standing Grafana push authorization (fec022a)
- alerts: per-rule evaluation policy, runbook and panel links, and a real PromQL parser gate (e54a4cd)
- annotations: publish curated tailnet events to Grafana as annotations (8d2ab97), closes #518
- api: freeze availability-state, scope-class and entity-age seams (da772f5)
- api: restore dropped telemetry dimensions and classify API availability (7445cc6), closes #411 #412 #413 #414 #415 #416 #417 #418 #419 #420 #421 #425 #426 #427 #428 #429 #430
- api: version and publish the admin status/flows API contract (fde409f), closes #323
- auditlogs: ingest the configuration-log S3 export (2018f07), closes #288
- catalog: gate every signal on a declared dashboard/rule disposition (1d2203b), closes #390
- catalog: gate that every emitted signal reaches a panel (4617b10), closes #526
- checkpoint: use a platform-appropriate state path on native runs (3ce3461), closes #336
- ci: authenticate the live-contract lane with workload identity federation (8de36d5), closes #355
- ci: check documented install commands against the real schemas (123fe72), closes #445
- ci: review the Tailscale changelog for new observability surfaces (cfc60b9), closes #446
- ci: watch the committed IANA service registry for staleness (a0fdd75), closes #440
- cli: add -preflight and -once single-cycle execution modes (ee7e206), closes #311
- cli: add a native -healthcheck readiness probe (4cc1bb3), closes #337
- cli: print the effective redacted configuration and where each key came from (355c8b1), closes #309
- config: add log_format for one-record-per-line JSON logs (c156ccd), closes #312
- config: advise when a flow-cardinality key is inert under the current metrics_mode (681fe1e), closes #525
- config: generate a standalone JSON Schema for the application config (b15156f), closes #308
- config: report every configuration diagnostic in one pass (95da889), closes #307
- dashboards: add the Kubernetes Audit tab (0e02a05)
- deploy: add file-based Docker Compose secrets, and fix audit objectstore (a544576), closes #334
- deploy: ship a validated Alloy gateway recipe (5c422ab), closes #363
- docs: take the fleet project icon for the site logo and favicon (a6db322)
- docs: take the fleet-generated social card (4bffb6b)
- enrichment: add optional local GeoIP and ASN enrichment (47d9e49), closes #461
- flows: export the filtered connection list as CSV and JSON (cebb89d), closes #299
- flows: filter and paginate connections server-side (86833de), closes #296
- flows: make flow-store capacity and memory policy configurable (ead2f47), closes #329
- flows: put the flow view's state in shareable URLs (1f32b15), closes #298
- flowstore: optional SQLite persistence for multi-day /flows history (4b25580), closes #294
- github: replace free-form issue templates with structured forms (ea9f9bf), closes #444
- grafana: group the flagship's ten flat tabs into a two-level navigation (e0e20b9), closes #495
- grafana: rebuild the health dashboard around pipeline stages (6a16821), closes #526
- grafana: rebuild the product dashboard around domains and sub-tabs (b3572e8), closes #526
- helm: add an opt-in Prometheus Operator PodMonitor (e01d6c6), closes #345
- helm: add an opt-in Prometheus ServiceMonitor (9ade22f), closes #458
- helm: add default-off, per-listener Services (1e5d29a), closes #344
- helm: add first-class projected Workload Identity Federation tokens (30589c4), closes #343
- helm: add image digests, configurable probes, and a NetworkPolicy baseline (15cd177), closes #349 #350 #351
- helm: add opt-in Ingress and Gateway API routes for the receivers (9993b50), closes #346
- helm: add typed extraEnv and extraEnvFrom with a reserved-name policy (b188b9a), closes #348
- helm: support externally managed application config resources (098dbb3), closes #347
- improve first-run delivery experience (2cf4644)
- ingest: add optional durable receiver WAL (04384a2), closes #279
- ingest: expose trust and harden receiver edges (e88c1c5), closes #262 #263 #265 #266 #270 #275 #276 #281
- ingest: make event ingestion trustworthy (6561eb7), closes #258 #259 #260 #261 #264 #267 #268 #269 #272 #273 #274 #278 #280 #282
- k8saudit: export metrics and logs from tsrecorder Kubernetes audit data (b61fe7a), closes #462
- mint release-please token from the OpenBao broker (fec703d)
- mint the docs-sync token from the OpenBao broker (b618f04)
- oas: detect parameter, success-status and media-type drift (ffb7a95), closes #432
- objectstore: expose provider request and cursor-health telemetry (6709c54), closes #451
- objectstore: support flat copied-export layouts (0794f61), closes #293
- objectstore: support per-tailnet storage destinations and credentials (ddef918), closes #284
- observability: installable alert profiles, dashboard a11y and budget gates, and deployment drift verification (ea53c30), closes #389 #396 #397 #408
- observability: move alerts to gcx-native manifests and close the 71-signal coverage gap (9a3674c)
- observability: stop rendering unchecked security signals as healthy zeros, and compare ingestion across sources (db37106), closes #395 #400
- rdns: serve a resolved PTR name past its TTL while refreshing (e17a3cc), closes #297
- release: read the published release back and fail when it is incomplete (3c413e1), closes #442
- s3: support AWS container credential providers (26bb03c), closes #452
- telemetry: bound log records, trace dark clients, harden /metrics (3858408), closes #356 #366 #367 #369 #371 #374 #375 #376 #377 #378 #379
- telemetry: finish the OTLP exporter core, sampling and profiling work (0084290), closes #357 #358 #359 #360 #361 #362 #365 #370 #372 #373 #380 #383 #384
- tls: reload listener certificates in place and expose expiry health (9b92b48), closes #316
Bug Fixes¶
- acl: send the policy to /acl/validate, and stop 4xx reading as transient (1e488ef), closes #523
- admin: derive the status verdict from the same component state as /readyz (3aaab59), closes #318
- admin: make the /events explorer keyboard- and screen-reader-legible (25e5b2b), closes #512
- admin: make the default landing page safely usable (3584827), closes #314
- alerts: 10m pending window on exporter-down and config-invalid (b399957), closes #529
- alerts: correct the three stale rule counts that have had CI red (b27ed99)
- alerts: execErrState spells its OK state "Ok", not "OK" — corrected by a real push (5eead5b)
- alerts: key credential and auth alerts off semantics, not raw counts (2b48098)
- api: complete API fidelity drift contracts (fb4f877), closes #422 #423 #424
- apply CodeRabbit auto-fixes (b8634c4)
- author is Rob Knight, not Rob Knighton (54ef3c7)
- catalog: a template variable is not a panel (c54e0df)
- ci: aggregate matrix failures before filing, so one defect files one issue (b695f27), closes #435
- ci: satisfy workflow contracts (d8a56ad)
- ci: stop two version/timing-fragile tests failing correct code (cb07b5d), closes #521
- ci: the dashboard sync reported success while publishing nothing (f167a1c), closes #526
- ci: use a plain if in the live-contract negative case (2aa2e03)
- config: canonicalize listener addresses and feed bind failures to readiness (6a113d9), closes #306
- config: only require a positive prometheus.max_requests_in_flight while the endpoint is on (9df928e)
- config: protect object-store credentials (3260963), closes #449
- config: reject global objectstore in multi-tailnet mode (c6f66b0), closes #283
- config: reject unknown YAML configuration keys (96c5e9b), closes #303
- config: resolve relative file paths against the config file's directory (8154192), closes #310
- config: validate complete, loadable TLS keypairs for every listener (a3b96be), closes #305
- deploy: align Compose and Kubernetes shutdown budgets with the staged drain (ac58014), closes #332
- deploy: move the Compose config-file mount to an override file (a9311a3), closes #333
- deploy: split the published-image Compose from the developer build (1faaa5e), closes #335
- deps: update github.com/tailscale/hujson digest to b80ff77 (#508) (6ca7c86)
- deps: update go dependencies (#572) (34589ff)
- deps: update module github.com/knadh/koanf/parsers/yaml to v1.1.1 (#535) (7480415)
- deps: update module github.com/knadh/koanf/providers/env/v2 to v2.0.1 (#536) (1ecd7dd)
- deps: update module github.com/knadh/koanf/providers/structs to v1.0.1 (#537) (44f863d)
- deps: update module github.com/knadh/koanf/v2 to v2.3.6 (#538) (66e0992)
- deps: update module github.com/prometheus/prometheus to v0.313.2 (#522) (2a032d4)
- deps: update module go.opentelemetry.io/proto/otlp to v1.11.0 (#499) (f4bf065)
- deps: update module google.golang.org/grpc to v1.83.0 (#520) (924be79)
- deps: update module google.golang.org/grpc to v1.83.2 (#576) (391dfa0)
- deps: update module modernc.org/sqlite to v1.56.0 (#530) (93c61f5)
- deps: update opentelemetry to v1.46.0 / log v0.22.0 (613d0a3)
- dev: make cloud setup cross-agent compatible (34f8f78)
- flowlogs: preserve node identity through poll dedup (622773c), closes #257
- flowstore: give pre-4.0.0 flow databases a way to be adopted (0741792)
- flowstore: order recent rows by event time and scope them to the query window (3de4fc7), closes #295 #301
- flows: version policy verdicts so retained traffic cannot join to the wrong rules (a6d14c9), closes #302
- grafana: give boolean panels semantic polarity and stop zero-filling absence (be4fc7d), closes #385
- grafana: panels referenced variables that were not in scope (c300199), closes #526
- grafana: the degradation row rendered on a healthy exporter (a273aa7), closes #526
- helm: make liveness/readiness probes follow admin TLS (82e43b5), closes #342
- helm: reject unknown values with a strict chart schema (69d7746), closes #304
- helm: render every Secret-typed config field into a Secret, not a ConfigMap (a51d901), closes #518
- helm: stop teaching credentials on the command line (7cd9a84), closes #341
- helm: stop the chart README drifting on every release PR (a78961e), closes #521
- metrics: make Prometheus authentication fail closed (5a0be19), closes #315
- oas: parse OpenAPI 3.1 type arrays and typed maps in drift analysis (607b32a), closes #431
- objectstore: accept .json.zstd and .json.gzip export keys (3df1b32), closes #496
- objectstore: bound decoded ingestion work (f969025), closes #292
- objectstore: commit objects only after complete preparation (f3e871e), closes #448
- objectstore: fail an object whose every row fails to decode (4f670ab), closes #497
- objectstore: persist bounded listing progress (8c951e2), closes #285
- objectstore: persist failed ingestion gaps (bf7e92d), closes #286
- objectstore: stop erasing durable listing progress under a leading-slash prefix (2fb0c45), closes #498
- objectstore: support official export keys (9b9f7a3), closes #447
- pass the JWT role explicitly for docs-sync (cb91b11)
- receivers: carry trace context onto streamed flow, audit and webhook logs (0a3536e)
- release: wait for the module proxy before GoReleaser rebuilds from it (f59c6f4), closes #254
- s3: preserve configured endpoint base paths (1e716e1), closes #290
- s3: stream list responses and refuse oversized ones explicitly (7ebdb9c), closes #291
- security: close 14 advisories across credentials, admission control and cache trust (6b65274)
- security: close the EPIC-10 follow-ups across decode budgets, retries, and checkpoints (15b1038), closes #488 #489 #490 #491
- security: close the public hardening backlog across privacy, credentials, and build context (476f236), closes #464 #465 #466 #467 #468 #469 #470 #471 #472 #473 #474 #475 #476
- security: remediate 19 scan findings (45e489c)
- selfobs: correct object-store ingest source and byte semantics (cc6e498), closes #450
- status: light up api-availability for every collector, and make the status page say why (6acd70f), closes #524
- status: show the state of collectors that have no matrix row of their own (8b674af), closes #524
- telemetry: bound OTLP metric export batches (6b1093a), closes #494
- telemetry: stop identical target_info duplicating on every Prometheus scrape (844f267), closes #519
Refactoring¶
- catalog: delete pending_panel now that every signal has a panel (e726aad), closes #526
- config: extract the effective-config projection to a leaf package (0d31d9f)
- flowstore: rename flows.store.path to directory and surface backend health (5b25a5e), closes #294
- grafana: split the dashboard generator into builder, variables and tab modules (8f36ffd), closes #495
- grafana: split the flagship dashboard into a tailnet and a health artifact (372b169), closes #526
- objectstore: add provider-neutral ingestion engine (d701ebe), closes #453
- telemetry: freeze one Options seam per outstanding EPIC-04 child (1e63883)
Build System¶
3.0.0 (2026-07-25)¶
⚠ BREAKING CHANGES¶
- move the module path to /v3 and guard the next major
- flowlog: cardinality.flow.destination_service is removed and tailscale.dst.service is emitted unconditionally on both flow metric families. The rollup families already carried it ungated, so the toggle only ever governed the raw ones — the same dimension appeared or vanished with metrics_mode. Its value space is a fixed IANA registry rather than the ephemeral port range, so gating it bought little. An existing destination_service: in a config file is silently ignored (unknown YAML keys are); a stale TS2OTEL_CARDINALITY__FLOW__DESTINATION_SERVICE raises the unknown-variable advisory at startup. Deployments on metrics_mode all/both gain the label on tailscale.network.io/packets, which changes those series' identity.
- admin: pii_filter no longer applies to the /flows view or /api/flows.json. An operator who set e.g. pii_filter.emails: false previously saw no user attached to any flow on the admin page, and will now see them; the same holds for hostnames, tailscale_ips and external_ips. Exported telemetry is unchanged — the filter governs it exactly as before. The admin token is now the only control over who can read tailnet identity from this process: if the set of people holding it is wider than the set who may see your users' email addresses, set a narrower admin.auth.token or bind admin.listen to loopback.
- admin: with an empty admin.auth.token, the admin status page and its JSON APIs (/, /api/status.json, /api/cardinality.json, /api/config.json, /api/rdns/purge) now return HTTP 403 on any non-loopback admin.listen instead of serving unauthenticated. The default listen is the wildcard :9091, so a default deployment is affected. Set admin.auth.token (e.g. TS2OTEL_ADMIN__AUTH__TOKEN) or bind admin.listen to loopback. The process still starts, and /healthz and /readyz remain open on every bind, so container and Kubernetes probes are unaffected.
- stream: an enabled streaming receiver with an empty streaming.token on a non-loopback streaming.listen now refuses every request with HTTP 403 instead of accepting unauthenticated POSTs. Log ingestion stops until streaming.token is set (e.g. TS2OTEL_STREAMING__TOKEN) or the listener is moved to a loopback address. The default listen is the wildcard :8088, so a receiver previously running without a token is affected. A loud ERROR naming both remedies is logged at startup.
- config: a config with a polling flowlogs/auditlogs max_window that is positive and <= interval now fails startup validation instead of only warning.
- nodemetrics: two node_metrics static targets resolving to the same effective identity (same normalized URL and instance label) now fail config validation instead of being silently double-scraped.
- stream: a corrupt or partially undecodable stream batch is now rejected with a 4xx (sender retries) instead of being partially ingested and acknowledged 200. The valid-prefix salvage behaviour is removed.
- helm: Helm installs/upgrades with replicaCount != 1 now fail rendering instead of deploying multiple pollers.
Features¶
- aclpolicy: compile and evaluate a tailnet policy against observed flows (a0a986e), closes #237
- admin: built-in network flow visualiser at /flows (4427507), closes #237
- admin: emitted-throughput and collector-fleet trend charts (a1c1fe9), closes #223
- admin: enable admin server by default on :9091 (730d467)
- admin: identity views on /flows — tag matrix, split tags, identity on connections (dd81b6b), closes #237
- admin: show identity in full on /flows, unfiltered by pii_filter (b0616a9), closes #241 #237
- admin: the path-quality section on /flows (6037e1c), closes #237
- admin: the policy section on /flows (51937e3), closes #237
- app: add read-only cardinality and config JSON export endpoints (30d0672)
- app: build cardinality suite, collector freshness and API auth panels (372627f)
- app: extend status DTO for cardinality suite, freshness and API auth (71449f3)
- app: feed the ACL evaluator from the acl and users collectors (5587695), closes #237
- app: retain per-metric active-series history for cardinality growth view (d072aac)
- collector: track last successful run time for status freshness (13f60e4)
- config: add cardinality warning/critical thresholds and label-value sample cap (00b0a65)
- config: reject positive max_window <= interval for polling log collectors (376b47d), closes #202
- console: configurable status-page refresh interval (default 5s) (9b13a84), closes #215
- deploy: expose cardinality threshold + label-cap knobs in Helm chart (5991d21), closes #208
- flowlog: carry path, DERP region and identity on the rollup families (cb73daa), closes #243
- flowlog: decode embedded node identity for self-enrichment (8cb3f7b), closes #235
- flowlog: name IP protocol 99 tsmp and explain what a TSMP flow means (0971527), closes #249
- flowlog: reconcile each connection against the tailnet policy (c114f92), closes #237
- flowlogs: read the S3 export as a third ingestion source (a8ce1aa), closes #238
- flowstore: aggregate the policy verdict, unexplained relationships and rule use (ce15572), closes #237
- flowstore: bounded in-memory store of recent flow activity (cb40c29), closes #237
- flowstore: classify how each peer was actually reached on the wire (08d1724), closes #237
- pyroscope: collect all profile types by default incl. goroutine-leak (fec8915), closes #185
- stream: make HEC batch delivery atomic instead of ACKing partial loss (cfa330a), closes #201
- telemetry: capture bounded per-label distinct values and plumb the cap from config (c301413)
- ui: tabbed layout, light/dark theme, real charts, cardinality suite (55cc1e6), closes #208
Bug Fixes¶
- admin: record the fail-closed status page as a breaking change (5656149)
- admin: refuse the status page on a network-reachable bind with no token (effb816), closes #227
- alerts: page on tagged device key expiry only, not untagged user devices (15bf0ba), closes #250
- api: bound successful JSON responses before decoding (054ee09), closes #210 #211
- deps: update github.com/tailscale/hujson digest to 10d7940 (#213) (2a278df)
- deps: update github.com/tailscale/hujson digest to 78b5b16 (#225) (e38676c)
- deps: update module github.com/klauspost/compress to v1.19.1 (#216) (c8fe2f4)
- deps: update module github.com/prometheus/client_golang to v1.24.0 (#217) (a22617a)
- deps: update module github.com/prometheus/client_golang to v1.24.1 (#247) (10c5e01)
- deps: update module github.com/rknightion/tailscale2otel/v2 to v2.0.2 (#188) (9325849)
- deps: update module google.golang.org/grpc to v1.82.1 (#192) (6d9c74d)
- flowlog: omit absent flow endpoints instead of fabricating them (b6629a2), closes #236
- flowlog: read Tailscale's ":0" as the absent port it is (7d36026), closes #248
- flowlog: stop naming the DERP relay marker as a destination (2004791), closes #245
- flowlog: timestamp flow logs by window start, not capture time (a0cce89), closes #234
- flowstore: keep underlay ports out of the destination-services table (e8156bf), closes #246
- helm: re-sync the chart config block with the app's config surface (c817573), closes #242
- helm: reject any replicaCount other than 1 (93cb2d5), closes #203
- nodemetrics: key delta baselines by source series, not post-drop labels (b3217f6), closes #199
- pii: classify host:port IP values before falling back to hostnames (a206df4), closes #198
- stream: bound record count, unwrap depth and concurrent bodies; fail closed without a token (992d7f6), closes #209 #228 #229
- stream: derive the listener write window from the process deadline (f8dab4b), closes #232
- stream: record fail-closed receiver auth as a breaking change (cd90397)
- telemetry: apply the PII filter to span attributes (0550813), closes #212
- telemetry: drop service.version from the metrics resource (#187) (1658133)
- telemetry: give telemetry pipelines independent shutdown budgets (c7f4f1e), closes #204
- telemetry: redact PII from log bodies, not only attributes (5441abf), closes #197
- tsapi: bound OAuth/workload-identity token fetches through the body read (4d5afa1), closes #200
- tsapi: cap Retry-After backoff at the configured max_delay (d581993), closes #206
- webhook: reject signed timestamps too far in the future (94774c7), closes #205
Build System¶
2.0.2 (2026-07-14)¶
Bug Fixes¶
2.0.1 (2026-07-13)¶
Bug Fixes¶
2.0.0 (2026-07-13)¶
⚠ BREAKING CHANGES¶
- the telemetry attributes above (and their Prometheus label normalizations) are renamed with no compatibility window; update external queries per the docs/upgrading.md v2.0.0 table.
Features¶
- add -version and -validate flags to the release binary (86c2e35), closes #162
- align telemetry attributes with OTel semantic conventions (e59642d), closes #161
- auth: workload identity federation (auth.method: workload_identity) (d55341a), closes #168
- ci: report which live-contract ops actually ran (550f84d)
- collector: OAuth Apps collector + OpenAPI spec re-vendor (8f2c3ca), closes #167
- config: file-based secrets (*_file) for all credentials (a474fb9), closes #169
- deploy: alert + dashboard pack for the v2.0.0 program (25aa62b), closes #172
- devices: emit multipleConnections, blocksIncomingConnections, postureIdentity.disabled (e5551fc), closes #163
- devices: posture-attribute expiry telemetry (de0c50c), closes #164
- keys: key owner (userId) and auto-applied device tags (e548e5e), closes #165
- nodemetrics: curate key tailscaled client metrics into the named catalog (c362a92), closes #171
- security: fuzz the untrusted-input decoders, add a vuln-reporting policy (ba82856), closes #144
- services: resolve service-VIP flow peers to service names (f3669cd), closes #166
- TLS support for the admin and Prometheus listeners (63c02a1), closes #170
Bug Fixes¶
- ci: don't fail fuzz jobs on Go's benign -fuzztime shutdown race (c42b28d)
- ci: run the live API contract lane on ubuntu-latest (0acd799), closes #160
- deps: update module github.com/grafana/pyroscope-go to v1.4.1 (#142) (b7f83df)
- deps: update module github.com/klauspost/compress to v1.19.0 (#41) (15a754d)
- deps: update module google.golang.org/grpc to v1.82.0 (#42) (8abf4ce)
- renovate: stop raising invalid major bumps of tools/* indirect deps (688a7a6)
1.0.0 (2026-07-05)¶
⚠ BREAKING CHANGES¶
- v1.0.0 stabilises the public interface (config, metric names, HTTP endpoints, Helm values). There are no new breaking changes over 0.6.0; docs/upgrading.md carries the consolidated pre-1.0 to v1.0.0 migration notes for anyone upgrading from an earlier 0.x.
Features¶
- declare stable v1.0.0 release (eba5996)
0.6.0 (2026-07-04)¶
Features¶
- app,config: readiness, cache reuse, User-Agent, rate-limit visibility, secret headers + collector fixes (5d43509), closes #66 #76 #57 #85 #70 #79 #73 #61 #63 #67
- deploy: add fsGroup, extra volumes/mounts, and baseline alert rules (250b4c5), closes #82 #83 #123
- docs: align docs site with m7kni.io brand + server-side SEO/LLM metadata (77e7c4f), closes #46
- helm: add conditional liveness/readiness probes to deployment (3210c9b)
- telemetry: add GaugeSnapshot observable-gauge facade for churn-safe per-entity gauges (ac22409), closes #55
Bug Fixes¶
- app: emit enrich.cache_age at export time so staleness is detectable (e3ef49e), closes #108
- app: join receivers before shutdown; attribute tailnet client failures; static node_metrics once (f0e20d1), closes #53 #125 #59
- app: report dedup self-obs for every tailnet runtime, not just runtimes[0] (eb2700d), closes #60
- app: status page reads per-tailnet identity in multi-tailnet (list) mode (796c75b), closes #116
- app: stop double-counting self-obs under provider=headscale (543b336), closes #54
- auditlogs: include action/target in the grouped boundary-dedup key (47f0eb1), closes #97
- collector: checkpoint resilience + effective-store reporting + compile-time registry check (38dfcaa), closes #69 #105 #58
- collector: don't count shutdown cancellation as a collector scrape failure (0dc5ec0), closes #93
- collector: errors.As 403 classification (flowlogs) + Headscale adapter fidelity (3b4cbbb), closes #95 #64
- collector: posture-log PII routing, posture status.error signal, device tags on status page (6035361), closes #56 #99 #102
- collectors: migrate churning per-entity gauges to observable snapshots (fixes ghost series) (479575e), closes #55
- config: close validation gaps + backfill tailnet HTTP defaults (4781a88), closes #52 #104 #106
- config: headscale receiver guard/warnings + least-privilege tailnet OAuth scopes (45d73b8), closes #117 #127
- config: validate receiver paths, grpc endpoint shape, required tailnet; align Helm defaults (030b185)
- deploy: correct broken PromQL in shipped alerts + flagship dashboard (08d0b87), closes #107 #109 #110 #111
- deps: update module github.com/grafana/pyroscope-go to v1.4.0 (#45) (be6e1d9)
- ingestion: bound wire-derived metric attribute values (audit action/origin, flow proto) (742e6c1), closes #77
- nodemetrics: bound per-tick scrape time (worker pool + interval deadline) (ff47ce3), closes #80
- nodemetrics: stable, batch-independent instance-label disambiguation (403dd98), closes #98
- pii: register user identity keys so per-user gauges suppress instead of collapsing (7126f31), closes #74
- rdns: enforce cache bound under concurrency + fix Close()/LookupName WaitGroup race (ec63303), closes #118 #121
- rdns: pick PTR name deterministically to stop flow-metric label flap (158b29f), closes #119
- security/telemetry: OTLP skip-verify knob, scrub lab identifiers, correct stale comments/descriptions (33942fe), closes #94 #89 #51 #65 #68
- stream: salvage the valid decoded prefix from a corrupted HEC batch (829c09a), closes #96
- telemetry: stop /metrics 500 on tailnet_name=false; classify instrument-name errors; guard const-attr collisions (16246da), closes #103 #91 #62
- tsapi: bound the OAuth token fetch so a hung refresh can't stall collectors forever (086c9b5), closes #84
- tsapi: tolerate empty device timestamps; fix ServiceHost stableNodeID tag (bb4d575), closes #48 #72
Performance¶
- telemetry: alloc-free label-collision fast path; harden portservice gen; document Headscale (4984ad6), closes #86 #128 #71
0.5.0 (2026-06-26)¶
Features¶
- app: auto-resolve tailnet name from the "-" placeholder (f660faa)
- ci: adversarial Tailscale API drift detection suite (e1e5e20)
- metrics: add opt-in Prometheus /metrics pull endpoint (e63e4b0)
- telemetry: emit tailnet/provider as signal attributes, off the Resource (6cfbb52)
Bug Fixes¶
- app: hostname-free instance ID under pii_filter; validate and clamp OTLP metric interval (81accad)
- audit: bound audit-change metric labels; keep identifiers out of ACL/key log bodies (21cd0f9)
- ci: vendor OpenAPI spec to committed spec/ baseline (drift lanes need it in CI) (4f5f665)
- config: redact Secret under JSON/YAML marshaling + permissions/cardinality advisories (82d620d)
- grafana: query tailnet/provider as direct labels, drop target_info joins (78b80a0)
- helm: never render empty secret keys; serve multi-tailnet config from a Secret (chart 0.7.3) (bffe3f1)
- http: bound request/response lifetimes on the admin and metrics servers (f5a3340)
- lint: suppress SA5011 false-positive on t.Fatal nil-guards in tests (15a3096)
- nodemetrics: restrict discovery to Tailscale address ranges and cap delta baselines (cc990fb)
- telemetry: respect pii_filter.tailnet_name on universal const attrs; cap collision diagnostics (79a35a7)
- tsapi: elide variable path segments from API endpoint labels (91ef35a)
- tsapi: keep OAuth token-endpoint response bodies out of traces and status (d4276a5)
Performance¶
- telemetry: drop exemplar reservoirs for synchronous non-histogram instruments (c31d7ba)
0.4.0 (2026-06-08)¶
Features¶
- app: multi-tailnet/MSP via per-tailnet OTEL providers (6648327)
- pii: configurable redaction filter + identifier backfill (J+K) (8ed3ede)
- provider: add Headscale control-plane provider (a5e48a4)
- telemetry: OTLP export-duration self-observability histogram (C2) (0ff4437)
- viz: drain dashboard/alert backlog — panels, PII rendering, multi-tailnet, taxonomy (096ebec)
Refactoring¶
- logs: keep redactable PII identifiers out of log bodies (dfe001a)
0.3.0 (2026-06-07)¶
Features¶
- acl: policy risk-scoring gauges (wildcard/unrestricted/autoapprover/ssh/posture) (de8100c)
- audit: curated security/lifecycle change counter + device churn (98bcc48)
- collector: per-collector scrape staleness + budget-headroom gauges (f43fdd8)
- devices,flowlogs: connectivity quality + exit-node/subnet-router analytics (B3+B4) (f58b73b)
- devices: fleet hygiene roll-ups (untagged/ephemeral/version/tag distributions + key-expiry histogram) (da158e3)
- devices: inventory outstanding device-share invites (5bdfa85)
- dns: unified DNS configuration with override-local + per-resolver exit-node visibility (b51b5dc)
- keys: inventory OAuth clients & API tokens via the unified key model (4a8a3f7)
- selfobs: API request latency histogram (api.duration) (756b042)
- selfobs: ingestion volume + OTLP export-cost self-observability (C8) (d517fa0)
- selfobs: receiver in-flight/duration, dedup hits, checkpoint/process/config health (C6/C7/C9) (e09ffcc)
- telemetry: cardinality headroom — series.limit + series.overflowing self-obs gauges (be7be05)
- telemetry: OTEL traces pillar — scrape/API/receiver spans + exemplars (e8b78ee)
- version: self update-available + device version-skew via shared release fetcher (02a47d1)
Bug Fixes¶
- docs: remove glightbox slide_effect option (rejected by zensical 0.0.44) (5083835)
- keys: correct stale docs and keys-by-type dashboard aggregation (b9420c9)
- selfobs: drop unnecessary int64 conversion in tvToSeconds (unconvert) (012307f)
0.2.0 (2026-06-06)¶
⚠ BREAKING CHANGES¶
- config: restructure schema, env-driven loader, generated env-var reference
- node-metrics series now carry the scraped node's identity on the
tailscale_nodelabel instead ofinstance(which on Grafana Cloud always held the collector host); update node-metrics dashboards/queries accordingly. The per-device posture log now defaults to on-change; set
Features¶
- admin: add status landing page, JSON API endpoint, and opt-in profiling (pprof + Pyroscope) (282a333)
- admin: authenticate status page + pprof with a shared token (bbfea01)
- admin: per-collector info tooltip on status page (5bfd025)
- alerts: add Grafana-managed alert + recording rules (a49dab0)
- app: derive overall health + enrich collector status rows (e3f86b8)
- app: redesign admin status page — health, sparklines, API panel, live tables (e7a26d5)
- app: sample runtime/cardinality trends for status sparklines (b03d4a1)
- app: start the series.active cardinality reporter, gated by self-obs (a9db840)
- app: surface per-endpoint API health and window checkpoint state (66359f6)
- app: tag subsystem loggers with component for per-subsystem filtering (da75818)
- app: wire dynamic node-metrics discovery from the devices API (3900f89)
- app: wire node-metrics passthrough filters into nodeMetricsOptions (1c42f81)
- bounded top-N flow-metric rollups (default) with other + unique counts (d8bcbb8)
- cardinality cap, stream feature.enabled, posture metric, node-label fix (d3e5494)
- cardinality: per-entity gauge toggles for devices/users/keys (389352f)
- collector: track per-collector run history and consecutive failures (4f7e5ca)
- config: add node_metrics.discovery schema (7b29868)
- config: document new collectors + cardinality toggles (config + Helm chart) (fb55c8c)
- config: redact credential fields via a Secret type (987de8f)
- config: restructure schema, env-driven loader, generated env-var reference (0891d26)
- config: warn on undefined ${ENV} references at load (d10b3cb)
- contacts: add tailnet contact verification collector (9ddbc66)
- devices: add tailnet-lock errors + per-DERP-region rollup (dbbcd19)
- devices: add tailscale.tags label to per-device gauges (3c8c5d1)
- devices: expose MDM/posture attributes as queryable metrics (e3eb199)
- flow-log service-name mapping, independent port toggles, external reverse-DNS (0835122)
- grafana: add Cardinality & Cost tab (1a93a1e)
- grafana: add comprehensive v2-schema multi-tab dashboard (generated) (843f1e0)
- grafana: add DERP-vs-direct connection-path row to Node Metrics tab (0a47685)
- grafana: add Security & Audit tab (027c9fb)
- grafana: add tag filter and Devices-by-tag panel to Fleet tab (ce86f71)
- grafana: dashboard coverage for new collectors (3131e672+) (ec527f6)
- grafana: surface alloc churn, heap objects, GC next-target in Diagnostics (e4c52f1)
- helm: expose collectors.devices.attribute_namespaces (1dfa89e)
- logstream: add log-stream delivery-health collector (a0b259b)
- nodemetrics: add metric_allow/metric_deny/drop_labels passthrough filters (603790c)
- nodemetrics: emit discovery-health gauges (cbb4831)
- nodemetrics: support dynamic target discovery (1b86831)
- posture: add device-posture integration sync-health collector (3131e67)
- rdns: observability, purge control, and larger defaults for the PTR cache (a8b8867)
- ringbuf: add generic thread-safe bounded ring buffer (14c01c7)
- selfobs: add runtime, dedup, and component-error self-observability metrics (b0fa95f)
- services: add Tailscale Services (VIP) collector (30900f4)
- settings: surface httpsEnabled, aclsExternallyManaged & external-tailnets role (667e4e7)
- telemetry: add tailscale2otel.series.active cardinality self-metric (918ca76)
- tsapi: add equal-jitter to retry backoff (62f73ca)
- tsapi: decode per-device tags from /devices?fields=all (6e7906a)
- tsapi: honor HTTP-date form of Retry-After (8e0ce6e)
- tsapi: per-attempt timeout so long Retry-After is honored (85c3584)
- tsapi: rate-limit retries, not just first attempt (87107a1)
- tsapi: status-aware retry logging (429 INFO, 5xx DEBUG, 401 ERROR) (65403c8)
- tsapi: widen request hook to RequestInfo (latency + error) (4d89430)
- webhooks: add webhook-endpoint inventory collector (8931eb9)
Bug Fixes¶
- app: don't log receiver clean shutdown as ERROR (0db54c8)
- ci: authenticate cosign to ghcr.io before signing the chart (c363142)
- ci: bump Go to 1.26.4 to clear govulncheck stdlib findings (5345bce)
- ci: bump tool modules to go 1.26.4 to match root module (50cb7db)
- ci: clear govulncheck stdlib findings + fix broken action versions (62ace00)
- ci: cosign snapshot image digest (#12) (5bf2fa0)
- ci: make snapshot chart prerelease version valid SemVer (ba12049)
- ci: pin cosign installer action (#10) (8ae03eb)
- ci: pin cosign-installer to @v3 (no moving v4 tag exists) (37c9f7f)
- ci: pin cosign-installer to @v4.1.2 (required for cosign v3+) (0bf6156)
- ci: rename helm-values-schema-json input -> values (0a0b900)
- ci: use correct losisin/helm-docs-github-action@v2 repo (2680758)
- collector: run first collector tick promptly at startup (2c72ee3)
- config: scope the undefined-${ENV} advisory to active config values (d6809f8)
- deps: update github.com/tailscale/hujson digest to ecc657c (d9843a0)
- docker: copy per-platform binary in dockers_v2 multi-arch build (f780ca5)
- docs: redact live tailnet recon details from tracked files (5ded0e6)
- flowlog: bound rollup accumulator memory between flushes (629b111)
- grafana: correct policy/config, network & diagnostics panels (4bfd717)
- grafana: show 0 not "No data" for empty audit-count stats (a0c26a2)
- grafana: stabilize panels across redeploys (strip service_version) (2224bce)
- guard main snapshot publishing (44ee52e)
- helm: disable ServiceAccount token automount by default (289a0fd)
- nodemetrics: bound discovered scrape work (2770030)
- nodemetrics: unique short MagicDNS instance labels + collision guard (f578e54)
- reserve node metrics identity label (#16) (d439c38)
- restrict main snapshot publishing to main ref (1e58858)
- security: harden receivers, scraper, TLS, and Helm from security review (b743858)
- selfobs: guard cardinality reporter against non-positive interval to prevent panic (cf1d7f4)
- stream: cap zstd decoder back-reference window at the body limit (bfde16b)
- telemetry: drop OTLP→Prometheus colliding labels and log export errors (874cf1b)
- telemetry: stop emitting redundant service.version on build_info (d82d71d)
- webhook: bound request bodies pre-auth and add server timeouts (92348f4)
- webhook: stop user cross-dedup over-suppressing distinct changes (D11) (75a2c98)
- webhook: wire replay-protection tolerance from config (default 5m) (7ce9cf6)
Performance¶
- telemetry: disable unused metric exemplars, add GC tuning knobs (5e6fce3)
Refactoring¶
- config: remove dead oauth token_url field (d21f11c)
- config: remove legacy cardinality.flow_include_ports toggle (6bc1a56)
- tsapi: use min() in computeBackoff (3e58f5f)