Logchef 1.7 is a big one. It makes the metadata store pluggable — run the default single-binary SQLite, or opt into a Postgres backend so multiple replicas share state for high availability. It also ships a redesigned Library for saved queries and collections with a real permission model, turns alerts.enabled into a proper server-wide switch, surfaces token expiry everywhere, and clears a wave of UX bugs — all on Go 1.26.
Heads-up: this release includes one SQLite migration (
000024) and a breaking Library URL consolidation (/logs/saved+/logs/collections→/logs/library, no redirects). Read Breaking changes and How to upgrade before deploying.
✨ What's new
Pluggable Postgres metadata backend (opt-in) (#96)
Logchef's application metadata — users, teams, sources, saved queries, collections, alerts, API tokens, settings, sessions — can now live in Postgres instead of the embedded SQLite file, so multiple Logchef replicas can serve any request off shared state behind a load balancer. This is the groundwork for high availability.
- SQLite stays the default. The zero-config single-binary start is unchanged — you only need Postgres if you run more than one replica.
- Select it with
database.driver = "postgres"and a[postgres]DSN (orLOGCHEF_DATABASE__DRIVER/LOGCHEF_POSTGRES__DSN). - Postgres migrations take a PostgreSQL advisory lock, so concurrent replica boots don't race — one migrates while the others wait, then all proceed.
- Your logs always stay in ClickHouse and are unaffected by this choice.
- Both backends sit behind a backend-agnostic store contract, validated by a shared conformance suite that runs against both databases in CI.
See the Database Backends & HA guide — including the current caveat that alert evaluation must run on exactly one replica.
Redesigned Library
Saved queries and collections are now one place, with a real permission model.
- Unified
/logs/library— a collections rail on the left, the selected collection's detail on the right. Replaces the old three views (/logs/saved,/logs/collections,/logs/collections/:id) with a single nav item. - Collection editor role — collections now have
owner/editor/member. Editors curate and edit the collection's queries; owners also rename/delete and manage members. - Delegated edit — you can edit a saved query if you're its creator, a global admin, or an owner/editor of a shared collection that contains it. Delete stays creator/admin-only.
- Curate as any participant — pin, move, and remove queries in a shared collection without owning it.
- Anyone can create collections — the old team-admin gate is gone; per-collection roles are the authority.
- Inline save-to-collection — the Save dialog has a collection picker (defaults to your personal collection), so a new query lands where you want in one step.
- Collection detail upgrades — an "Add query" search picker to pin an existing query, "Move to another collection" per query, and a "Created by" column.
- Affordances match your permissions — the server sends
can_edit/can_deletehints so the UI shows the right actions instead of guessing (and never offers one that would 403).
"All Queries" browse for admins
GET /api/v1/saved-queries?scope=all (global-admin only) lists every saved query — including ones not pinned to any collection, which previously had no browse surface. Each row is marked runnable for the caller; queries on sources you can't reach show locked. The default source-gated response used by the explorer dropdown and CLI is unchanged.
alerts.enabled — a real server-wide switch (#98, fixes #97)
Setting alerts.enabled = false (or LOGCHEF_ALERTS__ENABLED=false) used to only stop the evaluation scheduler while the API and UI stayed fully live — a confusing "half-off" state. Now a middleware gates the whole subsystem: every /api/v1/alerts/* route (plus the admin test-email / test-webhook endpoints) returns a clean 503, and /api/v1/meta exposes alerts_enabled so the UI hides alerting entirely. Handy for exploration-only deployments, or to keep alert evaluation on a single instance in a multi-replica setup.
Token expiry, everywhere
The service-tokens admin page now shows the same expiry status as the profile API-token list — never expires / expires / expiring soon / expired — via a shared helper. The API-token model gained a computed expired flag so consumers don't re-derive it, and the CLI flags an expired saved token in logchef auth current.
Searchable pickers & sortable tables
A reusable type-to-filter picker replaces plain dropdowns for inviting collection members and adding service accounts to teams, and the Manage Sources and team-member tables gain a search box and sortable columns.
🛠️ Fixed (vs v1.6.1)
- Inline 403s no longer bounce you to a full-page Forbidden view — an access error on an inline action (toggle, save, delete) now shows a toast and stays put; page-level access is still enforced by the router.
- Dead toggles across the app work again — Switch/Checkbox controls were bound to
:checked/@update:checked, but the underlying reka-ui primitives only exposemodel-value, so the admin Active toggle, alert enable/disable, source TLS/auth switches, the column selector, and variable multi-selects all silently no-op'd. Rebound tomodel-value. - Saved-query resolver no longer panics on certain resolve paths — it recovers and returns a clean error.
- Saved queries wait for the source schema before running, so opening one no longer races the previously selected source.
- Accurate access status codes —
404only when something's missing,403when the recipient lacks team access (exports & shared queries). - Save dialog only offers collections you own (adding an item is owner-only, so it no longer saves the query and then silently 403s on the pin), and the item Remove button gates on the current collection's ownership.
- Tighter memory accounting on large responses (fixes an under-count from the performance pass), plus a cancellable field-value fan-out and identifier validation on provisioned source database/table/field names.
- Provisioned member users get
account_typeset correctly. - UI/URL polish — bare
/logs/libraryis canonical (click vs reload no longer differ), the add-query dialog no longer overflows,?view=allis preserved, and the date-picker type drift is fixed (TypeScript checks are green and enforced in CI again).
💥 Breaking changes
Library URL consolidation. The three saved-query / collection views are collapsed into one, with no redirects from the old paths:
| Old | New |
|---|---|
/logs/saved
| /logs/library
|
/logs/collections
| /logs/library
|
/logs/collections/:id
| /logs/library (select the collection in the rail)
|
/logs/saved/:queryId is kept as the canonical share / explorer-hydration link. Update any bookmarked or documented old collection URLs.
Collection creation is no longer team-admin-gated — any authenticated user can create a collection; per-collection roles (owner / editor / member) govern everything after that.
🗃️ Migration notes
| Backend | Migration | What it does |
|---|---|---|
| SQLite | 000024
| Rebuilds the collection_members role CHECK to owner | editor | member (adds the collection editor role). Existing rows preserved. Applied automatically on upgrade from 1.6.1.
|
| Postgres | 000001_init
| Fresh Postgres backends create the full schema in a single advisory-lock–guarded init migration. |
Take a backup of your SQLite database before upgrading. Migrations are forward-only.
How to upgrade
Binary — download the v1.7.0 binary, stop the service, replace the binary, start it. The 000024 SQLite migration applies on first boot; no config changes are needed to stay on SQLite.
Docker
docker pull ghcr.io/mr-karan/logchef:v1.7.0
docker compose down
docker compose up -dPostgres (optional, for HA) — read the Database Backends & HA guide first, then set database.driver = "postgres" with a [postgres] DSN. Run alert evaluation on exactly one replica until leader election lands.
Full changelog: v1.6.1...v1.7.0