BREAKING CHANGE: upgrades the HTTP framework from gofiber/fiber/v2 to gofiber/fiber/v3, and gofiber/websocket/v2 to gofiber/contrib/v3/websocket.
- Handlers now take fiber.Ctx (interface) instead of *fiber.Ctx. - DisableStartupMessage moved from fiber.Config to fiber.ListenConfig on the proxy/api/monitoring Listen calls. - cors AllowOrigins is now []string; c.BodyParser -> c.Bind().Body(). - app.Test takes fiber.TestConfig instead of an int timeout (tests updated). - WebSocket swapped to contrib/v3/websocket (same Conn/New/Config/IsCloseError/IsWebSocketUpgrade API; Conn.Query preserved). - Adopts fasthttp v1.71.0 (pulled by fiber v3), resolving the v1.71 Host-header enforcement that broke the prior pinned-v1.69 workaround.
fix(connpool): the background keep-alive goroutine no longer reads the mutable global cfg (captures HostGraphQL/HealthcheckGraphQL at pool creation). Under v3 timing it raced with parseConfig/test cfg reassignment; go test -race ./... is now clean (0 data races).
test: make the circuit-breaker cache-fallback and request-coalescing integration tests deterministic (cache TTL outlives the retry loop; coalescing asserts against a measured single-request baseline instead of a hard-coded count); drop the flaky timing-ratio assertion in TestTimingAttackResistance (constant-time guarantee comes from subtle.ConstantTimeCompare, not wall-clock timing).
Verified: go build, go vet, golangci-lint (0 issues), go test -race ./... (all packages pass, 0 races), govulncheck (no vulnerabilities). App + dashboard + WebSocket verified live under v3 in single-node and cluster modes.
Bump golang.org/x/net v0.52.0 -> v0.56.0, fixing GO-2026-5026 (idna Punycode label rejection) and GO-2026-4918 (HTTP/2 transport infinite loop). govulncheck now reports no vulnerabilities. Also bumps x/sync, x/sys, x/term, x/text, otel v1.43->v1.44, grpc v1.80->v1.81 and genproto.
Hold github.com/valyala/fasthttp at v1.69.0: v1.71.0 changes request handling such that the API auth/integration security suites fail (app.Test errors on benign requests), violating the behaviour-preserving upgrade rule. fasthttp had no flagged vulnerability, so pinning it back loses no security fix. Adopting v1.71.0 needs separate investigation.
Verified: go build, go vet, golangci-lint, go test -race ./... all pass; govulncheck clean.
Starting with ENABLE_CIRCUIT_BREAKER=true panicked at boot: parseConfig -> initCircuitBreaker registers a metrics gauge, but cfg.Monitoring is assigned later by StartMonitoringServer, so the registration dereferenced a nil *MetricsSetup.
Add nil-receiver guards to the MetricsSetup registration methods (RegisterMetricsGauge/GaugeFunc/Counter, RegisterFloatCounter, RegisterMetricsSummary/Histogram), matching their existing 'return a dummy to prevent panics' contract. The guard is a no-op for non-nil receivers, so existing callers are unaffected. The breaker and the admin dashboard (which reads gobreaker state directly) keep working.
Add regression tests for the nil-receiver methods and for initCircuitBreaker with nil monitoring.
RecordRequest() only ran inside proxyTheRequest, but cache hits return from handleCaching before reaching it. As a result the dashboard's current RPS read 0 whenever traffic was served from cache (e.g. a repeated query at 100% hit rate). Record the request on the cache-hit branch too; misses and proxied/GET requests still record in proxyTheRequest, so there is no double counting.
Verified: 100% cache-hit load now reports ~16-20k req/s instead of a flat 0.
Replace the AI-slop visual (indigo->purple gradient, glassmorphism, uniform rounded cards, hover-lift) with a deliberate warm-paper 'instrument panel': monospace tabular telemetry, GraphQL brand magenta accent, flat hairline cards, real type hierarchy, WCAG-AA contrast, focus-visible, prefers-reduced-motion and aria-live status. No new font/CDN deps.
Make the cluster-view toggle functional: the WebSocket stats stream now honours a ?view=local|cluster query param, so toggling streams this-node-only vs aggregated metrics instead of being cosmetic (the stream previously always sent cluster-aware data when an aggregator existed). The toggle is always visible -- disabled with a 'single node' hint when Redis cluster mode is off -- so it is discoverable.
Fix cluster-mode rendering bugs: derive backend health from healthy/total instances (health card no longer stuck on 'Loading'), show 'n/a' for Redis memory instead of a misleading 0 MB, render aggregated CB/retry/coalescing/connections on the polling path too, and surface the proxy version and backend-health detail.
Tests assert the served dashboard against stable markers instead of the cosmetic page title.
The repo's go.mod has required go 1.25.0 since the perf+coverage pass,
but the release workflow still pinned setup-go to 1.24 — the latest
1.24.X tool refuses to compile a 1.25 module with GOTOOLCHAIN=local,
breaking auto-release on every push.
The released v0.45.1 binary shipped with the source default
appVersion="dev" because .goreleaser.yaml had ldflags="-s -w" only,
so every startup ping was rejected by the receiver with HTTP 400
(invalid version: regex requires leading digit).
Two-layer fix:
1. .goreleaser.yaml now passes -X main.appVersion={{.Version}} so
goreleaser-built binaries report the actual release version.
2. Switch to telemetry.SendForModule which prefers
debug.ReadBuildInfo Main/Deps when available, falling back to
appVersion. This means `go install github.com/lukaszraczylo/
[email protected]` users also get correct versions
without relying on the ldflag.
Bumps oss-telemetry to v0.2.1 for SendForModule.
Discloses the single anonymous adoption ping sent on startup and points
users to the upstream README section for full opt-out instructions
instead of duplicating the table here.
Send a single fire-and-forget ping at startup to help track adoption
and version spread. No persistent identifiers are collected.
Adds main.appVersion var (defaulting to "dev"); wire ldflags
(-X main.appVersion=$VERSION) to populate it at release time.
Opt out via any of:
DO_NOT_TRACK=1
OSS_TELEMETRY_DISABLED=1
GRAPHQL_MONITORING_PROXY_DISABLE_TELEMETRY=1