Skip to content

v1.12.9

Choose a tag to compare

@juicycleff juicycleff released this 16 Oct 01:52
· 35 commits to main since this release

Forge Framework v1.12.9 (2026-10-16T01:43:52Z)

Welcome to this new release of Forge Framework!

Changelog

New Features

  • 64bbf0a: feat(cli): add forge dev --observability to send an app's telemetry to the local stack (@juicycleff)
  • c5ad464: feat(cli): add forge observability up, down, status and export (@juicycleff)
  • a822add: feat(cli): export the Forge Service dashboard and rules for your own Grafana (@juicycleff)
  • ffab61d: feat(cli): generate the Grafana stack's provisioning and scrape targets (@juicycleff)
  • a6c2f43: feat(cli): render the Forge Service dashboard and Prometheus alert rules (@juicycleff)
  • ddfe4f1: feat(cli): run the grafana/otel-lgtm stack as one long-lived container (@juicycleff)
  • 8d2247e: feat(conduit): add a leased service registry to Redis Streams (@juicycleff)
  • 103030f: feat(conduit): add a leased service registry to the PostgreSQL provider (@juicycleff)
  • 41ac764: feat(conduit): add consumer controls and backfill to Redis Streams (@juicycleff)
  • 6d76b8d: feat(conduit): add consumer controls and backfill to the PostgreSQL provider (@juicycleff)
  • 26852dc: feat(conduit): add dead letters and retention to the PostgreSQL provider (@juicycleff)
  • 4c2bb0e: feat(conduit): add request and reply RPC to Redis Streams (@juicycleff)
  • 54717e4: feat(conduit): add request and reply RPC to the PostgreSQL provider (@juicycleff)
  • 5c54cba: feat(conduit): add the PostgreSQL provider's schema and streams (@juicycleff)
  • c70a094: feat(conduit): carry trace context in envelope headers from prepare to handler (@juicycleff)
  • 49b999b: feat(conduit): deliver PostgreSQL messages in commit-safe order (@juicycleff)
  • d612aae: feat(conduit): log PostgreSQL listener outages (@juicycleff)
  • f7b2dcb: feat(conduit): publish to PostgreSQL with transactional wakeups (@juicycleff)
  • 4222652: feat(conduit): read PostgreSQL messages after a position (@juicycleff)
  • 05e4a48: feat(conduit): repair a restored PostgreSQL database with Rebase (@juicycleff)
  • 39ee763: feat(dashboard): add a span processor that feeds the trace store from OTel spans (@juicycleff)
  • d054454: feat(dashboard): feed the trace viewer from the app's OTel spans (@juicycleff)
  • 70b31c7: feat(deploy): accept an observability block on kubernetes targets (@juicycleff)
  • 8aef1f9: feat(deploy): render ServiceMonitors and OTEL_* env for kubernetes observability (@juicycleff)
  • f326f24: feat(events): trace events from publish to handler and switch to semconv durations (@juicycleff)
  • 8836a2a: feat(extensions): read the config file in features and auth (@juicycleff)
  • 61034d4: feat(extensions): use snake_case config keys in mcp, cache and security (@juicycleff)
  • 04dd2c1: feat(grpc)!: record rpc.server.call.duration in place of the grpc_* series (@juicycleff)
  • c96d1d9: feat(grpc)!: start the server at the end of app.Start so other extensions can register (@juicycleff)
  • acf3cd3: feat(grpc): register app services with WithService and WithServiceRegistrar (@juicycleff)
  • d6d69b8: feat(grpc): report checker changes from health Watch and statuses from List (@juicycleff)
  • 6a83e26: feat(grpc): trace outbound gRPC calls from conduit and ClientDialOptions (@juicycleff)
  • 78e33f3: feat(grpc): trace served calls with otelgrpc and put trace IDs on the log context (@juicycleff)
  • e275ff3: feat(kafka): trace records from send to handler and record semconv durations (@juicycleff)
  • 3f0b55a: feat(metrics)!: semconv HTTP server metrics replace the unlabelled forge_http series (@juicycleff)
  • d463379: feat(metrics)!: stream connection metrics, with stream routes timed by their handshake (@juicycleff)
  • c143e1f: feat(metrics): add an OTLP producer over the registry stream (@juicycleff)
  • 54cf85c: feat(metrics): cap series per metric and register WithLabels children (@juicycleff)
  • 103a23d: feat(metrics): export semconv names unprefixed with unit suffixes and exemplars (@juicycleff)
  • fb16bb2: feat(metrics): label vectors for custom metrics (@juicycleff)
  • 0f36f31: feat(metrics): let the collector hand out an OTLP producer (@juicycleff)
  • 78fdb85: feat(metrics): push Go and process collector families with their scrape names (@juicycleff)
  • 2b0990e: feat(metrics): push metrics over OTLP when an endpoint is configured (@juicycleff)
  • b589d88: feat(metrics): report delta temporality from the OTLP producer (@juicycleff)
  • 0276c4b: feat(metrics): semconv HTTP server metrics keyed by matched route (@juicycleff)
  • bf818fb: feat(profiling): push profiles to Pyroscope through grafana/pyroscope-go (@juicycleff)
  • 646cf80: feat(profiling): resolve profiling config from code, forge config and PYROSCOPE_* env (@juicycleff)
  • 35e5019: feat(queue): trace messages from publish to handler and record messaging durations (@juicycleff)
  • 7c4648b: feat(router): mark stream routes established after upgrade or first flush (@juicycleff)
  • ab7a043: feat(router): record 5xx errors and recovered panics on the request span (@juicycleff)
  • 05ea988: feat(router): report a stream route's kind and establishment to outer middleware (@juicycleff)
  • afa7096: feat(router): report stream open, close and messages to a stream observer (@juicycleff)
  • 325bb6d: feat(router): report the matched route pattern to outer middleware (@juicycleff)
  • 724272e: feat(shared): report the matched route through RouteMatch.OnMatched (@juicycleff)
  • 258dc92: feat(telemetry): OTLP/HTTP tracer provider with rate-limited export errors (@juicycleff)
  • 68dc4e2: feat(telemetry): instrumented outbound HTTP client and transport (@juicycleff)
  • 8246fed: feat(telemetry): label sampled requests with span_id and span_name for the CPU profiler (@juicycleff)
  • ba6f9c6: feat(telemetry): push metrics over OTLP/HTTP from a private meter provider (@juicycleff)
  • 3efb70a: feat(telemetry): resolve OTLP metrics export settings from code, config and env (@juicycleff)
  • 781a643: feat(telemetry): resolve tracing config from code, file and OTEL env (@juicycleff)
  • f168762: feat(telemetry): server span middleware named after the matched route (@juicycleff)
  • 7311718: feat(telemetry): shared resource and parent-based sampler (@juicycleff)
  • e3a2f7f: feat(tracing): add the messaging package and trace context helpers for message headers (@juicycleff)
  • a9f80f8: feat(tracing): always sample lifecycle roots and let processors ask for unsampled spans (@juicycleff)
  • 1f45347: feat(tracing): trace extension register, start and stop (@juicycleff)
  • f9f3148: feat: histogram units in HistogramOpts and span ID log helpers in forge (@juicycleff)
  • 2c9d05c: feat: push profiles to Pyroscope and link sampled spans to their CPU profile (@juicycleff)
  • 117182f: feat: trace every request and export over OTLP when an endpoint is set (@juicycleff)

Bug Fixes

  • f9ddbb4: fix(cli): catch ports Docker Desktop holds and clean up after a failed stack start (@juicycleff)
  • c8f5fcc: fix(cli): find grove's migrations when central migrations are on (@juicycleff)
  • 71de4a6: fix(cli): keep metrics on the scrape path when forge sends traces to the stack (@juicycleff)
  • 0473f1c: fix(cli): let forge dev --docker build projects with local replaces (@juicycleff)
  • b0f1622: fix(cli): pin streaming client generator fixes (@juicycleff)
  • a070a2e: fix(cli): pin the forge release with nullable array item types (@juicycleff)
  • 97938c1: fix(cli): point the busy-port hint at forge obs up (@juicycleff)
  • 62ab4f4: fix(cli): wire forge dev --docker -O to the stack over a shared docker network (@juicycleff)
  • a52b18c: fix(client): preserve streaming protocols and omit unused helpers (@juicycleff)
  • ffe531f: fix(conduit): accept pool settings in the PostgreSQL listener URL (@juicycleff)
  • 020f0ae: fix(conduit): back off PostgreSQL re-polls while a transaction holds the horizon (@juicycleff)
  • 4ab0246: fix(conduit): back off a PostgreSQL listener whose connection keeps dropping (@juicycleff)
  • 70cb250: fix(conduit): bound the PostgreSQL backlog window in the index scan (@juicycleff)
  • 72afed7: fix(conduit): close PostgreSQL replay, stale reply and empty subject gaps (@juicycleff)
  • a411066: fix(conduit): fail loudly when a PostgreSQL cursor is ahead of the cluster (@juicycleff)
  • 16485af: fix(conduit): give a retried PostgreSQL RPC its own reply (@juicycleff)
  • 66854d0: fix(conduit): keep automatic discovery and RPC choices working on upgrade (@juicycleff)
  • c8cfb1b: fix(conduit): keep the app's notification handler off the PostgreSQL listener (@juicycleff)
  • 7afd612: fix(conduit): leave the memory provider out of automatic RPC selection (@juicycleff)
  • 6aefa96: fix(conduit): let the PostgreSQL listener connect to a direct URL (@juicycleff)
  • e699e92: fix(conduit): migrate PostgreSQL without the database CREATE privilege (@juicycleff)
  • d68aa70: fix(conduit): order PostgreSQL delivery by transaction ID, not its text (@juicycleff)
  • 80d916b: fix(conduit): prune only below the visibility horizon (@juicycleff)
  • 2ca61cc: fix(conduit): reject a conflicting PostgreSQL backfill before claiming it (@juicycleff)
  • f3917e5: fix(conduit): repair start snapshots and reroute Redis requests from closing servers (@juicycleff)
  • 59cb9cd: fix(conduit): report a Redis read that hits the caller's deadline as a deadline (@juicycleff)
  • 0ce2989: fix(conduit): report the whole PostgreSQL listener outage and skip its PG13-only test (@juicycleff)
  • d4987f1: fix(conduit): route Redis RPC replies to the call that sent them (@juicycleff)
  • 2f80c1e: fix(conduit): serve every Redis RPC procedure from one reader (@juicycleff)
  • 07df295: fix(conduit): skip PostgreSQL DDL when the schema is current (@juicycleff)
  • cc31742: fix(conduit): stop Redis RPC from starting a reply reader after Close (@juicycleff)
  • 9cc08fb: fix(conduit): stop idle PostgreSQL subscribers from busy polling and pinning the horizon (@juicycleff)
  • 77de49c: fix(conduit): sweep every aged-out PostgreSQL message on each pass (@juicycleff)
  • 0b2f776: fix(conduit): track pruned positions so a read after one is never wrongly resumable (@juicycleff)
  • 6ad41dd: fix(conduit): wake only the PostgreSQL caller a reply belongs to (@juicycleff)
  • 40d916a: fix(conduit): walk large PostgreSQL backlogs in bounded windows (@juicycleff)
  • 79f6e9f: fix(config): ignore config values that don't convert and log a warning (@juicycleff)
  • 69857c6: fix(config): let an option set a field to its zero value (@juicycleff)
  • eb8f1c6: fix(config): let config files override extension defaults (@juicycleff)
  • eb2d938: fix(dashboard): read the stream broker atomically and register the span processor last (@juicycleff)
  • c2d6c33: fix(dashboard): stop GetTrace writing shared spans and add an exchange side channel (@juicycleff)
  • c8dff6f: fix(deploy): find the ServiceMonitor API through discovery instead of reading CRDs (@juicycleff)
  • fa11e8f: fix(grpc)!: fail Start when TLS is on and the credentials don't load (@juicycleff)
  • 92adeee: fix(grpc): drop the server when Start fails to listen (@juicycleff)
  • 977f62f: fix(grpc): keep services registered before Start (@juicycleff)
  • d03e129: fix(grpc): put trace_id and span_id on the server's own log lines (@juicycleff)
  • f867897: fix(grpc): register the example's services before the server starts (@juicycleff)
  • ca6120b: fix(grpc): stop GracefulStop deadlocking on calls in flight (@juicycleff)
  • 70c8fbf: fix(health): stop doubling the forge_ prefix and give durations seconds buckets (@juicycleff)
  • b4c986b: fix(kafka): inject the async send span's context into the record (@juicycleff)
  • 502586c: fix(kafka): send the headers and timestamp SendMessages was dropping, add ctx-aware calls (@juicycleff)
  • 0b29c58: fix(kafka): skip telemetry for an empty batch, bound conduit tracing test waits (@juicycleff)
  • 2979f1b: fix(metrics): ask go-utils for timer quantiles as fractions (@juicycleff)
  • 0eedc90: fix(metrics): count Winsock resets as a client leaving on Windows (@juicycleff)
  • e4b0835: fix(metrics): count a write to a vanished stream client as a clean close (@juicycleff)
  • 4e3a215: fix(metrics): honour limits.max_metrics and warn once when it is reached (@juicycleff)
  • 416df98: fix(metrics): keep a cut-short OTLP produce from letting a colliding series flip owner (@juicycleff)
  • e7cf20d: fix(metrics): keep series state when a producer walk is cut short (@juicycleff)
  • 2b42bc0: fix(metrics): let the config file change metrics defaults when code sets none (@juicycleff)
  • 4ebe8ce: fix(metrics): record only the handshake of a stream route as an HTTP request (@juicycleff)
  • 34a74a8: fix(metrics): record stream connections when HTTP metrics are off (@juicycleff)
  • eec946f: fix(metrics): settle OTLP series collisions and bucket edge cases before touching state (@juicycleff)
  • a7cfa59: fix(metrics): start the collector from app.Start and export host series with labels (@juicycleff)
  • 7cc7cca: fix(middleware): keep context values in the handler behind Compress (@juicycleff)
  • 00e97a4: fix(profiling): cap the final upload at 5 seconds and clean tag values (@juicycleff)
  • 6d8c62e: fix(router): cap WebTransport uni streams with MaxUniStreams (@juicycleff)
  • ce4850f: fix(router): close streams before reporting them closed and guard nil observer handles (@juicycleff)
  • bf128d7: fix(router): deprecate WebTransportConfig.EnableDatagrams (@juicycleff)
  • 9122add: fix(router): don't let a stalled socket hold up the shutdown drain (@juicycleff)
  • 8517d90: fix(router): end open streams when a graceful shutdown starts (@juicycleff)
  • a49f64b: fix(router): enforce WebTransportConfig.MaxDatagramFrameSize (@juicycleff)
  • 759bd5c: fix(router): keep WebTransport stream JSON values apart on read and write (@juicycleff)
  • d59f6f9: fix(router): let handlers read what middleware stores with ctx.Set (@juicycleff)
  • 1d52782: fix(router): make WebTransport upgrades work on forge's HTTP/3 server (@juicycleff)
  • efb2a6c: fix(router): refuse a nil middleware when you register it (@juicycleff)
  • c96a107: fix(router): serve "/" when you mount a handler at the root (@juicycleff)
  • 0929de5: fix(scheduler): keep a panicking panic handler from taking the process down (@juicycleff)
  • c316528: fix(scheduler): report recovered job panics with the job name and stack (@juicycleff)
  • 6fb5a7a: fix(system): validate filesystem counters before calculating disk usage (@juicycleff)
  • 36effde: fix(telemetry): drop stream kind from rejected upgrades and skip excluded paths (@juicycleff)
  • c75cd99: fix(telemetry): end a stream route's span at the handshake (@juicycleff)
  • 10e1b87: fix(telemetry): keep nested dispatch off the outer span and propagate when disabled (@juicycleff)
  • f6a8d67: fix(telemetry): push metrics only while the app runs, from Start to Stop (@juicycleff)
  • 5e2623e: fix(telemetry): reject NaN sample ratios and keep literal plus in header values (@juicycleff)
  • bbb8ff6: fix(telemetry): reject OTLP endpoints that are not http or https URLs (@juicycleff)
  • 296c8f6: fix(telemetry): trim OTLP endpoint env, copy headers and only warn when metrics push is on (@juicycleff)
  • 94169ce: fix(telemetry): warn when tracing config can't be read (@juicycleff)
  • 9bf4159: fix(tracing): let errors.Is reach a panicked error value (@juicycleff)
  • 23956ac: fix: bumped confy version (@juicycleff)
  • 73b7d2f: fix: fixed confy config bug (@juicycleff)
  • 73ac884: fix: fixed forge cli version (@juicycleff)

Performance Improvements

Refactoring

  • 364e9db: refactor(consensus)!: remove the unused TracingManager (@juicycleff)
  • 00d4b26: refactor(events): delete the bus worker pool that nothing ever fed (@juicycleff)
  • c13b722: refactor(logger): share the rate-limited warn logger tracing uses for export errors (@juicycleff)
  • 786e126: refactor(metrics)!: delete the StatsD and Influx formatters (@juicycleff)
  • 9591a16: refactor(metrics): read custom collector values in one place (@juicycleff)
  • 5fa4b1b: refactor(telemetry): remove the unused observability package and Jaeger exporter (@juicycleff)

Documentation Updates

  • 2149cbb: docs(changelog): update CHANGELOG.md for v1.12.8 (@github-actions[bot])
  • 479f075: docs(cli): document forge observability and the deploy observability block (@juicycleff)
  • 1c53cdb: docs(cli): note the stack's docker network in llm.txt (@juicycleff)
  • b6bdf48: docs(conduit): clarify RPC connections, Rebase limits and benchmark data (@juicycleff)
  • 946f198: docs(conduit): correct provider guarantees and PostgreSQL operations notes (@juicycleff)
  • 7f49963: docs(conduit): document PostgreSQL and the providers at JetStream parity (@juicycleff)
  • da0efc7: docs(conduit): fix the restore repair and provider wording (@juicycleff)
  • 17d97a8: docs(conduit): list postgres among the configurable provider types (@juicycleff)
  • 8bc75fd: docs(conduit): match the README's RPC selection to the memory rule (@juicycleff)
  • 2f9a89a: docs(deploy): scope the ServiceMonitor cleanup command to one project (@juicycleff)
  • 309aae1: docs(examples): point the observability example at forge obs (@juicycleff)
  • aba276a: docs(examples): regenerate the observability dashboard and add alert rules (@juicycleff)
  • 25a985f: docs(extensions): drop the advice to put false values in the config file (@juicycleff)
  • eef42c4: docs(features): say flag values can come from YAML now (@juicycleff)
  • 5f02880: docs(grpc): document gRPC tracing, rpc.server.call.duration and client dial options (@juicycleff)
  • 1369316: docs(grpc): fix the interceptor order and note the observability edge cases (@juicycleff)
  • 399b709: docs(metrics): add an upgrade note and say which trace settings turn metrics push on (@juicycleff)
  • cda2f37: docs(metrics): document OTLP metrics push and drop StatsD and Influx (@juicycleff)
  • 65919c9: docs(metrics): state the real config precedence and fix the cap and exemplar notes (@juicycleff)
  • bba46b8: docs(metrics): tell Agent-free Datadog users that metrics push is on (@juicycleff)
  • 6e8a822: docs(metrics): tie metrics push to app.Start and app.Stop, hedge exemplars, fix a table reference (@juicycleff)
  • f0f9d09: docs(mqtt): deprecate the tracing flag MQTT 3.1.1 can't honour (@juicycleff)
  • 1c49a49: docs(observability): cover boot and shutdown traces and the dashboard's OTel trace viewer (@juicycleff)
  • 426d42c: docs(observability): fix the profiling link wording and cover pull, env and stream limits (@juicycleff)
  • 681057c: docs(observability): lead the Grafana guide with forge dev --observability (@juicycleff)
  • 35a2009: docs(observability): say span processors see request attributes in OnEnd (@juicycleff)
  • 8b70e05: docs(observability): say that every span processor sees recorded unsampled spans (@juicycleff)
  • 6778280: docs(router): describe the WebTransport stream limits in llm.txt (@juicycleff)
  • b95b8b3: docs(telemetry): describe the metrics push lifecycle from Start to Stop in llm.txt (@juicycleff)
  • 460c133: docs(telemetry): say that forge.New takes over the OpenTelemetry globals (@juicycleff)
  • 2ce2d6c: docs(telemetry): say the server middleware sits in the router's outer slot (@juicycleff)
  • c7421a7: docs(tracing): correct llm.txt for the forge sampler and add UnsampledSpanProcessor (@juicycleff)
  • 2e2e59c: docs(webtransport): show the real setup and what each config field does (@juicycleff)

Build System

  • 95179a1: build(deps): bump go-utils to v1.4.1 and confy to v1.1.0 in every module (@juicycleff)
  • 18f7446: build(deps): require forge v1.12.9 in every module that replaces it locally (@juicycleff)
  • bea17ec: build(graphql): build against this checkout's root like the other extensions (@juicycleff)
  • aa75231: build: pin go-utils with span_id log context (@juicycleff)
  • 6562d44: build: tidy sibling modules for the tracing dependencies (@juicycleff)
  • 064d7df: build: tidy sub-module go.mod files for the pyroscope and OTLP metrics requirements (@juicycleff)

Other Changes

Installation

Using Go Install

go install github.com/xraph/forge/cmd/forge@v1.12.9

Download Binary

Download the appropriate binary for your platform from the assets below.

Using Package Managers

# Homebrew (macOS/Linux)
brew install xraph/tap/forge

# Scoop (Windows)
scoop bucket add xraph https://github.com/xraph/scoop-bucket
scoop install forge

What's Changed

Full changelog: v1.12.8...v1.12.9