## v0.27.1

- Consistently initialize rustls TLS binaries at the binary root. Previously, outgoing HTTPS traffic may have caused panics when not properly initialized. Thanks @jimmydjabali 🙏.
- Small optimization: increase connection re-use and reduce spawning of threads across admin APIs.
- Remove legacy `_session` table. Session data now lives in a separate DB.
- Update dependencies.

## v0.27.0

- Cleanup release: remove the Sqlean's `define()` extensions for stored procedures. Breaking for users of Sqlean.
  - Read queries modify connection state, therefore don't work with the `query_only` pragma resulting in elevated scheduling requirements.
  - Doesn't allow anything that isn't possible with `VIEW` + WASM SQLite extensions.
  - Is another source of SQLite lock-in, while we're moving towards loosened coupling.
- Other major changes since the previous major release are mostly around DB coupling and execution model.
  - There is a proof-of-concept Postgres driver now but it would still be a long way to hook it up:
    - different SQL dialects,
    - schema extraction missing,
    - dependencies on SQLite extensions for `CHECK()`, migrations, etc.,
    - change notifications for RecordApi subscriptions would need to work very differently,
    - more fun surprises...?
- Lift Rust MVRV (1.93) and Rust toolchain (1.95) versions.

## v0.26.9

- Enable custom WASM SQLite extension functions in multi-DB migrations.
- Apply migrations asynchronously to further untangle DB implementation from execution model.
- Improve error handling and simplify bespoke initialization order of DB connection.
- Update dependencies.

## v0.26.8

- Add two new SQL connection types: a postgres one and a polymorphic one with runtime dispatch.
  - This is mostly a proof-of-concept. Tests pass with the polymorphic connection pointing at SQLite but using postgres entails many more challenges:
    - different SQL dialects,
    - schema extraction missing,
    - dependencies on SQLite extensions for `CHECK()`, migrations, etc.,
    - change notifications for RecordApi subscriptions would need to work very differently,
    - more fun surprises...?
- Introduce a new `AsyncReactive` + snapshot primitive to further entangle DB connection establishment from the execution model, i.e. allow establishing connection asynchronously and thus `RecordApi`s.
- Update dependencies.

## v0.26.7

- Fix CLI regression for `user` and `admin` commands due to DB initialization order changes.
- Fix missing version identifier in `--version` for CI release builds. There were two issues: shallow checkouts and permissions for docker MUSL builds.
- Admin UI: For geospatial data show EWKT SRID only when present and fix form prefill during record update for WKT.
- Add `&skip_cursor` parameter for RecordAPI listing to help with GeoJSON consumers who don't support the `foreign_member` standard extension.
- More work towards untangling TrailBase from SQLite specifics: make lock acquisition fallible.
- Update dependencies.

## v0.26.6

- Admin UI improvements:
  - Allow using WKT-formatted geometries in row insert/update forms.
  - Early client-side validation of RecordAPI names.
  - Show toast close button on small screens w/o hover.
- Add `execute_batch()` to `SyncConnectionTrait` for downstream schema metadata building code.
- Remove more use-cases of leaky `Connection::write_lock()` abstraction.
- Update dependencies.

## v0.26.5

- Remove most leaky abstractions from `trailbase_sqlite::Connection`:
  - Introduce an async `Connection::transaction()` API to remove many `.call_reader()` calls.
  - Add a `SyncConnection` for the remaining batch uses of `.call_reader()`.
  - Add a dedicated backup API.
  - Add a first-party Statement abstraction to allow binding parameters to other clients.
  - Clean-up a few more overlooked uses and narrow `ToSqlProxy`'s lifetimes.
- Add a new `refinery` driver using above async `transaction()` API.
- Use new APIs in `TransactionRecorder` used for migrations.
- Increase statement cache size.
- Minor: replace `kanal` with `flume` everywhere.
- Update dependencies.

## v0.26.4

- Use WASI resources to model WASM transactions more correctly. Also spawn a watcher task that force-unlocks the DB after a deadline for better isolation from user code.
  - The new APIs are transparent and implemented in a backwards-compatible way, i.e. if you rebuild your WASM guests against future releases of the guest runtimes you'll pick up those changes.
- Make server limits more configurable: rate limits and body size limits.
- Add "created" and "last-updated" timestamps to accounts page in admin UI.
- Switch SQLite execution model from `kanal` to `flume` to allow the writer to lend a hand with reads.
- Mark read connections as explicitly `query_only`.
- More work towards untangling from `rusqlite`: remove more uses of leaky abstractions and make error handling generic.
- Update dependencies.

## v0.26.3

- Make `trailbase-sqlite`'s abstractions less leaky, i.e. don't depend on `rusqlite`'s internals as much. This is a pre-requisite if we wanted to support other drivers and DBs.
- Fix and clean-up `trailbase-sqlite`'s execution engine.
- Update clients across all languages to automatically "log out" on token refresh when a 401 (Unauthorized) error is received.
- Stricter "read-only" query filtering for WASM guests. Sqlean's `SELECT define()` statements are actually mutating. Maybe it's time to remove `sqlean`. It predates JS and WASM components and may have overstayed its welcome.
- Allow loading `*.wasm` components from symlinks.
- Tweak `auth-ui`'s profile page to properly clean-up invalid cookie tokens.
- Fix a few small issues with the blog example.
- Update dependencies.

## v0.26.2

- Fork the `reactivate` crate to streamline it and make it lock-free. Previously, accessing the config would require claiming an eclusive lock.
- Remove unsafe query construction from WASM guest examples and add utilities for escaping safe SQL string literals to the guest runtimes.
- Fix wiring of new `redirect_uri_allowlist` config option.

## v0.26.1

- Add an `redirect_uri_allowlist` config option to enable select off-site auth redirects.
- Fix escaping of migration file names to work for any unicode characters.
- Fix escaping of named placeholders to work for any unicode characters.
- Update Rust and JavaScript dependencies.

## v0.26.0

- Overhaul change subscriptions:
  - Minimize work done on SQLite's pre-update hook.
  - Push brokering into separate thread and ACL-checking+filtering into handler tasks.
  - Simplify locking.
  - Add layered sequence numbers to track both, server-side event losses (e.g. due to back-pressure) and allow clients to detect client-side losses (e.g. due to unreliable network).
  - Add structured status to error events. This changes the wire-format and is a breaking change. While this only affects errors, users of change subscriptions should update their client.
    - We did also explore switching from an externally to an internally tagged union format. However, externally tagged is the way to go for change event schemas with something like JSON schema or Avro.
  - Update all the clients that support change subscriptions, i.e. all but Swift.
  - Add stress-tests.
- Fix `ATTACH DATABASE` calls from WASM guests.
- Update dependencies.

## v0.25.4

- Fix MacOS release workflows.

## v0.25.3

- Concurrent `SELECT`s for WASM guests.
  - The guest APIs don't distinguish between reads and writes, hence everything was assumed to be potentially mutating.
  - We're now "pre-parsing" queries to handle `SELECT`s and `ATTACH/DETACH DATABASE` specially and multiplex to multiple connections.
- Stricter `Content-Type` handling and some preparations for supporting more encodings. This is part of an exploration to support Avro.
- Fix JSON schemas for nullable JSON and expanded foreign key columns.
- Add JSON input/output validation to record APIs in debug builds.
- Update dependencies.

## v0.25.2

- Update clients for all eight supported language environments to allow injecting custom "transport" implementations.
  - This can be used for testing but also in prod. For example, a backend may want to inject users' original IPs via `X-Forwarded-For` to make sure logging and rate limiting works correctly.
- Update JS/TS WASM guest runtime to use canonical jco generated types.
- Update Rust and JavaScript dependencies including latest Wasmtime & TS6.

## v0.25.1

- Add GitHub OAuth provider (validated).
- Minor: stable, lexicograpic sorting of OAuth providers.
- Fix smaller cookie issues and inconsistencies, previously:
  - `same-site` policy shouldn't depend on dev-mode to avoid inconsitencies and late surprises.
  - OAuth state cookies were `secure` in dev-mode and not as strict as they could be in prod-mode. Now all cookies `secure` policy depends on dev-mode + HTTPS site.
  - Empty override-cookies during logout API should not bet `secure`, i.e require TLS.
- QoL: Trim whitespaces from OAuth client id/secret in UI.
- Update Rust and JS dependencies (Astro 6, vite 8, ...).

## v0.25.0

- Add support for TOTP (e.g. authenticator app) two-factor auth: APIs, auth UI and admin UI 🎉.
  - Added support for two-factor login to client libraries in all 8 languages.
- Add support for single-factor OTP authentication, i.e. receive a code/link by email: APIs, auth UI and admin UI.
  - Note that this is disabled by default. Using single-factor OTPs delegates security to your users' inboxes, which may be more or less secure.
  - Access is rate-limited to avoid brute-force, enumeration attacks.
  - Added support for request/login OTP to client libraries in all 8 languages.
- Hardening: move all session-like, ephemeral state into JWTs or a separate `session.db` database.
  - This way a WASM component-level SQL injection vulnerability cannot leak session artifacts.
  - This also makes it possible to just drop the entire `session.db` to invalidate all refresh tokens and other auth codes (however not JWTs like the auth token).
  - The new setup may also allow more flexible expiration times for various codes and tokens.
- Many small and big (breaking) improvements to auth APIs and auth UIs. If you're using the `auth-ui` WASM component, make sure to update:
  ```sh
  trail --data-dir client/testfixture components add trailbase/auth_ui
  ```
  - If you're running your own auth UI or customized the auth-ui component, this update will prompt significant but hopefully welcome changes on your end. If you run into any issues, don't hesitate to reach out.
  - Auth APIs and UI are no fully decoupled allowing custom UIs to use all of the same facilities.
- Stop sending emails in dev-mode, instead print to stderr.
- Minor: fix DB size formatting in admin UI.
- Update dependencies, including critical SQLite update.

## v0.24.4

- Disable SQLite FK constraints during migrations and re-enable just before the transaction is committed to avoid getting stuck with inconsistencies while allowing more flexible table alterations in preparation for major auth changes.
- Fix HTTP routing ambiguities for JS/TS WASM guests.
- Add support for "realtime" change subscriptions to Kotlin client.
- Release Kotlin client as multi-platform library.
- Update dependencies.

## v0.24.3

- Add a Yandex OAuth provider.
- Expose RNG to Rust WASM guests.
- Update Rust WASM guest integration to avoid repeated calls to `Guest::Init()` and avoid repeated sqlite function registration.
- Update dependencies.

## v0.24.2

- Revert WASM execution model to not share state between HTTP requests. Rust Guests seem fine but JS guests can get stuck. This requires further investigation.
- Pass `Client-Id` header for Twitch OAuth provider.
- Update realtime SSR docs.
- Update dependencies.

## v0.24.1

- Add experimental Twitch OAuth provider.
- Use `defer_foreign_keys` for schema alterations.
- Update dependencies.

## v0.24.0

- TrailBase received first-class support for geometric/geospatial data and querying 🎉
  - We published [`LiteGIS`](https://github.com/trailbaseio/LiteGIS), an in-house GEOS SQLite extension.
    It's early days but we hope for this to become useful to folks beyond TrailBase.
    Alternatively check out the amazing `SpatiaLite`.
  - TrailBase recognizes columns tagged as `CHECK(ST_IsValid(_))`, e.g.:
    ```sql
    CREATE TABLE table_with_geometry (
        id         INTEGER PRIMARY KEY,
        geometry   BLOB CHECK(ST_IsValid(geometry))
    ) STRICT;

    INSERT INTO table_with_geometry (geometry) VALUES (ST_MakeEnvelope(-180, -90, 180, 90));
    ```
    and updates its API/JSON schemas to expect and produce GeoJSON `Geometry` objects.
  - Internally geometries are represented in the "Well Known Binary" format (WKB). This enables `INDEX`es to accelerate filtering based on certain geometric relationships, see next.
  - The spatial filter operators `@within`, `@intersects` and `@contains` were added to the list API to allow filtering on spatial relations like:
    - List records with bounding boxes that contain my point.
    - List records with points, lines or polygons intersecting my bounding box.

    Reference geometries are specified in the "Well Known Text" (WKT) format, e.g. `?filter[geometry][@contains]=POINT (11.393  47.268)`.
    All clients were updated to support these new filter relations.
  - Using the new list query parameter `?geojson=<geo_column_name>` will return a GeoJSON `FeatureCollection` directly instead of a `ListResponse`.
    The geometry of the collection's features is derived from the column specified by `<geo_column_name>`.
  - The admin UI parses a geometry column's WKB and displays readable WKT but doesn't yet support convenient WKT insertion.
    Similarly clients don't aid in the construction of WKT parameters, this is left to the user, however WKT libraries exist in most languages.
  - Thanks for making it to here 🙏 - would love to hear your input.
- For visibility, other notable changes since the prior major release:
  - Much improved admin UI: better maps and stats on the logs page, improved accounts page, tables handle the loading state to reduce layout jank,  ...
  - Allow change subscriptions via WebSockets in addition to SSE.
  - Support `bcrypt` password hashes for auth. Support importing auth data from Auth0: `trail user import --auth0-json=<file>`.
    - The goal is to provide more horizontal mobility, i.e. reduce lock-in, by allowing auth in and export.
  - Make TrailBase's SQLite extensions available standalone to reduce lock-in, see `/crates/extensions-so`.
  - Dual-licensed clients under permissive Apache-2.0.
- More idiomatic HTTP handling in WASM JS/TS: trailbase-wasm@0.5.0.
- Redo cross-platform builds to deal with new C++ & CMake dependencies introduced by `geos`. MUSL releases are now built with Docker.
- Remove default features from core crate, to get better build coverage of feature permutations and fix latent no-WASM issue.
- Update dependencies.

## v0.23.10

- Add a standalone SQLite extension with all of TrailBase's custom functions to minimize lock-in and make it easier on folks who'd like to move off.
- Overhaul schema metadata handling. More consistency and simplicity across `(Table|View)Metadata` and `RecordApi`. Fewer allocations.
- Make status codes more consistent across auth: user registration, email verification and reset password.
  - Also fix and update the corresponding OpenAPI documentation.
- Update dependencies.

## v0.23.9

- Support `bcrypt` password hashes in addition to `argon2`.
- Add a user import function to CLI. Currently supports Auth0 user exports.
  - Will be straight forward to support other providers that use `bcrypt` or `argon2`, please reach out 🙏.
  - Dual-licensed clients under permissive Apache-2.0.
- Update dependencies.

## v0.23.8

- Show validation errors for `TABLE`/`VIEW`s that do not qualify for Record APIs.
- Improve config validation errors.
- Allow `GROUP BY` expressions on `VIEW`'s non-PK column for `MIN`/`MAX` PK aggregations.
- Add body extraction back to `FetchError`.
- Update dependencies.

## v0.23.7

- Clean up the accounts UI.
- Fix ephemeral invalid cell access in admin UI on `VIEW`s for first access due to column schema fallback.
- Further improve error handling in TS client and admin UI.
- Update JavaScript and Rust dependencies.

## v0.23.6

- Handle permission errors (401 & 403) and 429 more gracefully in admin UI.
- Add uptime to dashboard.
- Update Rust dependencies.

## v0.23.5

- Switch map of the admin UI's logs page from leaflet to maplibre and vector tiles.
- Switch rate graph to a bar chart.
- No longer "auto-hide" stats on `pageIndex > 0`. Instead add an explicit collapse option.
- Split "list logs" from stats endpoint.
- Make break-down by country, e.g. the map, correctly reflect filter queries.
- Update dependencies.

## v0.23.4

- Include cursors in list responses only when properly supported.
- Fix cursor state handling in Admin UI with respect to both reactivity and `pageIndex`-based indexing.
- Add an explicit security/vulnerability policy with `SECURITY.md`.
- Update dependencies.

## v0.23.3

- Polish admin UI: use skeletons/shimmers during data loads for tables to reduce layout jank.
- Minor: improve initial screen fill in ERD graph.
- Update `serde_qs` resulting in stricter query string parsing. This is technically a breaking API change, however affects edge-cases only and users of the client libraries won't have any issues.
- Update dependencies and switch back to upstream `serde_rusqlite`.

## v0.23.2

- Switch to case-sensitive `LIKE` expression, thus making list queries with `filter[col][$like]=val` case-sensitive as well.
  - This is technically a breaking change, though sneaking it into a minor release assuming that nobody actually expected case-insensitive filtering.
- Hoist external SQLite extension loading up to the CLI level and replace upstream sqlite-vec with maintained fork: https://github.com/vlasky/sqlite-vec.
- Add a join-order benchmark for further performance tuning.
- Update dependencies.

## v0.23.1

- Dual license clients under permissive Apache-2.0 license. The server continues to be under OSL-3.0.
- Add a WebSocket subscription feature to the Rust client. Requires the server to be compiled with the non-default "ws" feature as well.
- Update dependencies.

## v0.23.0

- WASM component model:
  - Merge Host implementations for HTTP/Job handlers and custom SQLite extension functions
  - Extend state life-cycle for SQLite extension functions to allow for statefulness and avoid overhead of repeat initialization.
  - Use `async | store | task_exit` exports and `Store::run_concurrent` in preparation for `component-model-async`, which will enable much richer async host-backed plugin APIs.
- Enable "late" authentication for WebSocket subscriptions to support clients (e.g. Browsers) that don't allow setting the headers of the HTTP UPGRADE request.
  - Add early, yet private support for WASM to JS/TS client and tests. We still cannot upstream the WebSocket support for the Rust client due to stale `reqwest-websocket` dependency.
- Update Rust toolchain to latest stable: 1.93.
- Update dependencies.

## v0.22.13

- Support realtime change subscriptions via WebSockets behind the "ws" cargo build feature.
  - When built with the feature and the `?ws=true` parameter is passed a `ws://` protocol upgrade is attempted.
  - The Rust client on the `ws_client` branch supports WebSocket-based subscriptions. We cannot currently mainline it, due to a stale crate dependency.
- Internal: improve Rust client's test setup.
- Update dependencies.

## v0.22.12

- Enable sorting of columns in table explorer, logs and accounts page 🎉.
- Update column's data type when picking a foreign key table in create/alter table form.
- Reduce table jank by setting fixed sizes for well-known columns.
- Fix stability (e.g. during re-ordering) of column card's accordion collapse state.
- Add execution timestamp to any SQL editor's execution result, including errors.
- Cleanup: split table state from table UI.
- Update Rust and JavaScript dependencies.

## v0.22.11

- Allow re-ordering of columns in Create/Alter table admin UI.
- Optimization for filtered realtime subscriptions: enforce filter before access check.
- Admin UI: filter foreign key options based on column type.
- Minor: remove stale mentions of V8 in admin UI.
- Update dependencies.

## v0.22.10

- Fix list record edge case: `?limit=0&count=true` to yield a potentially incorrect `total_count` of 0. #207
- Fix overly eager de-registration of record subscriptions.
- Update Rust and JavaScript dependencies.

## v0.22.9

- Allow streaming of HTTP responses from WASM.
- Internal: major overhaul of WASM integration, remove indirection and scaffolds from previous execution model.
- Update Rust dependencies.

## v0.22.8

- Expose SQL `CREATE (TABLE|VIEW)` statements in admin UI's explorer.
- Move API's JSON schemas in to explorer's API dialog.
- Update Rust dependencies including `reqwest`, which changes default `rustls` crypto provider from `ring` to `aws_lc`.

## v0.22.7

- Add IP-based rate limiting to all auth POST endpoints to further reduce abuse surface like sign-up bombing (sign-ins were already limited).
  - The ip-based nature means that, if you're using a reverse-proxy you should set the `X-Forwarded-For` header. This was already true to get correct log entries.
- Do not instantiate parts of the WASM runtime when no WASM component is found. This reduces the memory footprint for instances that don't use WASM.
- Update SQLite from v3.50.2 -> v3.51.1 (i.e. rusqlite v0.38).
- Update Rust dependencies.

## v0.22.6

- Stop using baseline WASM compiler "winch" in dev-mode on MacOS. Previously loading WASM components on MacOS with `--dev` would cause a panic related to nested tokio runtimes. This increases initial-load & hot-reload times, thus isn't ideal for DevEx but better than crashing. This will require further investigation: https://github.com/trailbaseio/trailbase/issues/206.
- Upon request: add re-serialization of list queries to trailbase-qs.
- Update Rust and JavaScript dependencies.

## v0.22.5

- New "--spa" command-line option for serving SPAs from `--public-dir`. Any path that doesn't look like a file/asset request, i.e. doesn't have a file extension, will fall back to `<public_dir>/index.html` to let a client-side router take over. Otherwise, navigating to non-root paths would serve 404. Thanks @takumi3488.
- Improve error handling and cleanup OAuth callback handling.
- Internal: build queries at build-time rather than relying on lazy-statics whenever possible.
- Update dependencies.

## v0.22.4

- New CLI command `trail user add <email> <pw>` to create verified users from the command-line.
- Add an optional "admin" boolean property to JWTs.
  - Update the Kotlin client to parse JWT more loosely and publish v0.2.0.
  - Kotlin users will need to update their clients before updating to v0.22.4.
- Early support of logical column pinning to visually highlight columns in wide tables.
- Admin UI's login screen now explicit rejects non-admin users. This is a quality-of-life and **not** a security change. Access to admin APIs has always been protected. This just avoids showing a defunct UI to non-admin users.
- Auth registration endpoint now accepts JSON-encoded requests (like the other auth endpoints too).
- Show warning dialogs in admin UI when deleting or updating RecordAPIs.
- Update Rust and JavaScript dependencies.

## v0.22.3

- Downgrade vite-tsconfig-paths to fix Windows release builds (missing in v0.22.2).
- Simplify table explorer's pagination state management.

## v0.22.2

- Add a simple UI (in admin settings) to link/unlink additional databases.
- Fix user account pagination.
- Fix `RecordApiConfig` construction from admin UI for non-main DBs.
- More conservative pre-update hook cleanup.
- Disallow config changes in demo mode.
- Update Rust and JavaScript dependencies.

## v0.22.1

- Improve "realtime" change subscriptions:
  - Introduce a unique connection identity for more robust subscription management.
  - Use layered locks to reduce congestion and thus improve performance.
  - Explicitly recycle connections whenever config changes trigger RecordApi rebuilds. Otherwise, cycling connections can lead to dropped subscriptions with more than 256 DBs.
- No longer do a linear seek to look up APIs optimizing for large N, especially now with multi-DB.
- Update dependencies.

## v0.22.0

- Multi-DB support 🎉: record APIs can be backed by `TABLE`/`VIEW`s in independent DBs. This can help with physical isolation and offer a path when encountering locking bottlenecks.
  - This change includes:
    - Config-driven DB life-cycle management, i.e. creation, migrations, ... .
    - Generalized connection management.
    - Per-DB file-upload/life-cycle management.
    - Multi-DB subscription "realtime" management.
    - End-to-end tests.
  - Limitations:
    - SQLite does not allow for `FOREIGN KEY`s and `TRIGGER`s to cross DB boundaries. However `JOIN`s, etc. are perfectly capable of crossing DB boundaries.
    - The implemented management of independent connections allows for an arbitrary number of DBs despite SQLite's limit of 125 DBs per connection. However, `VIEW`s executed within the context of a connection are still subject to this limit.
  - Documentation is TBD :hide:, see `<repo>/client/testfixture/config.textproto` for an example.
    - DBs are mapped to `<traildepot>/data/<name>.db` and `<traildepot>/migrations/<name>/`.
  - This change doesn't introduce a notion of multi-tenancy, e.g.: create and route per-tenant DBs based on schema templates.
  - This was a big change, please reach out for any issues or feedback. 🙏
- Changed Record API's default behavior to run batches w/o transactions unless requested.
- Improved errors for file-handling record APIs.
- Update Rust (latest stable: 1.92) and dependencies.

## v0.21.11

- Pre-built binary releases:
  - Release aarch64 (arm64) static binaries for Linux (#184) and update install script.
  - Stop releasing Linux glibc binaries. Using them is a gamble depending on your system: best-case it won't work at all, worst-case you end up with hard to debug issues. Even "static" glibc builds aren't static, e.g. when looking up hostnames.
  - There are valid, e.g. performance, reasons to use glibc builds, however it's safer to build from source or for a controlled container environment.
- Remove left-over pseudo error handling to stop swallowing errors in a few places in the admin UI, e.g. when deleting tables.
- Update Rust and JavaScript dependencies.

## v0.21.10

- Fix table renames in admin UI.
- Include database schema name when sorting tables in admin UI explorer.
- Minor layout tweaks for very narrow screens.
- Entirely disallow schema alterations/drops in demo mode.
- Update Rust dependencies.

## v0.21.9

- Use fully-qualified TABLE/VIEW/INDEX/TRIGGER names throughout admin UI in preparation for multi-DB.
- Fix column type update when setting a foreign key constraint. We forgot to additionally set affinity type and type name after re-modelling the type representation. #183 @tingletech 🙏
- Update Rust and JavaScript dependencies.

## v0.21.8

- Make visual ERD schema browser in admin UI usable on mobile. The @antv/x6 latest update fixed panning. By adding zoom buttons (in the absence of pinch), you can now navigate on mobile.
- Use a separate/fresh SQLite connection for script executions from the admin UI. This prevents any modification of the main connection that's used internally, e.g. dropping attached databases in a multi-DB world.
- Fix default-value form field validation in Create/Alter table form. Previously, it would prevent SQLite functions for some column types. #182 thanks @tingletech.
- Fix visual overflow in SQL script editor for longer scripts.
- Update Rust and JavaScript dependencies.

## v0.21.7

- Move more migration-file-loading from refinery into TB in preparation for multi-DB migrations. At the moment this is a noop.
- Use SQLites's `STRICT` for new migration tables.
- Fix docker alias for Mac.
- Update Rust dependencies, major versions.

## v0.21.6

- Maintenance release to explicitly drop the deprecated V8 integration from the repo.
  - It has been a little over 6 weeks since v0.19, which removed V8 from the trail binary.
  - I wasn't sure how long to keep the code around as an optional feature. However, the latest wasmtime release pins serde to a version that is incompatible with the latest (somewhat stale) deno/V8/SWC dependencies. In other words, updating wasmtime would break the V8 build :/. The state of the dependency chain had been one of the driving factors to move away. While it feels validating, it's a little sad to finally send it into the sunset.
- Update Rust dependencies.

## v0.21.5

- Add "excluded columns" to Admin UI's record API form.
- Add early CLI commands for listing installed components as well as updating them to match the binary release.
- PoC: open-telemetry integration behind a compile-time feature flag. There's still a few integration challenges around how to make metrics available to WASM components.

## v0.21.4

- Fix filter button in admin UI.
- Fix compilation of trailbase library with "wasm" feature disabled.
- Update Rust & JavaScript dependencies.

## v0.21.3

- Admin UI polish:
  - Add dirty state to navbar for prompting a confirmation dialog to prevent accidental loss, e.g. when navigating away from a script editor with pending changes.
  - Enable `col = NULL` and `col != NULL` filter queries from table explorer.
  - Remember previsously selected TABLE/VIEW on table explorer page.
- Minor: always log uncaught errors from user-provided WASM components.
- Update dependencies.

## v0.21.2

- Remove unnecessary and harmful assertions on "invariants", which may be temporarily violated while streaming in rows during schema alterations.
- Make release builds less chatty about uncaught errors in custom user WASM endpoints.
- Minor admin UI tweak: lower z-height of map to avoid rendering on top of dialogs and tooltips.
- Update Rust dependencies.

## v0.21.1

- Very minor release, mostly just improving the error message when encountering ABI incompatible WASM components.
  - This is a bit of a sticky issue, especially if you're using Docker and externally mounting a traildepot path. The docker image packages the matching auth-UI component, however an external mount can shadow it with a stale version. In this case, you've a few options:
    - either download the latest auth UI from https://github.com/trailbaseio/trailbase/releases and manually replace the file,
    - or shell into your container `docker run -it --entrypoint /bin/sh <id>` and use the CLI: `cd /app && ./trail components add trailbase/auth_ui`.
- Layout tweaks in admin UI's auth settings.
- Update Rust and JavaScript dependencies.

## v0.21.0

- Extend WASM component/plugin system: enable custom SQLite extension functions from WASM components.
  - This is unfortunately an ABI breaking change. Interface definitions weren't versioned before and going to versioned itself is breaking :/ - my bad 🙏.
  - The APIs remained stable, so it should be enough to rebuild your components against the latest WASM runtimes and update the auth component if installed (`trail components add trailbase/auth_ui`).
  - We would like to further extend the component model in the future, e.g. to support middleware, which we're in a much better place for now.
- Just for visibility, a lot of admin UI work - especially mobile - went in since the last major release. Maybe worth checking out in case you're interested:
  - A scrollable top nav and collapsible sidebar for better UX on mobile.
  - Configurable OIDC provider.
  - Fixed and simplified CREATE/ALTER table UI.
  - And countless small tweaks. Thanks for all the feedback, especially to BlueBurst on Discord 🙏.
- Updated dependencies.

## v0.20.14

- Allow configuring OIDC provider using admin UI.
- Show associated OAuth providers on accounts page.
- Fix SQL editor's save button and simplify state.
- A few more layout and behavior tweaks.

## v0.20.13

- Admin UI SQL editor improvements
  - Fix delayed execution.
  - Avoid "clipping" overflow in codemirror element. Technically we set overflow to scroll and not clip, however Firefox would still clipped.
  - Allow to permanently disable migration warning.
- Fix theme color for mobile chrome.
- Update JavaScript dependencies.

## v0.20.12

- More admin UI tweaks:
  - auto-close sidebar on item selection on mobile.
  - Tweak layout of CREATE/ALTER column form: more efficient space use, overflow, alignment increased touch target size.
  - Fix OAuth provider deletion.
  - More efficient ERD graph screen use.
- Update Rust dependencies.

## v0.20.11

- Admin UI layout improvements:
  - Switch to solid-ui/shadcn collapsible sidebar, rather than horizontal split fallback on mobile.
  - Make mobile/top-navbar always scroll with content.
  - Avoid editor layout issues by making it not resizable.
  - Move editor script rename/delete buttons into sidebar.
  - Consistent icons everywhere.
- Fix CSP/routing for non-local dev setup (e.g. via mobile).
- Many internal admin UI cleanups: move code around, distribution of column_type responsibility, random name collisions, ... .

## v0.20.10

- Fix regression with column types in CREATE/ALTER table forms.
- Improve & simplify the DEFAULT and CHECK column schema fields. They no longer need to be explicitly toggled and the inputs are validated.
- Improve & fix the generated curl template queries: replace "Null" with null and pre-fill more fields for easier editing.
- Update JavaScript and Rust dependencies.

## v0.20.9

- Overhauled admin UI for rendering file(s) columns: less convoluted, image preview and easy download.
- Support admin file reads from VIEWs.
- Add auth-UI WASM component to default docker image.
- Fix `ALTER TABLE` issue, when table is referenced by views. SQLite sporadically validates consistency, it does so during `ALTER TABLE` (but not `DROP TABLE`).

## v0.20.8

- Fix admin UI drop/alter table regression in v0.20.7. The stricter schema reload validations require us to fix the API config first before reloading schemas.
- Properly catch and display uncaught async rejections in admin UI. In the past we removed the built-in toast from `adminFetch`, which led to fetch errors going quiet, since browsers uncaught error handlers don't handle async rejections.
- Minor: also improve error handler life-cycle to avoid duplicate toast in combination with hot-reload during development.
- Update JS dependencies.

## v0.20.7

- Support literals in `VIEW`-based record APIs, e.g. `CREATE VIEW v AS SELECT id, "literal" AS data FROM 'table'`;
- Disentangle config validation from JSON schema metadata. This allows us to initialize the JSON schema registry from the config before building the metadata, thus letting us remove our double-load work-around and introduce stricter error handling in case of JSON schemas that are referenced but missing.
- Rebuild JSON schema registry when reloading config.
- Make admin UI use bigints when dealing with longs in the config proto.
- Fix OIDC OAuth provider config validation and admin UI's OIDC config handling.
- Minor: have `trail --version` display the bundled SQLite version.
- Update dependencies.

## v0.20.6

- Overhaul internal DB & JSON schema abstractions:
  - Introduce an explicit JsonSchemaRegistry abstractions and injected it where needed, making our initialization order challenges more explicit.
  - Remove unused and redundant JSON schema registry abstractions.
  - Remove TableOrViewMetadata trait in favor of sealed tagged union.
  - Simplify expanded FK column abstractions.
- Fix form input validation issue when inserting/updating records in the admin UI.

## v0.20.5

- Fix initialization order issue with custom schemas. DB schema metadata, which also contains JSON metadata, has to be (re-)loaded after registering custom schemas (#170).
  - The re-loading is a workaround to deal with the fact that config validation currently depends on the same schema metadata. Ideally, we disentangle those and validate against schema metadata that doesn't contain hitherto incomplete JSON metadata.
- More consistently "early" validate all JSON inputs. Previously, serialized JSON was accepted but validated only later by SQLite unlike structured JSON input. We may want to consider disallowing serialized JSON in the future, given it contradicts the JSON schema and we could be more strict.
- Fix error code - return 400 when input is rejected by SQLite column `CHECK` constraint.

## v0.20.4

- Improve admin UI on small screens - still a long way to go:
  - Make admin UI's main navbar responsive, i.e. stick to the top on small screens.
  - Fix preset button overflow in create/alter table forms.
- Move Docker images to MUSL builds instead of pseudo-static glibc. We know that the latter are broken and would crash when looking up a hostname on Alpine, e.g. try to specify the `--address` not as an IP address.
- Clean up cursor encryption code and switch to a more maintained crated, e.g. `aes-gcm-siv` vs `aes-gcm`.
- Update dependencies.

## v0.20.3

- Add **untested** "Sign-in with Apple" OAuth provider. I didn't find a way to test it locally (e.g. Apple doesn't let you have dev services with localhost callbacks). Sadly, committing this code upstream and iterating upstream, is the only way I could think of :/. If you know how, please let me know 🙏.
- Update Rust dependencies.

## v0.20.2

- Disable caching for all SPA admin UI paths and streamline the implementation. The previous "fix" only covered the root path: `/_/admin`.
- Update Rust and JavaScript dependencies.

## v0.20.1

- Fix issue with stale, cached query results in admin SQL editor. The internal representation of SQL values changed with v0.20.0, which means the UI can no longer render the old format. Consequently, the editor could get into an error state that could only be recovered from by deleting the Browser's respective local storage. This update introduces an error boundary that lets users recover by re-executing the query to fetch data in the new format.
- Don't cache static `/_/admin/index.html` asset.
- Update Rust dependencies.

## v0.20.0

- Model types more closely after SQLite's and derive an affinity type. We use it to parse `ANY` columns in the admin UI.
  - As a consequence, `VIEW` column types are now stricter when parsing `CAST` expressions. If you were using non-`STRICT` types, you'll have to update your `VIEW` definition.
- Stop encoding SQLite values as generic JSON for internal APIs, both in admin APIs and between WASM host and guests.
  - This is mostly an internal quality change - improving internal type-safety and simplifying the implementation.
  - Albeit internal, this change affects the serialization format between WASM guests and the host. Consequently, you'll need to rebuild your guest component against the latest guest runtime to avoid skew. The public APIs remained the same except for the JS/TS guest's SQL value definition, which got cleaned up.
  - Changing the admin APIs also meant that the admin dash's insert/update row UI was more-or-less rewritten, with many small edge-cases getting fixed.
- Add `base64` and `base64_url_safe` SQLite extension functions. Can be used, e.g. to `SELECT` on an encoded primary-key.
- Add a switch to the admin UI's table explorer for selecting the `BLOB` encoding: url-safe base64, hex, or mixed (UUID text-format and url-safe base64 otherwise).
- Update dependencies.

## v0.19.2

- Use the `winch` non-optimizing baseline WASM compiler in `--dev` mode to speed-up cold start and reload.
- Add "hot"-reload setups to `examples/wasm-guest-(ts|js)`. Simply run `npm run dev`. This will start a TrailBase server and a file-watcher. The latter will rebuild the WASM component, deploy it and send a `SIGHUP` to the server to trigger a reload.
  - Note that JS/TS WASM components are generally large, i.e. slow to build and slow to load, because a SpiderMonkey JS interpreter is bundled. Using `winch` (see above), reloads take just under 5s on my notebook. Your mileage may vary :hide:.
- Update Rust and JavaScript dependencies.

## v0.19.1

- Use first-class column information when interpreting filter queries when listing records.
- Remove ambiguous parse for booleans from filter query strings.
- Fix handling of i64 range in TS/JS client and Admin UI.
- Update Rust dependencies.

## v0.19.0

- First WASM-only release dropping support for the V8 runtime (technically, custom binary builds can still enable it as a stop-gap but complete removal will follow)
  - The default Linux release is now build with MUSL rather than GLibc and thus truly static and portable.
- Drop support for index-based file reads via `api/records/v1/{api}/{record_id}/files/{column_name}/{uniq_file_name}` in favor of unique filenames following the convention: `{original_stem}_{rand#10}.{suffix}`. This is a breaking change.
  - Before, index-based access for read-after-write access patterns could lead to stale cache reads, which is avoided using unique identifiers.
- Notable updates since the previous major release:
  - Official Kotlin client.
  - Record-based subscription filters (same as record listing). Could - for example - be used to subscribe to changes only within a bound-box.
  - Reworked WASM execution model - shared executor across components for better scalability and work stealing.
  - More comprehensive access rule validation.

## v0.18.5

- Small preparatory release to make sure that a v0.18.x version exists with V8 and all the latest fixes to ease transition.
- Pre-process subscription filter query to check it matches the API/Table schema before accepting the subscription. This reduces late failure-modes and parsing ambiguity.
- Admin UI internally uses unique filenames to access images rather than indexes.
- Push minimal Rust version to v1.88.

## v0.18.4

- Add an official Kotlin client.
- Overhaul Dart client and allow for cheap, shared realtime subscriptions using broadcast streams.
- Add access rules validations to discover misuse of magic `_REQ_`, `_ROW_`, ... in inappropriate methods.
- Avoid `workspace:*` deps for all JS examples to ease copy & paste re-use.
- Update Rust and JavaScript dependencies.

## v0.18.3

- Change WASM execution model to share a single executor across components and allow work-stealing.
  - The prior model was simple with low overhead but would not scale well to many components.
  - Remove `host-endpoint::thread-id`, which doesn't make sense with the new execution model.
- Update Rust dependencies.

## v0.18.2

- Add support for record-filters for realtime subscriptions to Dart and .NET clients.
- Fix parsing of implicit `$and` filter on expressions touching the same column, e.g. `?filter[col0][$gt]=0&filter[col0][$lt]=5`. Thanks @kokroo 🙏.
  - Also further streamline the parsing and allow single element sequences in accordance with QS.
- Restore ability to parse record inputs for `STRICT` tables with `ANY` columns.
- Fix blog example after `FileUpload` changes in previous release (which should have arguably been a major release :hide:)
- Update Rust dependencies.

## v0.18.1

- Allow realtime subscriptions to define record-based filters 🎉. This could be used, e.g. to subscribe to only to changes within a GIS bounding-box. The query API is consistent with listing records. The TypeScript client has been updated to support it.
- Create unique filenames for uploads: `{stem}_{rand#10}.{ext}` and allow accessing their contents using said filename.
  - We may want to deprecate indexed-based access in the future - there's clear advantages for stable unique ids, e.g. for content caching strategies when using a proxy or CDN.
- Address issue with `@tanstack/form`s missing `crypto.randomUUID` #157.
- Update Rust and JavaScript dependencies.

## v0.18.0

- If everything goes to [plan](https://trailbase.io/blog/switching_to_a_wasm_runtime), v0.18.x will be the last releases containing the V8 JavaScript engine. It's time to move to WASM. If you have any issues or encounter any limitations, please reach out 🙏.
- **Remove built-in auth UI** in favor of a matching WASM component. To get the auth UI back, simply run: `trail components add trailbase/auth_ui`. Why did we remove it?
  - Moving the UI into a component in `crates/auth-ui` offers a starting point for folks to **customize or build their own**. We plan to further streamline the process of customization, both in structure and documentation.
  - The component serves as a proof-of-concept for the new WASM compositional model, our commitment and also makes us eat our own dogfood.
  - We hope that the current, extremely basic component management may inform a possible future of a more open plugin ecosystem. We would love to hear your feedback 🙏.
- Update Rust dependencies.

## v0.17.4

- Fix/change JSON file-upload to expect contents as (url-safe) base64 rather than verbose JSON arrays. Also add integration tests - thanks @ibilux 🙏.
- Add very basic WASM component management functionality to the CLI, e.g.: `trail components add trailbase/auth_ui`.
  - Note that this is far from being a third-party plugin system. For now this is barely more than a short-hand to install the auth-ui component in a versioned fashion.
- Add a new `traildepot/metadata.textproto` to persist ephemeral metadata in human-readable form - currently only the previously run version of `trail` to detect version transitions.
- Add an argument to the WASI `init-endpoint` for future-proofing and to pass metadata, e.g. to let a component validate itself against the host version.
- Update Rust dependencies and toolchain to v1.90.

## v0.17.3

- Reload WASM components on SIGHUP in dev mode.
- Fix JSON schema construction for schemas with nested references.
- Small styling fixes for admin UI.
- Update `wstd`, publish updated `trailbase-wasm` crate and update JavaScript dependencies.

## v0.17.2

- PoC: release built-in Auth UI as separate WASM component. In the future we may want to unbundle the UI and allow installing it as a plugin.
- Allow disabling WASM runtime via feature flag in the core crate.
- Improved Rust guest runtime: query param de-serialization and response.
- Update Rust dependencies.

## v0.17.1

- Add an SMTP encryption setting (plain, STARTTLS, TLS).
- Migrate all UIs to Tailwind v4.
- Fix job name encoding for WASM jobs.
- Make examples/wasm-guest-(js|ts|rust) standalone to just be copyable.
- Update Rust & JavaScript dependencies.

## v0.17.0

- Add new WASM runtime based on [wasmtime](https://github.com/bytecodealliance/wasmtime). More information in our dedicated update [article](https://trailbase.io/blog/switching_to_a_wasm_runtime).
  - This is a transitional release containing both the V8 and WASM runtime. The plan is to eventually remove V8.
  - We expect WASM to unlock a lot of opportunities going forward, from increased performance (though JS is slower), strict state isolation, flexible guest language choice, more extensibility... if we peaked your interest, check out the article.
- Update JavaScript and Rust dependencies.

## v0.16.9

- Add support for non-transactional bulk edits to experimental "transaction record API" and expose it in the JS/TS client. Thanks so much @ibilux 🙏.
- Update Rust dependencies.

## v0.16.8

- Allow signed-out change-email verification. This allows validation from a different browser or device, e.g. pivot to phone.
- Fix change-password auth flow.
- Update JS dependencies.

## v0.16.7

- Fix and improve email-template forms in admin UI
  - Fix mapping of form to config fields
  - Allow individual setting of subject or body as well es un-setting either.
  - Check that body contains `{{CODE}}` or `{{VERIFICATION _URL}}`.
- Update Rust dependencies.

## v0.16.6

- Fix slow startup of streaming connections. Previously, clients would consider connections established only after first observed change or heartbeat. Thanks @daniel-vainsencher and meghprkh!
- Fix update-params in experimental record transaction API. Thanks @ibilux!
- Minor: improve tb-sqlite connection setup and support arc locks (backport from ongoing WASM work).
- Simplify JS runtime's handling of transactions.
- Update Rust dependencies.

## v0.16.5

- Add an experimental `/api/transaction/v1/execute` endpoint for executing multiple record mutations (create, update & delete) across multiple APIs in a single transaction.
  - Disabled by default and needs to be enabled in config file (no UI option yet).
  - There's no client-integrations yet. We're looking into how to best model type-safety for multi-API operations.
- Update to JS/TS runtime to deno 2.3.3 level.
- Update dependencies.

## v0.16.4

- Switch to dynamically linked binaries on Linux by default. Statically pre-built binaries are still available.
  - Turns out that glibc, even in static executables, will load NSS to support `getaddrinfo`. The ABIs are less stable than the main shared-library entry-points potentially leading to crashes with "floating point exception" (e.g. Arch).
  - Note that linking statically against MUSL is currently not an option due to Deno's pre-built V8 requiring glibc.
  - Note further that we were already linking dynamically for other OSs due to lack of stable syscall ABIs.
- Update dependencies

## v0.16.3

- Admin settings UI: simplify forms by removing explicit empty string handling, better placeholders, add missing change email templates, ... .
- Internal: add a generalized WriteQuery abstraction tyding up query building but also in preparation of a potential batched transaction feature.
- Update Rust toolchain from 1.86 to latest stable 1.89.
- Update dependencies

## v0.16.2

- Fix regression allowing record updates to alter the primary key. In rare setups, this could be abused. For example, a primary key column referencing `_user(id)` would have allowed users to sign their records over to other users. Now covered by tests.
- Break up input (lazy-)params into separate insert & update params to simplify the individual paths.
- Update dependencies.

## v0.16.1

- Fix cleanup of pending file deletions and add comprehensive tests.
- Override default `--version` flag to yield version tag rather than crates version.
- Cleanup repo: all Rust code is now in a crates sub-directory.
- Update dependencies.

## v0.16.0

- Less magic: parse JSON/Form requests more strictly during record creation/updates. Previously, `{ "int_col": "1" }` would be parsed to `{ "int_col": 1 }`. If you were using type-safe, generated bindings or properly typed your requests, this change will not affect you.
- Rename auth query parameter `?redirect_to=` to `?redirect_uri=` in compliance with RFC 6749. I you are explicitly passing `?redirect_to=`, please update all references.
- Add "Send Test Email" feature to the admin UI.
- Reactively rebuild Record API configuration when database schemas change.
- Update dependencies.

## v0.15.13

- Record sequence of operations when altering table schemas to enable non-destructive column changes.
- Make columns in CreateAlterTable form append-only.
- Chore: clean up foreign key expansion code for Record APIs.
- Update dependencies.

## v0.15.12

- Rebuild Record API config on schema alterations.
- Parse strings more leniently to JSON: all integer, all real types.
- Accept a wider range of primary key values to support more complex `VIEW`s.
- Fix parsing of explicit "null" column constraint.
- Admin UI: clear dirty state on Record API submit and hide `STRICT`ness alteration in alter table form.
- Update dependencies.

## v0.15.11

- Make TypeScript `query`/`execute` database APIs type-safe.
- Consistently serialize/deserialize JS blobs as `{ blob: <urlSafeB64(bytes)> }`.
- Update dependencies.

## v0.15.10

- Significantly broaden the applicability of `VIEW`s for Record APIs.
  - Top-level `GROUP BY` clause can be used to explicitly define a key allowing arbitrary joins.
  - Also allow a broader set of expressions and joins in the general case.
  - Infer the type of computed columns for some simple built-in aggregations, e.g. MIN, MAX.
- Update dependencies.

## v0.15.9

- Auth settings UI:
  - Add explicit _Redirect URI_ for registration with external provider as suggested by @eugenefil.
  - Tidy up walls of help text.
  - Avoid rendering empty errors.
- Fix Gitlab OAuth provider, thanks @eugenefil.
- Unify input parameters and validation between password and OAuth login.
- Many more auth tests.
- Update dependencies.

## v0.15.8

- Support custom URI schmes for auth redirects like `my-app://callback`.
- Stop auto-redirect for signed in users if explicit `?redirect_to` is provided.
- Fix benign ghost session when logging in using PKCE.
- Fix param propagation for OAuth login flow.
- Many more tests and better documentation.
- Minor: clean up the repository of clients.
- Update dependencies.

## v0.15.7

- Add an official Golang client for TrailBase 🎉.
- Support simple sub-queries in `VIEW`-based APIs.
- Fix total `count` for `VIEW`-based APIs.
- Update Rust & JS dependencies.

## v0.15.6

- Make "Dry Run" button available for all table and index schema changes.
- Automatically re-render data table after changing the schema.
- Fix: column preset buttons and add a UUIDv4 preset.
- Update JS and Rust dependencies.

## v0.15.5

- Check out the [TanStack/db](https://github.com/TanStack/db) sync engine, which now officially supports TrailBase 🥳.
- Prevent schema alterations from invalidating Record API configuration, fix up renamed table and error when dropping referenced columns.
- Add dry-run to all the schema altering admin handlers.
- Fix: add missing symlink to assets.
- Update dependencies.

## v0.15.4

- Stricter JSON conversion and better errors for record APIs.
- Automatically fix-up record API config on table renames.
- Update dependencies.

## v0.15.3

- Fix parsing of `VIEW` definitions with elided aliases and handle `VIEW` parsing errors more gracefully.
- Fix `SIGHUP` migration/config order to match startup.
- Fix references in auth Emails.
- Documentation improvements: early schema migration doc, multi-API in UI, use of PKCE, etc.
- Update Rust & JS dependencies.

## v0.15.2

- Fix change email email form. Thanks @eugenefil!
- Admin UI: fix vertical scrolling in SplitView on small screens.
- Update dependencies.

## v0.15.1

- Re-apply migrations on SIGHUP. This allows applying schema changes w/o having to restart TrailBase.
- Polish: add copy&paste to log/user id and vertically align tooltips.
- Add a callout to the SQL editor warning users of schema skew when not using migrations.
- Minor: fix broken documentation link in dashboard.
- Update dependencies.

## v0.15.0

- Overhaul `user` and `admin` CLI commands to additionally support: change email, delete user, set verify status, invalidate sessions.
  - Users can now be referenced both by UUID (string and base64 encoded) and email addresses.
- With the extended CLI surface, disallow update/delete of admin users from the UI, thus reducing the potential for abuse. Priviledge now lies with sys-admins.
- Support install using a one-liner: `curl -sSL https://raw.githubusercontent.com/trailbaseio/trailbase/main/install.sh | bash` in addition to docker.
  - Also overhauled the "getting started" guide making it clearer how easy it is to install vanilla TrailBase and that docker is entirely optional.
- Fix record filtering when `[$is]=(!NULL|NULL)` is the only filter.
- Minor: reduce info log spam.

## v0.14.8

- Add an `$is` operator for filtering records. Allows filltering by `NULL` and `!NULL`.
- Add optional `--public-url` CLI argument and push responsibility of handling absent `site_url` down the stack to OAuth and Email components for more appropriate fallbacks.
- Documentation fixes around getting started with docker and relations.
- Update dependencies.

## v0.14.7

- Allow setting up multiple record APIs per `TABLE` or `VIEW` from with the admin UI. Previously, this was only available manually.
- User-configurable per-API limits on listing records, see config.
- Many small admin UI tweaks.
- Update Rust & JS dependencies.

## v0.14.6

- Render OAuth login options on the server rather than the client. Reduces the
  need for client JS.
- Fix `&redirect_to=` propagation for OAuth login.
- Denormalize `axum_extra::protobuf` and update Rust deps.

## v0.14.5

- Fix `&redirect_to=` propagation for password-based login.

## v0.14.4

- Improve OpenAPI definitions.
- Fix multi-row selection in Admin UI's table view.
- Update dependencies.

## v0.14.3

- Fix issue with listing records from `VIEW`s. We cannot rely on `_rowid_`,
  thus fall back to `OFFSET`. In the future we may add cursoring back for
  `VIEW`s that include a cursorable PK column.
- Minor: add an `limit=5` query parameter to list example queries.

## v0.14.2

- OpenAPI:
  - Include OpenAPI spec output into default builds with only Swagger UI behind
    a "swagger" feature flag.
  - Replace `--port` with `--address` for Swagger UI.
  - Add OpenAPI auth output to docs.
- Update dependencies.

## v0.14.1

- Admin UI:
  - Fix Record API id constraints to allow any UUID after v0.14.0 update.
  - Add more curl examples for record create/update/delete.
  - Fix and improve default value construction.
- More permissive default CORS, allow any headers.
- Update JS dependencies.

## v0.14.0

- Allow truly random UUIDv4 record IDs by relying on AES encrypted `_rowid_`s
  for cursors. UUIDv7, while great, has the problem of leaking creation-time.
  - Note: the encryption key for cursors is tied to the instance lifetime, i.e.
    they cannot be used across instance restarts (at least for now).
- Move user ids to UUIDv4 by default to avoid leaking user creation-time.
  - A bundled schema migration will update the PK to allow any UUID type, this is
    mostly to allow for existing users with UUIDv7 ids to continue to exist.
  - We expect this change to be transparent for most users but may break you,
    if you're relying on user ids being of the UUIDv7. Sorry, we felt this was an
    important change and wanted to rip off the band-aid. If you're having issues
    and are unsure on how to address them, please reach out and we'll help.

## v0.13.3

- Improve RecordAPI settings sheet with tabs, help text, and curl examples.
- Fix state update on key-stroke for input fields in admin UI.
- Minor: inline filter examples.
- Update Rust dependencies.

## v0.13.2

- Fix Admin-UI login form reactivity issue.

## v0.13.1

- Fix index names in admin UI.
- Update JS & Rust dependencies.

## v0.13.0

- Improve authentication and avatar handling (breaking).
  - Remove avatar handling dependence on _special_ `_user_avatar` record API by introducing dedicaed APIs.
    This is a breaking change to the semantics of `/api/auth/v1/avatar*`, which
    affects users of said APIs or `client.avatarUrl()`. Make sure to update to
    the latest JS/TS client (v0.6).
  - We also recommend removing the `_user_avatar` API definition from your `<traildepot>/config.textproto`.
    It's inconsequential to have but no longer needed.
  - Further, `/api/auth/v1/status` will now also refresh tokens thus not only
    validating the auth token but also the session. The JS/TS client uses this to
    asynchronously validate provided tokens.
  - Allow deletion of avatars on `/_/auth/profile`. Also adopt nanostores to
    manage client/user state on the profiles page.
  - Add avatars back to admin UI.
  - Document auth token lifecycle expectations when persisting tokens.
- Update dependencies.

## v0.12.3

- Fix row insertion/update in admin dashboard.
- Fall back to downloading JS deps during build when missing. This helps with vendoring TrailBase for framework use-cases.
- Update dependencies.

## v0.12.2

- Fix unchecked null assertion in admin auth dashboard.
- Update JS dependencies.

## v0.12.1

- Use fully-qualified databases everywhere. Preparation for multi-DB.
- Support for for Maxmind's city-geoip DB and command line to specificy custom
  DB locations.
- Explicitly parse cursor based on schema.
- Show command line in admin dashboard
- Improve admin dash's state management .
- Internal: Reduce dependence on vendored crates.
- Update dependencies including latest version of SQLite.

## v0.12.0

- Overhaul list API filters to allow for nested, complex expressions. The query
  parameters change making is a **breaking** change. Users will need to update
  their client libraries.
  - All clients have been updated to both: support the new syntax and help in
    the construction of nested filters.
  - For raw HTTP users, the filter format went from `col[ne]=val` to
    `filter[col][$ne]=val` following QS conventions.
  - For example, exluding a range of values `[v_min, v_max]`:
    `?filter[$or][0][col][$gt]=v_max&filter[$or][1][col][$lt]=v_min`.
- A new client implementation for the Swift language.
- Show release version in the admin dashboard and link to release page.
- Update dependencies.

## v0.11.5

- Improved admin SQL editor: save dialog and pending change indication.
- Fix short-cut links on dashboard landing page.
- Update dependencies.

## v0.11.4

- Replaced Mermaid-based schema renderer with x6.
- Fix admin UI create-table regression.

## v0.11.3

- Add simple schema visualizer to admin UI. This is a starting point.
- Configurable password policies: length, characters, ...
- Turn admin UI's landing page into more of a dashboard, i.e. provide some
  quick numbers on DB size, num users, ...
- Some small fixes and internal cleanups, e.g. preserve `redirect_to`, simplify
  state management, ...
- Update dependencies.

## v0.11.2

- Rate-limit failed login attempts to protect against brute force.
- Add option to disallow password-based sign-up.
- Fix 404 content-type.
- Fix escaping of hidden form state in auth UI after moving to askama templates.
- Update dependencies.

## v0.11.1

- While JS transactions are waiting for a DB lock, periodically yield back to
  the event loop to allow it to make progress.
- Allow using foreign key expansion on record APIs backed by `VIEW`s.

## v0.11.0

- Support SQLite transactions from JS/TS, e.g.:

  ```ts
  import { transaction, Transaction } from "../trailbase.js";

  await transaction((tx: Transaction) => {
    tx.execute("INSERT INTO 'table0' (v) VALUES (5)", []);
    tx.execute("INSERT INTO 'table1' (v) VALUES (23)", []);
    tx.commit();
  });
  ```

  WARN: This will block the event-loop until a lock on the underlying database
  connection can be acquired. This may become a bottleneck if there's a lot of
  write congestion. The API is already async to transparently update the
  implementation in the future.

- Update rusqlite to v0.35. On of the major changes is that rusqlite will no
  longer quietly ignore statements beyond the first. This makes a lot of sense
  but is a breaking change, if you were previously relying on this this odd
  behavior.
- Overhaul JS runtime integration: separate crate, unified execution model, use
  kanal and more tests.
- Added `trailbase_sqlite::Connection::write_lock()` API to get a lock on the
  underlying connection to support JS transactions in a way that is compatible
  with realtime subscriptions w/o blocking the SQLite writer thread for
  extended periods of time while deferring control to JS.
- Fix benign double slash in some urls.
- Minor: improve internal migration writer.
- Update other dependencies.

## v0.10.1

- Further refine SQLite execution model.
  - Previously reader/writer queues were processed independently. That's great
    for naive benchmarks but not ideal for more real-world, mixed workloads.
  - Use an in-process RwLock to orchestrate access avoiding file-lock congestion.
- Improve Record listing:
  - Support `?offset=N` based pagination. Cursor will always be more efficient when applicable.
  - Updated all the clients to support offset.
  - Error on in-applicable cursors.
  - Error on user-provided `?limit=N`s exceeding the hard limit.
- Fix corner cases for not properly escaped and not fully-qualified filter column names.
- Update dependencies.

## v0.10.0

- Finer-grained access control over exposed APIs on a per-column basis:
  - Columns can be explicitly excluded via a `excluded_columns` config option
    rendering them inaccessible for both: reads and writes. This is different
    from columns prefixed with "\_", which are only hidden from read operations.
  - A new `_REQ_FIELDS_` table is availble during access checks for `UPDATE` and
    `CREATE` endpoints allowing to check for field presence in requests, e.g.
    `'field' IN _REQ_FIELDS_`. A field in `_REQ`\_ will be `NULL` whether it was
    absent or explicitly passed as `null`.
- Early message queue work (WIP).
- Updated dependencies.

## v0.9.4

- Overhaul insert/update row/record form:
  - Integer primary keys are nullable.
  - Explicit nullability for numbers.
  - Ignore defaults for update path.
  - Don't pre-fill defaults.
- Install SIGHUP handler for config reload.
- Update to Rust edition 2024.
- Update dependencies.

## v0.9.3

- Custom JSON stdout request logger to have a stable format as opposed to
  depending on the span/event structure, which is an implementation detail.
- Show response timestamps in dashboard with millisecond resolution.
- Log response timestamp explicitly.
- Improve logs writer performance: no transaction needed, improved statement
  caching.
- Improve incremental release build times by ~70% switching from "fat" to "thin" LTO.
- Update dependencies.

## v0.9.2

- Overhaul SQLite execution model to allow for parallel reads. This should help
  reduce latency long-tail with slow queries.
  - And add more benchmarks.
- Log request/response logs to stdout in JSON format.
- Always re-create traildepot/.gitignore. Previously gated on creating the root
  path, which was never the case for docker users.
- Update dependencies.

## v0.9.1

- Consistently expanded JSON schemas for specific APIs everywhere (UI & CLI).
- Improved foreign table id lookup during schema evaluation.
- Stricter SQL validation in admin UI.
- Break up sqlite and core creates into two additional crates: schema & assets.
- Update dependencies.

## v0.9.0

- Performance:
  - Read and write latency improved both by ~30% 🔥.
  - Memory footprint dropped by ~20% in our insert benchmarks.
  - Build narrower INSERT queries.
  - Use more cached statements.
- Overhaul object-store/S3 file life-cycle/cleanup.
  - Use triggers + persistent deletion log.
  - Retry cleanups on transient object store isues.
  - Fix issue with zombie files on UPSERTs.
- Decouple record APIs form underlying TABLE/VIEW schemas.
- Fix leaky abstractions by pushing tracing initialization into server
  initialization and more strictly separate from logging.
- Update dependencies.

## v0.8.4

- Add a `?loginMessage=` query parameter to admin login page.
- Move query construction for more complex queries to askama templates and add more tests.
- Move subscription-access query construction from hook-time to RecordApi build-time.
- Use askama for auth UI.

## v0.8.3

- Support more SQL constructs:
  - Conflict clause in table and column unique constraints.
  - FK triggers in column constraints.
  - CHECK table constraints.
- Fix: pagination cursors in list queries for arbitrary PKs.
- Sanitize expand and order column names in list queries.
- Update dependencies.

## v0.8.2

- Quote table/index/column names during "CREATE TABLE/INDEX" parsing and construction.
- Improve auth UI: more consistent shadcn styling and explicit tab orders.
- UUID decode sqlite extension and more consistent extension names.
- Update deps.

## v0.8.1

- Derive job id in native code for JS/TS jobs.
- Fix conflict resolution selector in admin UI's API settings.
- Fix primary key card collapsing in create table form.

## v0.8.0

- Add support for periodic cron jobs:
  - Add dashboard to admin UI to inspect, configure and trigger cron jobs.
  - Users can register their own cron jobs from the JS runtime.
  - Replace internal periodic tasks with cron jobs to increase configurability,
    discoverabilty, and avoid drift.
  - BREAKING: removed `backup_interval_sec` from proto config. When explicitly specified,
    users will need to remove it from their `<traildepot>/config.textproto` and set an
    appropriate cron schedule instead.

## v0.7.3

- Cleanup logs DB schema and log ids of authenticated users.
- Allow setting the name and INTEGER type for PKs in create table form.
- Fix reactivity for FK settings in create/alter table forms.
- Add confirmation dialog for user deletions.
- Limit mutations in `--demo` mode.
  - Dedicated admin delete user endpoint.
- Unified parameter building for listing records, users and logs.
- Cleanup backend auth code and query API.
- Update dependencies including rusqlite.

## v0.7.2

- Fix and test OpenId Connect (OIDC) integration.
- Audit and remove unwraps.
- Fix auth img-src CSP for external avatars and dev instances.

## v0.7.1

- Add generic OIDC provider. Can currently only be configured in config. Admin UI integration pending.
- Add --demo mode to protect PII in demo setup.
- Improve secrets redaction/merging.

## v0.7.0

- Schema-aware auto-completion in SQL editor.
- Allow UUID text-encoded 16byte blobs as record ids and in filters during record listing.
- Redact secrets in admin APIs/UI to reduce surface for potential leaks.
- Polish auth/admin UI with image assets for external auth providers like discord, gitlab, ... .
- Permissive `img-src` CSP in auth UI to allow displaying avatars from external auth providers.

## v0.6.8

- Fix client-side merging of fetch arguments including credentials.
- Improved auth UI styling.

## v0.6.7

- Improve token life cycle for JS/TS clients including admin dash.

## v0.6.6

- Add a dialog to avoid accidentally discarding unsaved changes in the SQL editor.
- Polish UI: animate buttons, consistent refresh, avoid logs timestamp overflow.
- Update Rust and JS deps.

## v0.6.5

- Fix routing issues with auth UI.
- Redirect /login to /profile on already logged in.
- Redirect /register to /login?alert= on success.
- Persist execution result in Admin SQL editor.
- Address linter issues.
- Update dependencies.

## v0.6.4

- Add undo history to query editor and improve error handling.
- Cosmetic improvements of Admin UI like more consistency, more accessible buttons, ...
- Indicate foreign keys in table headers.
- Turn table into a route parameter and simplify state management.
- Fix hidden table UI inconsistency.
- Fix input validation issues in form UI.
- Limit cell height in Table UI.

## v0.6.3

- Allow downloading JSON schemas from the UI for all modes: Insert, Update, Select.
- Add some more UI polish: tooltips, optics, and tweaks.
- Improve UI type-safety

## v0.6.2

- Update to address broken vite-plugin-solid: https://github.com/solidjs/vite-plugin-solid/pull/195.

## v0.6.1

- Fix config handling in the UI.
- Improve form handling in the UI.
- Few minor UI fixes & cleanups.
- Update dependencies.

## v0.6.0

- Support foreign record expansion. If a record API is configured allow
  expansion of specific foreign key columns, clients can request to expand the
  parent record into the JSON response of RecordApi `read` and `list`. This is
  also reflected in the JSON schema and warrants a major version update.
  Updates to all the client packages have already been pushed out.
- Support for bulk record creation. This is particularly useful when
  transactional consistency is advisable, e.g. creating a large set of M:N
  dependencies.
- Record subscriptions now have to be explicitly enabled in the
  admin-UI/configuration
- Simplify PNPM workspace setup, i.e. get rid of nesting.
- Fixed rustc_tools_util upstream, thus drop vendored version.
- Reduce logs noise.
- Update dependencies.

## v0.5.5

- Fix build metadata release channel and include compiler version.
- Admin UI: Avoid triggering table's onClick action on text selection.
- Update deps.

## v0.5.4

- Add a `?count=true` query parameter to RecordApi.list to fetch the total
  number of entries.
- Return error on invalid list queries rather than skipping over them.
- Address Admin UI issues:
- Stale config after altering schema or dropping table.
- Out-of-sync filter bar value.
- Reset filter when switching tables.
- Hide "sqlite\_" internal tables in Admin UI.

## v0.5.3

- Built-in TLS support.
- Add "server info" to the admin dashboard, e.g. including build commit hash.
- Update deps.

## v0.5.2

- Add file-system APIs to JS/TS runtime to facility accessing resources, e.g.
  templates for SSR (see example/colab-clicker-ssr).
- Add a timeout to graceful shutdown to deal with long-lived streaming connections.
- Allow short-cutting above timeout by pressing a Ctrl+C second time.

## v0.5.1

- Update SQLite from 3.46.1 to 3.48.0.

## v0.5.0

- Breaking change: RecordApi.list now nests records in a parent structure to
  include cursor now and be extensible for the future.
- Update all the client libraries to expect a ListResponse.

## v0.4.1

Minor update:

- Fix issue with delete table potentially invalidating config due to stale RecordAPI entries.
- Update dependencies.

## v0.4.0

Added an early version of Record change subscriptions, a.k.a. realtime, APIs.
Users can now subscribe to an entire API/table or specific record to listen for
changes: insertions, updates, deletions (see client tests, docs are TBD).

## v0.3.4

- Update Axum major version to v0.8.
- Major overhaul of project structure to allow for releasing crates.

## v0.3.3

- Pre-built Windows binary.

## v0.3.2

- Move record API access query construction to RecordApi construction time.
- Cache auth queries
- Some tweaks and hooks API for trailbase_sqlite::Connection.
- Remove sqlite-loadable and replace with rusqlite functions.
- Reduce allocations.

## v0.3.1

- Fix client-ip logging.
- Wire request-type into logs

## v0.3.0

A foundational overhaul of SQLite's integration and orchestration. This will
unlock more features in the future and already improves performance.
Write performance roughly doubled and read latencies are are down by about two
thirds to sub-milliseconds 🏃:

- Replaced the libsql rust bindings with rusqlite and the libsql fork of SQLite
  with vanilla SQLite.
- The bindings specifically are sub-par as witnessed by libsql-server itself
  using a forked rusqlite.
- Besides some missing APIs like `update_hooks`, which we require for realtime
  APIs in the future, the implemented execution model is not ideal for
  high-concurrency.
- The libsql fork is also slowly getting more and more outdated missing out on
  recent SQLite development.
- The idea of a more inclusive SQLite is great but the manifesto hasn't yet
  manifested itself. It seems the owners are currently focused on
  libsql-server and another fork called limbo. Time will tell, we can always
  revisit.

Other breaking changes:

- Removed Query APIs in favor of JS/TS APIs, which were added in v0.2. The JS
  runtime is a lot more versatile and provides general I/O. Moreover, query APIs
  weren't very integrated yet, for one they were missing an Admin UI. We would
  rather spent the effort on realtime APIs instead.
  If you have an existing configuration, you need to strip the `query_apis`
  top-level field to satisfy the textproto parser. We could have left the
  field as deprecated but since there aren't any users yet, might as well...

Other changes:

- Replaced libsql's vector search with sqlite-vec.
- Reduced logging overhead.

## v0.2.6

- Type JSON more strictly.
- Fix input validation for nullable columns in the insert/edit row Admin UI form.

## v0.2.5

- Addresses issues reported by reddit user _qwacko_ 🙏
  - Fix serialization of foreign key column options.
  - Fix deserialization of TableIndex.
  - Admin UI: Show all tables, including hidden ones, in create-table-form's
    drop down for column foreign-keys.

## v0.2.4

- Allow configuring S3 compatible storage backend for file uploads.

## v0.2.3

- Interleaving of multiple HTTP requests into busy v8 isolates/workers.
- JS runtime:
  - add `addPeriodicCallback` function to register periodic tasks that
    executes on a single worker/isolate.
  - Constrain method TS argument type (`MethodType`).

## v0.2.2

- Enable "web" APIs in JS runtime.
- Add "Facebook" and "Microsoft" OAuth providers.

## v0.2.1

- Allow setting the number V8 isolates (i.e. JS runtime threads) via
  `--js-runtime-threads`.

## v0.2.0

- Add JS/ES6/TS scripting support based on speedy V8-engine and rustyscript runtime.
  - Enables the registration of custom HTML end-points
  - Provides database access.
  - In the future we'd like to add more life-cycles (e.g. scheduled
    operations).
  - In our [micro-benchmarks](https://trailbase.io/reference/benchmarks/) V8
    was about 45x faster than goja.
- Added official C#/.NET client. Can be used with MAUI for cross-platform
  mobile and desktop development.

## v0.1.1

- Changed license to OSI-approved weak-copyleft OSL-3.0.
- Add GitHub action workflow to automatically build and publish binary releases
  for Linux adm64 as well as MacOS intel and apple arm silicone.
- Add support for geoip database to map client-ips to countries and draw a world map.

## v0.1.0

- Initial release.
