point reads for single-row policy checks
I changed single-row update and delete policy checks to read only the requested row. They no longer load every row in the table just to find one matching identifier.
I changed single-row update and delete policy checks to read only the requested row. They no longer load every row in the table just to find one matching identifier.
I fixed subscriptions losing local inserts, updates, or deletes while they were applying a server snapshot. Pending changes now remain visible until they are accepted or rejected, while genuine server changes still reconcile normally.
I added a local-first authentication mode to React's JazzProvider. It loads the saved secret before creating the client, shows the configured fallback while that happens, and keeps the existing authentication modes unchanged.
I fixed query paths that treated every column named id as Jazz's internal row identifier. When an application declares its own id, filters and joins now use that application value, while tables without one keep the existing behaviour.
I renamed Vue query subscriptions' reactive loading property to isLoading. The behaviour stays the same, but the name now makes it clearer that the value is a boolean state.
I renamed Svelte query subscriptions' reactive loading property to isLoading. Existing loading, success, and error transitions continue to work while the public name better matches the value.
I removed the old propagate query option so propagation is the single public way to control forwarding. Applications that need a query to stay local can now use propagation: "local-only" consistently.
I added reactive one-row helpers for React, Vue, Solid, and Svelte. They keep the query live while making loading, empty, and populated results clear without making developers pull the first item out of an array themselves.
I changed upsert to take the table, row ID, data, and optional settings in that order. This keeps the row ID separate from mutation settings and matches the shape used by the other row mutation methods.
I made global sequence allocation fail safely when the counter reaches its maximum value. The final value can be used once, but any later allocation now returns a clear error instead of wrapping around and reusing an old sequence number, and every current allocation path uses the same guard.
I replaced loosely shaped subscription messages with typed events that the native and TypeScript layers can agree on. The subscription manager now prepares the exact row layout once, so each update can decode fixed positions instead of guessing from field names, while unknown or redefined layouts fail clearly.
I fixed prepared queries so a number used in an access rule can be compared correctly even when it arrives in a different integer size. Values that cannot be converted safely keep their original type, which makes the permission check fail closed instead of silently matching the wrong value.
I fixed prepared permission queries that combine rules with and without a claim. Each active binding now gets the right route information, so the claimless branch no longer disappears or produces results for the wrong binding.
I updated Jazz's integration tests and simulation benchmark to use the new transaction API. The tests now pass the correct opening batch identifier and check that a committed batch exists before waiting for the change to become safely stored at the edge.
I changed startup recovery to scan only transactions that have a real sequence number. Pending or rejected local transactions are handled by their own replay paths, so recovery no longer spends time scanning unrelated history.
I added a set of reconnect tests that cover membership and permission changes while someone is disconnected. They check that the client receives exactly the rows that were added, changed, or removed, so future changes cannot accidentally reload everything.
I added a browser benchmark that measures how long it takes to load a large set of related records. It uses a repeatable project-board dataset and records the row counts and the time needed to turn the returned data into usable objects, giving us public coverage for this path without changing production behaviour.
I added a testing-only benchmark that measures the main stages of opening Jazz and recovering its saved data. The measurements now follow the current storage layout, including the final step that restores aliases, so future performance work can target real costs.
I made Jazz's SUM, AVG, MIN, and MAX behave like SQL when there are no rows or only null values, while keeping grouped queries and COUNT working as before. I also added support for signed 64-bit numbers and carried the resulting types through the public subscription API.
I updated the starter projects to use the tested Better Auth 1.6.24 release. I replaced an outdated token-request helper with the typed request supported by that release, keeping the starter authentication flows and compatibility checks aligned.