Skip to content

v1.12.2

Choose a tag to compare

@juicycleff juicycleff released this 08 Oct 13:23
· 502 commits to main since this release

Forge Framework v1.12.2 (2026-10-08T13:17:11Z)

Welcome to this new release of Forge Framework!

Changelog

New Features

Bug Fixes

  • cefd9b9: fix(client): apply one media-type rule, keep declared body types and bound the whole rest exchange (@juicycleff)
  • 5c038c9: fix(client): decode and type +json responses in the TypeScript client (@juicycleff)
  • b5b0581: fix(client): drop the redundant cast on enum branches of a union (@juicycleff)
  • 77f5dd0: fix(client): encode a dart int64 in the shape its schema declares (@juicycleff)
  • 61b6d77: fix(client): end dart live sockets cleanly, cancel stale attempts and keep sends in order (@juicycleff)
  • 53f8583: fix(client): ignore Dart tooling files in client check (@juicycleff)
  • 9b24692: fix(client): keep a poison send from stalling the queue and retry a drop during setup (@juicycleff)
  • d7fce42: fix(client): keep dart page walkers from shadowing call paths and honour has_more (@juicycleff)
  • d58496e: fix(client): keep declared invalidates on entity-less routes and drop malformed tags with a warning (@juicycleff)
  • b5ec57c: fix(client): keep generator ports, stream order and method case in step across languages (@juicycleff)
  • be4f9b7: fix(client): keep int64 list params in their parameter form (@juicycleff)
  • c4cfdfa: fix(client): keep sync-only entities through path filters (@juicycleff)
  • 5fee9c4: fix(client): keep unknown enum values by generating enums as extension types (@juicycleff)
  • df94c80: fix(client): normalize SyncDataset, reject unplaceable WithSync declarations at registration (@juicycleff)
  • 72103c1: fix(client): own every dart generated directory and render the streaming connect arguments (@juicycleff)
  • a858e1a: fix(client): qualify members in generated equality so a field named other works (@juicycleff)
  • d653c7d: fix(client): rename Dart fields that shadow generated code and drop unused imports (@juicycleff)
  • 2158977: fix(client): report a literal optimistic patch on a POST action instead of minting a create (@juicycleff)
  • f8fee74: fix(client): report an untargeted optimistic patch instead of minting a phantom create (@juicycleff)
  • 565e21f: fix(client): reserve dart helper names, cancel rest calls and check per-client int64 (@juicycleff)
  • ee7084a: fix(client): send non-json binding bodies as their declared content type (@juicycleff)
  • 681bdbb: fix(client): tell a missing has_more from false, keep a bad frame off the socket, pin connect() (@juicycleff)
  • 3c8f7c4: fix(client): treat +json media types as JSON when choosing codecs (@juicycleff)
  • 28abe13: fix(client-core): route a release after repartition to the live socket (@juicycleff)
  • d196af7: fix(client-dart): abort a request delayed by the simulator when the principal changes (@juicycleff)
  • 031c7af: fix(client-dart): apply typed optimistic specs safely and keep the last good model while optimistic (@juicycleff)
  • 8ee6831: fix(client-dart): bound devtools copies by size, cycles and strings, and make them read-only (@juicycleff)
  • 4011e1f: fix(client-dart): bump the devtools protocol to 2 for the changed wire shapes (@juicycleff)
  • 3f78542: fix(client-dart): cap the devtools outbox listing and show failed writes the session no longer holds (@juicycleff)
  • a351936: fix(client-dart): classify response bodies as json, text or bytes by one rule (@juicycleff)
  • d02e35e: fix(client-dart): close a storage batch when its builder returns and pin scan order (@juicycleff)
  • f4ff0b0: fix(client-dart): compare string and double children by value in the store (@juicycleff)
  • 9e43543: fix(client-dart): compare sync statuses by value (@juicycleff)
  • 8e924f8: fix(client-dart): cover mid-hydrate clears in both modes and document denormalized owned data (@juicycleff)
  • 92fc1c1: fix(client-dart): drop frames from a previous principal and port the repartition release case (@juicycleff)
  • b33046b: fix(client-dart): drop stream frames while manager and cache principals disagree (@juicycleff)
  • fa092f9: fix(client-dart): drop the overlay fold memo with the records it was folded from (@juicycleff)
  • 85b9df4: fix(client-dart): fence old sync sources on principal change and expose cache idle (@juicycleff)
  • ca97779: fix(client-dart): fence owned rows across principals, clears, collection and snapshots (@juicycleff)
  • 1156338: fix(client-dart): follow browser semantics for SSE ids and scope resume ids by principal (@juicycleff)
  • e7bb053: fix(client-dart): guard request observers and close an owned http client (@juicycleff)
  • ba3ffd7: fix(client-dart): keep a request a principal change orphaned aborted when a release wakes it (@juicycleff)
  • 7fafb7b: fix(client-dart): keep a retrying query's state stable and release live bindings once (@juicycleff)
  • 2121796: fix(client-dart): keep optimistic folds linear and promote embedded edits as references (@juicycleff)
  • 508a3be: fix(client-dart): keep the status of unparseable error bodies and bound each attempt (@juicycleff)
  • 4630718: fix(client-dart): keep unconfirmed recoveries and report principal wiring mismatches (@juicycleff)
  • 8c3feba: fix(client-dart): keep value objects exact when edited in place and trust no reordering codec (@juicycleff)
  • f20b347: fix(client-dart): mark queries, query, entities and entity answers stale while the principal changes (@juicycleff)
  • e70d248: fix(client-dart): match native SSE event filtering to web and finish a failed socket close (@juicycleff)
  • 3ea5292: fix(client-dart): name key: in the untargeted optimistic errors (@juicycleff)
  • f20429e: fix(client-dart): never send a request cancelled during its credential wait, expose response headers (@juicycleff)
  • f23f455: fix(client-dart): pair optimistic merges by entity identity and keep undo references (@juicycleff)
  • d47cd08: fix(client-dart): purge a disposed inspector and hold the principal marker until the clear (@juicycleff)
  • a349f8c: fix(client-dart): reinstate every watched record before clear notifies any of them (@juicycleff)
  • f97ccf4: fix(client-dart): reject an async edit in SyncContext.write (@juicycleff)
  • 1e89fef: fix(client-dart): release the simulator on dispose instead of aborting its delayed writes (@juicycleff)
  • 643321f: fix(client-dart): repeat the key for each item of a form list value (@juicycleff)
  • 9d968cb: fix(client-dart): report a simulated offline to connectivity listeners before the setter returns (@juicycleff)
  • 8ef301b: fix(client-dart): require a session on devtools changes, cap explain lists, drop the principal value (@juicycleff)
  • 4888d6c: fix(client-dart): resolve embedded entities before an optimistic merge (@juicycleff)
  • ed29136: fix(client-dart): restore cancel aborts and pin timeout and error-body behaviour (@juicycleff)
  • c9847e7: fix(client-dart): return bytes for binary responses and honour a text charset (@juicycleff)
  • 64f5c4a: fix(client-dart): reuse a prior capture only at the top level of a bounded copy (@juicycleff)
  • f1596ef: fix(client-dart): say which devtools entry points are gated and test the fills-slots recipe (@juicycleff)
  • 02aaa6a: fix(client-dart): seal optimistic views and promote only what the caller changed (@juicycleff)
  • 69c1709: fix(client-dart): send devtools identifiers whole and refuse stale sessions on every write (@juicycleff)
  • 1db3071: fix(client-dart): settle a principal change from the cache, and drain held log entries in order (@juicycleff)
  • e044cd6: fix(client-dart): skip commits for writes that land after a clear and end polling on dispose (@juicycleff)
  • 00938fe: fix(client-dart): stop a superseded setPrincipal once a listener has switched principal again (@juicycleff)
  • ba41eae: fix(client-dart): stop the WebTransport read loop after close and prove EventSource cleanup (@juicycleff)
  • d297e5c: fix(client-dart): test that a nested prior capture is counted against the budget and depth (@juicycleff)
  • 84175d2: fix(client-dart): test the unheld-key fold across a switch and rollback on an owned key (@juicycleff)
  • bf0e183: fix(client-dart-devtools): accept only protocol 2 and ask a mismatched app nothing more (@juicycleff)
  • 8593566: fix(client-dart-devtools): follow isolate changes and refresh lists in place (@juicycleff)
  • c1098c9: fix(client-dart-devtools): keep the open frame by what identifies it, and aim capture at a session (@juicycleff)
  • 9f03488: fix(client-dart-devtools): refresh empty lists, hold what the viewport shows, say switching (@juicycleff)
  • d5fd802: fix(client-dart-devtools): say hello again when a cache attaches, detaches or is refused as gone (@juicycleff)
  • fd15c77: fix(client-dart-devtools): show capped and stale explain answers and hold the pages in view (@juicycleff)
  • c7d09c4: fix(client-flutter): batch computed recomputes per scope and report recompute errors (@juicycleff)
  • fb5febe: fix(client-flutter): drop events from a superseded query stream in QuerySubscription (@juicycleff)
  • 2d0b355: fix(client-flutter): fail a computed whose recompute throws during a client swap (@juicycleff)
  • 76ca828: fix(client-flutter): make the placement test discriminate and pin the held-rebuild paths (@juicycleff)
  • 89ceca7: fix(client-flutter): mask a query's state from the previous principal until its clear notification (@juicycleff)
  • b23bc16: fix(client-flutter): match the README to the generated shapes, harden restore and outbox (@juicycleff)
  • 549073d: fix(client-flutter): recompute a dirty computed when it is read inside a batch (@juicycleff)
  • febf03f: fix(client-flutter): reset ForgeMutationBuilder on a principal or client change and pin git refs (@juicycleff)
  • dc64b2b: fix(client-flutter): seed connectivity, flush frame commits when hidden (@juicycleff)
  • 01d3b67: fix(client-grove): a 404, 410, 401 or 403 on the change stream drives the gone or unauthorized state (@juicycleff)
  • 2263dfb: fix(client-grove): a queued erase on a fenced run fails as a principal change; harness holds stdin (@juicycleff)
  • ebb1399: fix(client-grove): credit window joins to cache.principal and let leave work during the load (@juicycleff)
  • 74ef7bd: fix(client-grove): drop fields the replica lost when projecting a record (@juicycleff)
  • cb46b63: fix(client-grove): keep a rejoin that waits on an erase with the principal that made it (@juicycleff)
  • ffd531f: fix(client-grove): keep the ws path prefix, queue an early join, add flush and document the fence (@juicycleff)
  • 5220f72: fix(client-grove): make a rejoin wait for an erase in flight and report a replica load failure once (@juicycleff)
  • 81843aa: fix(client-grove): never take the dataset path param as a row id, validate codecs (@juicycleff)
  • e03a541: fix(client-grove): queue ReplicaSpace.open per session so concurrent first opens share one node id (@juicycleff)
  • 915657b: fix(client-grove): refuse a whole mutation past the pending bound and validate it before any write (@juicycleff)
  • 41db8ab: fix(client-grove): retry interrupted runs with backoff and push replica() writes on any live channel (@juicycleff)
  • e63886b: fix(client-grove): surface a closed session through ReplicaSpace.erase's future (@juicycleff)
  • 954b874: fix(client-grove): take a dataset route's trailing param as the row only after the body id (@juicycleff)
  • 19fb233: fix(client-grove): tie pending joins to their principal and load replicas after start returns (@juicycleff)
  • 2f60e67: fix(client-offline): classify TLS errors and OS codes, validate overlay decode and failed state (@juicycleff)
  • 17f9256: fix(client-offline): clean the keychain after the macOS test, correct the Argon2id RFC note (@juicycleff)
  • be163f6: fix(client-offline): close test connections before a reset deletes, and pin close before delete (@juicycleff)
  • 7c90a3f: fix(client-offline): count principal changes for stale writes and never resend source-owned writes (@juicycleff)
  • bbe0ee9: fix(client-offline): isolate keystore names, share one salt, salt passphrase keys (@juicycleff)
  • fa438ec: fix(client-offline): keep the key out of errors, refuse lone surrogates, re-read migration version (@juicycleff)
  • dd3879b: fix(client-offline): own a storage subdirectory, set busy timeout first, recover salt leftovers (@juicycleff)
  • 392058c: fix(client-offline): publish passphrase salts by exclusive directory rename (@juicycleff)
  • 12a2385: fix(client-offline): refuse stale writes, jitter and cap retries, strip more credential headers (@juicycleff)
  • 84f0f7b: fix(client-offline): restore past owned rows, say why a replay stayed queued, document open waits (@juicycleff)
  • f2d34c5: fix(client-offline): rotate keys after final statuses, bound replays by the window, persist first (@juicycleff)
  • 215e9bb: fix(client-offline): tighten keystore identity, passphrase salt races and test-only parameters (@juicycleff)
  • b948a73: fix(client-offline): treat the Win32 refusal codes Dart reports on Windows as notSent (@juicycleff)
  • 8c9d220: fix(client-riverpod): mark the value provider stale before setPrincipal clears the cache (@juicycleff)
  • 7523b51: fix(client-riverpod): pin git refs in the README and test failures in flight across a change (@juicycleff)
  • c9597d9: fix(client-riverpod): rebuild .state providers on setPrincipal and pin disposal mid-fetch (@juicycleff)
  • 2e17fe2: fix(client-riverpod): start the value provider fresh on a principal change or client swap (@juicycleff)
  • 4b7f6e8: fix(dashboard): keep a command's entry when its claim lapses mid-run (@juicycleff)
  • 840b8a4: fix(dashboard): run a command once while its idempotency key is held (@juicycleff)
  • be75cec: fix(middleware): fence idempotency claims by holder token and sweep abandoned ones (@juicycleff)
  • 0fca828: fix(middleware): flag skipped anonymous keys, store oversized replies truncated, scope by provider (@juicycleff)
  • 9ff88ed: fix(middleware): let a stacked idempotency layer defer to the outer one (@juicycleff)
  • dd15de4: fix(middleware): release retryable statuses, skip anonymous keys, mark busy 409s retryable (@juicycleff)
  • d02f55c: fix(middleware): wait on Done, honour ctx in the replay loop and release past a cancelled request (@juicycleff)

Refactoring

  • dc8a98f: refactor(client-riverpod): share one noRetry, drop the value notifier export, fake the retry wait (@juicycleff)
  • 81cafbf: refactor(middleware): back the dashboard command store with the shared idempotency store (@juicycleff)
  • 2da7bd4: refactor(streaming): register the dashboard contributor as streaming (@juicycleff)

Documentation Updates

  • d95f626: docs(changelog): update CHANGELOG.md for v1.12.0 (@github-actions[bot])
  • 41994da: docs(changelog): update CHANGELOG.md for v1.12.1 (@github-actions[bot])
  • d6fb9c5: docs(client-dart): correct the key parity and private parameter claims (@juicycleff)
  • e6ddcca: docs(client-dart): pass key: in the optimistic README samples (@juicycleff)
  • 37d62be: docs(client-flutter): show forge_client_offline in the Offline section, compiled (@juicycleff)
  • 6e61761: docs(client-offline): call authPrincipal a pre-send check, not cover for swapping credentials first (@juicycleff)
  • ee6cb53: docs(client-offline): document the idempotency seams and say web is not yet supported (@juicycleff)
  • 2c253e3: docs(dart-client): add the dart client section with overview and installation (@juicycleff)
  • 54646ef: docs(dart-client): add the devtools and not yet shipped pages (@juicycleff)
  • 453156c: docs(dart-client): add the entities and invalidation pages (@juicycleff)
  • f9b17f3: docs(dart-client): add the generated package page (@juicycleff)
  • 228266e: docs(dart-client): add the getting started page (@juicycleff)
  • 4241b3e: docs(dart-client): apply the final review's fixes to release status, limits and drifted claims (@juicycleff)
  • 3747cbc: docs(dart-client): correct the airplane-mode callout and add the dart cli flags (@juicycleff)
  • 7a28239: docs(dart-client): describe every section in the not yet shipped intro (@juicycleff)
  • 28dc7da: docs(dart-client): document offline storage and grove sync (@juicycleff)
  • 926da29: docs(dart-client): document the flutter and riverpod adapters (@juicycleff)
  • 15ed5c3: docs(dart-client): fix an article and note the undeclared fields of a pending embedded change (@juicycleff)
  • e24ddef: docs(dart-client): fix the generated package page after review (@juicycleff)
  • 0c6f040: docs(dart-client): fix the hooks, retry and grove claims on overview and installation (@juicycleff)
  • 9a588f1: docs(dart-client): fix the identity claims and tighten the entities and invalidation pages (@juicycleff)
  • d467ea3: docs(dart-client): fix the late-stamp and keystore claims and the devtools sample (@juicycleff)
  • bc11aa3: docs(dart-client): fix the late-stamp scope and keystore claims in offline and sync (@juicycleff)
  • b8c7e57: docs(dart-client): restate the late-stamp mechanism, warn on keychain switches and anonymous keys (@juicycleff)
  • c4a3386: docs(dart-client): say plainly what the not yet shipped page collects (@juicycleff)
  • 443d04d: docs(dart-client): show optimistic writes on Order and fix the listener sample (@juicycleff)
  • 503c93d: docs(dart-client): tighten the getting started page after review (@juicycleff)
  • 45fd0f8: docs(dart-client): tighten the voice of the twelve pages and fix the Entities card (@juicycleff)
  • 7a34809: docs(dart-packages): add the repository url pub's validator requires (@juicycleff)

Build System

  • e16590d: build(client-dart-devtools): add the extension build script and README (@juicycleff)

Other Changes

  • 1653f6e: ci(dart-packages): let pub's validator pass on the runner and run on typescript generator changes (@juicycleff)
  • 32a313c: ci(dart-packages): run on web-client pages and router changes, check docs components (@juicycleff)
  • 0a8135a: ci(dart-packages): run the dart packages, generator gate and docs checks on the pinned flutter (@juicycleff)
  • 9edd69a: ci(dart-publish): publish only from the matching tag, fresh token per pub call, devtools apart (@juicycleff)
  • a9a1715: ci(dart-publish): publish the dart packages to pub.dev on a version tag through oidc (@juicycleff)
  • 77c0517: ci(dart-publish): refuse real prerelease publishes, keep the devtools build a week (@juicycleff)
  • 0e2d408: ci(dart-publish): reject leading zeros and recognise every common changelog heading (@juicycleff)
  • 4a96823: ci(dart-publish): stamp one release version on every package and its changelog (@juicycleff)
  • 2eacf78: ci(docs): add a grove-backed note to the catalog spec and let snippets import grove_crdt (@juicycleff)
  • d6a58b4: ci(docs): compile the dart docs against a catalog client and check pasted excerpts (@juicycleff)
  • 0f16327: ci(docs): compile the dart docs samples against the real packages (@juicycleff)
  • 8d351cc: ci(docs): make the dart docs extractor and link checker fail closed (@juicycleff)
  • 4630399: ci(docs): report the missing excerpt line from the closest generated client (@juicycleff)
  • 179b264: ci(release): install the TypeScript toolchain before the release tests (@juicycleff)
  • 90dd53f: style(client-dart): format the packages for the CI format check and keep README examples verbatim (@juicycleff)
  • 93df7ae: style(streaming): space out the manifest name check (@juicycleff)
  • 725b34f: test(client): harden the dart table and codec parity checks (@juicycleff)
  • 712eb1f: test(client): pin dart and typescript table and codec parity (@juicycleff)
  • e88278f: test(client): pin same-member tags and named-enum passthrough in dart codecs (@juicycleff)
  • 4493ebb: test(client): round-trip x-forge-sync; record raw-route sync paths as {param} (@juicycleff)
  • 2c43a90: test(client): satisfy makezero and usestdlibvars in the new parity tests (@juicycleff)
  • 7df257d: test(client): share one media-type vector table across go, forge_client and generated dart (@juicycleff)
  • 8460bfc: test(client-core): export cross-runtime client fixtures (@juicycleff)
  • 1e4b9cd: test(client-core): hydrate the snapshot the Dart runtime writes (@juicycleff)
  • 7f5160f: test(client-dart): give the README stubs the invalidates a generated client emits (@juicycleff)
  • c66a5e8: test(client-dart): make the cancel test fail on a dropped cancel (@juicycleff)
  • b699714: test(client-dart): pin a list row and the single-record read to one model (@juicycleff)
  • 16dfcc8: test(client-dart): pin the core surface the stream layer consumes (@juicycleff)
  • f87bec5: test(client-dart): prove caller cancel and timeouts abort the request (@juicycleff)
  • df9821e: test(client-dart): verify the cross-runtime fixtures (@juicycleff)
  • 55913a5: test(client-flutter): pin bind ordering and the microtask rethrow, make forgeRefetch reject (@juicycleff)
  • e160d94: test(client-flutter): pin principal, fail-closed, toggle-off and reconnect in live tests (@juicycleff)
  • 903599f: test(client-flutter): pin rebuild counts for identity and select (@juicycleff)
  • d4b69eb: test(client-flutter): pin the combined getters and reorder behaviour of ForgeQueriesBuilder (@juicycleff)
  • 3851bd1: test(client-flutter): port the live query suite against the stream runtime (@juicycleff)
  • e79b588: test(client-grove): compare whole records to the server and harden conformance teardown (@juicycleff)
  • 4468639: test(client-grove): two devices converge through the grove go server (@juicycleff)
  • b735e74: test(client-offline): count salt puts across equal stores, kill the writer on a held hot journal (@juicycleff)
  • c3e9e85: test(client-offline): exercise the real macOS Keychain and document the package (@juicycleff)
  • a817f5a: test(client-offline): pin devtools privacy, README recipes and the OfflineClient.open release fold (@juicycleff)
  • ecc63a5: test(client-riverpod): pin a cross-key read during setPrincipal to one fetch and the kept record (@juicycleff)
  • d649e59: test(client-riverpod): pin reinstall on change and no provider retry (@juicycleff)
  • 3cf548d: test(middleware): give each idempotency auth-order case its own store (@juicycleff)

Installation

Using Go Install

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

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.0...v1.12.2