Skip to content

Releases: The-Verscienta/kiln_cms

v1.6.0

Choose a tag to compare

@The-Verscienta The-Verscienta released this 28 Oct 21:58

KilnCMS 1.6.0 is the fourth wedge minor on the path to 2.0. Its headline is what readers saw (#1928): the governance trail now shows every publish and withdrawal on one line with its approver, the CDN purge, each endpoint's delivery time, its ?as_of= link and the chain verdict, in the view and in its CSV/JSON exports. Headless draft mode (#1887) lets a front end render a shared draft in its own templates.

It also brings a public change feed (server side), structured :group custom fields, private custom fields, public bylines, LiveBlogPosting and a Google News sitemap, richer media snapshots for native apps, and Kiln.SafeFetch for plugins (kiln_plugin 1.3).

It includes four security fixes. Among them, bandit 1.14.1 fixes EEF-CVE-2026-116078 (HIGH), an HTTP/2 memory amplification every instance is exposed to, and the release image now rebuilds its Debian packages every release.

There are no breaking changes. One Upgrade note is optional (mix kiln.media.resnapshot --apply). Otherwise mix kiln.update, or pinning the image to ghcr.io/the-verscienta/kiln_cms:1.6.0, moves you to it. This is v1.6.0-rc.2, canaried on kilncms.dev, plus the bandit fix.

Long form: docs/changelog/v1.6.0.md —
the 1.6.0 entries as they were written when each change merged.
Every summary line below that was shortened links to its own entry there.

Upgrade notes

  • Optional: run mix kiln.media.resnapshot --apply once after deploying
    so stored :media field values gain dimensions, focal point and variants;
    fired artifacts converge by themselves.
    (#2040 · long form)

Added

  • The governance trail shows what readers saw: each publish and withdrawal
    with its approver, CDN purge, each endpoint's delivery, ?as_of= and chain.

    (#2086 · long form)

  • Public bylines: a :reference field can be the page's schema.org author
    or contributor, on the fired JSON-LD and Kiln's own pages; ProfilePage.

    (#2087 · long form)

  • A link-field filter can name the connection it means: [target]=<id> beside
    the operators asks whether that record has the value.

    (#2081 · long form)

  • Private custom fields: a value only the site's editors and admins see; and
    a :user field type that names a person on the site, always private.

    (#2085 · long form)

  • A type can fire LiveBlogPosting: coverage times plus its published
    updates as liveBlogUpdate, newest first and capped.

    (#2075 · long form)

  • A Google News sitemap at /news-sitemap.xml for NewsArticle types:
    the last 48 hours, at most 1,000 URLs, listed from robots.txt.

    (#2077 · long form)

  • Headless draft mode: a preview token opens its draft on JSON:API and the fired-artifact read.
    (#1887 · long form)

  • A public change feed, server side: KilnCMS.Delivery.Feed publishes
    published / updated / withdrawn per site over PubSub.

    (#2069 · long form)

  • Kiln.SafeFetch (kiln_plugin 1.3): plugins get a covered, SSRF-safe way to fetch a URL they didn't write.
    (#2070 · long form)

  • mix kiln.fields.convert moves JSON-in-text values into a :group field.
    (#2052 · long form)

  • Media in delivered content carries dimensions, MIME type, focal point and variants.
    (#2040 · long form)

  • A :text custom field can also be delivered as plain text.
    (#2037 · long form)

  • ?fields= trims the fired json artifact; a guide to Kiln in a native app.
    (#2039 · long form)

  • A :group custom field holds structured rows: one object, or a list of
    them, keyed by typed sub-fields, with every bad key reported by its path.

    (#2036 · long form)

  • Group fields are edited in the fields admin and the content editor: sub-fields under the group, rows added, removed and dragged into order.
    (#2053 · long form)

  • KilnCMS.Firing.refire/3: a covered way for an overlay to re-fire named records, with their dependents, webhooks and CDN purge.
    (#2068 · long form)

Changed

  • Related content comes back in the order the editor set: JSON:API
    include=related_<type>s, GraphQL related<Type>s and related_links.

    (#2061 · #2064 · long form)

  • A single media custom field is picked from the library drawer, with a
    thumbnail, instead of a dropdown of filenames.

    (#2055 · long form)

  • Fired artifacts are gzipped: their ETag is now weak (W/"…") and
    If-None-Match is compared weakly.

    (#2041 · long form)

  • The opt-in ML stack (KILN_ML=1) moves to Bumblebee 0.8, Axon 0.9 and
    Nx/EXLA 1.0, clearing Axon's type-checker warnings.

    (#2067 · long form)

Fixed

  • Similar content (near-duplicates, tag suggestions) reads a page's searchable
    custom fields, not only its blocks; a fields-only page is no longer "empty".

    (#2096 · long form)

  • mix setup and mix assets.build work on macOS 27.2: tailwind 4.3.3, and
    mix assets.setup re-signs the binary ad hoc when its signature is invalid.

    (#2082 · long form)

  • mix setup, mix assets.setup and mix deps.compile work on OTP 29.1.1,
    loading the CI/Docker httpc header-limit patch into Mix's VM only.

    (#2080 · long form)

  • A release that rolls back no longer announces or notifies what it undid; post-publish broadcasts, notifications, audit anchors and cache busts wait for the release to commit, and content and type cache busts now always run after the commit.
    (#2072 · long form)

  • KILN_VECTOR_SEARCH_EXACT / KILN_HNSW_EF_SEARCH no longer crash-loop a
    deployment whose compiled config sets the other vector_scan: mode.

    (#2060 · long form)

Securit...

Read more

v1.6.0-rc.2

v1.6.0-rc.2 Pre-release
Pre-release

Choose a tag to compare

@The-Verscienta The-Verscienta released this 27 Oct 16:56
e28ee92

Release candidate 2 for 1.6.0. Not for production: it is published as a pre-release, so the admin update page and a plain mix kiln.update never offer it. To try it:

mix kiln.update --to v1.6.0-rc.2

Image: ghcr.io/the-verscienta/kiln_cms:1.6.0-rc.2 (latest stays on 1.5.x).

What changed since rc.1: the release image ships current Debian packages (#2097). Trivy found 87 fixable OS vulnerabilities in rc.1 and finds 0 in rc.2. Similar-content suggestions now also match a page's searchable custom fields (#2096). A kilncms.dev canary on rc.1 does not carry over; soak rc.2 from the start.

These are the notes as they stand under [Unreleased]; the final 1.6.0 condenses them.

Long form: docs/changelog/unreleased.md —
the Unreleased entries as they were written when each change merged.
Every summary line below that was shortened links to its own entry there.

Upgrade notes

  • Optional: run mix kiln.media.resnapshot --apply once after deploying
    so stored :media field values gain dimensions, focal point and variants;
    fired artifacts converge by themselves.
    (#2040 · long form)

Added

  • The governance trail shows what readers saw: each publish and withdrawal
    with its approver, CDN purge, each endpoint's delivery, ?as_of= and chain.

    (#2086 · long form)

  • Public bylines: a :reference field can be the page's schema.org author
    or contributor, on the fired JSON-LD and Kiln's own pages; ProfilePage.

    (#2087 · long form)

  • A link-field filter can name the connection it means: [target]=<id> beside
    the operators asks whether that record has the value.

    (#2081 · long form)

  • Private custom fields: a value only the site's editors and admins see; and
    a :user field type that names a person on the site, always private.

    (#2085 · long form)

  • A type can fire LiveBlogPosting: coverage times plus its published
    updates as liveBlogUpdate, newest first and capped.

    (#2075 · long form)

  • A Google News sitemap at /news-sitemap.xml for NewsArticle types:
    the last 48 hours, at most 1,000 URLs, listed from robots.txt.

    (#2077 · long form)

  • Headless draft mode: a preview token opens its draft on JSON:API and the fired-artifact read.
    (#1887 · long form)

  • A public change feed, server side: KilnCMS.Delivery.Feed publishes
    published / updated / withdrawn per site over PubSub.

    (#2069 · long form)

  • Kiln.SafeFetch (kiln_plugin 1.3): plugins get a covered, SSRF-safe way to fetch a URL they didn't write.
    (#2070 · long form)

  • mix kiln.fields.convert moves JSON-in-text values into a :group field.
    (#2052 · long form)

  • Media in delivered content carries dimensions, MIME type, focal point and variants.
    (#2040 · long form)

  • A :text custom field can also be delivered as plain text.
    (#2037 · long form)

  • ?fields= trims the fired json artifact; a guide to Kiln in a native app.
    (#2039 · long form)

  • A :group custom field holds structured rows: one object, or a list of
    them, keyed by typed sub-fields, with every bad key reported by its path.

    (#2036 · long form)

  • Group fields are edited in the fields admin and the content editor: sub-fields under the group, rows added, removed and dragged into order.
    (#2053 · long form)

  • KilnCMS.Firing.refire/3: a covered way for an overlay to re-fire named records, with their dependents, webhooks and CDN purge.
    (#2068 · long form)

Changed

  • Related content comes back in the order the editor set: JSON:API
    include=related_<type>s, GraphQL related<Type>s and related_links.

    (#2061 · #2064 · long form)

  • A single media custom field is picked from the library drawer, with a
    thumbnail, instead of a dropdown of filenames.

    (#2055 · long form)

  • Fired artifacts are gzipped: their ETag is now weak (W/"…") and
    If-None-Match is compared weakly.

    (#2041 · long form)

  • The opt-in ML stack (KILN_ML=1) moves to Bumblebee 0.8, Axon 0.9 and
    Nx/EXLA 1.0, clearing Axon's type-checker warnings.

    (#2067 · long form)

Fixed

  • Similar content (near-duplicates, tag suggestions) reads a page's searchable
    custom fields, not only its blocks; a fields-only page is no longer "empty".

    (#2096 · long form)

  • mix setup and mix assets.build work on macOS 27.2: tailwind 4.3.3, and
    mix assets.setup re-signs the binary ad hoc when its signature is invalid.

    (#2082 · long form)

  • mix setup, mix assets.setup and mix deps.compile work on OTP 29.1.1,
    loading the CI/Docker httpc header-limit patch into Mix's VM only.

    (#2080 · long form)

  • A release that rolls back no longer announces or notifies what it undid; post-publish broadcasts, notifications, audit anchors and cache busts wait for the release to commit, and content and type cache busts now always run after the commit.
    (#2072 · long form)

  • KILN_VECTOR_SEARCH_EXACT / KILN_HNSW_EF_SEARCH no longer crash-loop a
    deployment whose compiled config sets the other vector_scan: mode.

    (#2060 · long form)

Security

  • **ash 3.37.1 and ash_postgres 2.15.2 fix three tenancy advisories
    (EEF-CVE-2026-115627, -115635, -114214); Kiln was not expo...
Read more

v1.6.0-rc.1

v1.6.0-rc.1 Pre-release
Pre-release

Choose a tag to compare

@The-Verscienta The-Verscienta released this 27 Oct 01:13
26b625b

Release candidate for 1.6.0. Not for production: it is published as a pre-release, so the admin update page and a plain mix kiln.update never offer it. To try it:

mix kiln.update --to v1.6.0-rc.1

Image: ghcr.io/the-verscienta/kiln_cms:1.6.0-rc.1 (latest stays on 1.5.x).

These are the notes as they stand under [Unreleased]; the final 1.6.0 condenses them.

Long form: docs/changelog/unreleased.md —
the Unreleased entries as they were written when each change merged.
Every summary line below that was shortened links to its own entry there.

Upgrade notes

  • Optional: run mix kiln.media.resnapshot --apply once after deploying
    so stored :media field values gain dimensions, focal point and variants;
    fired artifacts converge by themselves.
    (#2040 · long form)

Added

  • The governance trail shows what readers saw: each publish and withdrawal
    with its approver, CDN purge, each endpoint's delivery, ?as_of= and chain.

    (#2086 · long form)

  • Public bylines: a :reference field can be the page's schema.org author
    or contributor, on the fired JSON-LD and Kiln's own pages; ProfilePage.

    (#2087 · long form)

  • A link-field filter can name the connection it means: [target]=<id> beside
    the operators asks whether that record has the value.

    (#2081 · long form)

  • Private custom fields: a value only the site's editors and admins see; and
    a :user field type that names a person on the site, always private.

    (#2085 · long form)

  • A type can fire LiveBlogPosting: coverage times plus its published
    updates as liveBlogUpdate, newest first and capped.

    (#2075 · long form)

  • A Google News sitemap at /news-sitemap.xml for NewsArticle types:
    the last 48 hours, at most 1,000 URLs, listed from robots.txt.

    (#2077 · long form)

  • Headless draft mode: a preview token opens its draft on JSON:API and the fired-artifact read.
    (#1887 · long form)

  • A public change feed, server side: KilnCMS.Delivery.Feed publishes
    published / updated / withdrawn per site over PubSub.

    (#2069 · long form)

  • Kiln.SafeFetch (kiln_plugin 1.3): plugins get a covered, SSRF-safe way to fetch a URL they didn't write.
    (#2070 · long form)

  • mix kiln.fields.convert moves JSON-in-text values into a :group field.
    (#2052 · long form)

  • Media in delivered content carries dimensions, MIME type, focal point and variants.
    (#2040 · long form)

  • A :text custom field can also be delivered as plain text.
    (#2037 · long form)

  • ?fields= trims the fired json artifact; a guide to Kiln in a native app.
    (#2039 · long form)

  • A :group custom field holds structured rows: one object, or a list of
    them, keyed by typed sub-fields, with every bad key reported by its path.

    (#2036 · long form)

  • Group fields are edited in the fields admin and the content editor: sub-fields under the group, rows added, removed and dragged into order.
    (#2053 · long form)

  • KilnCMS.Firing.refire/3: a covered way for an overlay to re-fire named records, with their dependents, webhooks and CDN purge.
    (#2068 · long form)

Changed

  • Related content comes back in the order the editor set: JSON:API
    include=related_<type>s, GraphQL related<Type>s and related_links.

    (#2061 · #2064 · long form)

  • A single media custom field is picked from the library drawer, with a
    thumbnail, instead of a dropdown of filenames.

    (#2055 · long form)

  • Fired artifacts are gzipped: their ETag is now weak (W/"…") and
    If-None-Match is compared weakly.

    (#2041 · long form)

  • The opt-in ML stack (KILN_ML=1) moves to Bumblebee 0.8, Axon 0.9 and
    Nx/EXLA 1.0, clearing Axon's type-checker warnings.

    (#2067 · long form)

Fixed

  • mix setup and mix assets.build work on macOS 27.2: tailwind 4.3.3, and
    mix assets.setup re-signs the binary ad hoc when its signature is invalid.

    (#2082 · long form)

  • mix setup, mix assets.setup and mix deps.compile work on OTP 29.1.1,
    loading the CI/Docker httpc header-limit patch into Mix's VM only.

    (#2080 · long form)

  • A release that rolls back no longer announces or notifies what it undid; post-publish broadcasts, notifications, audit anchors and cache busts wait for the release to commit, and content and type cache busts now always run after the commit.
    (#2072 · long form)

  • KILN_VECTOR_SEARCH_EXACT / KILN_HNSW_EF_SEARCH no longer crash-loop a
    deployment whose compiled config sets the other vector_scan: mode.

    (#2060 · long form)

Security

  • ash 3.37.1 and ash_postgres 2.15.2 fix three tenancy advisories
    (EEF-CVE-2026-115627, -115635, -114214); Kiln was not exposed.

    (#2091 · long form)

  • bandit 1.14.0, jose 1.11.13 and ash 3.37.2 fix twenty advisories,
    bandit's HTTP/2, HTTP/1 and WebSocket issues among them.

    (#2094 · long form)

v1.5.1

Choose a tag to compare

@The-Verscienta The-Verscienta released this 24 Oct 15:06

KilnCMS 1.5.1 is a patch release on the 1.5 line, with fixes only. Upgrade promptly: it ships req_llm 1.29.0, which fixes a CRITICAL advisory. In req_llm 1.24.0, WebSocket streaming did not verify TLS certificates. Kiln's own calls never stream over WebSocket, but a plugin or host app that does was exposed.

Also in this release, JSON:API and GraphQL serve :reference targets under their current slug and title, and the release image builds again under OTP 29.1.1.

There are no upgrade notes and no breaking changes. Run mix kiln.update, or pin the image to ghcr.io/the-verscienta/kiln_cms:1.5.1.

Long form: docs/changelog/v1.5.1.md —
the 1.5.1 entries as they were written when each change merged.
Every summary line below that was shortened links to its own entry there.

Fixed

  • JSON:API and GraphQL serve a :reference field's target under its
    current slug and title, not the ones stored when the referrer was saved.

    (#2059 · long form)

  • The release image builds again under OTP 29.1.1, whose :httpc refused
    GitHub's ~10.7 KB release-redirect headers.

    (#2062 · long form)

Security

  • req_llm 1.29.0 (CRITICAL EEF-CVE-2026-107685: WebSocket streaming
    skipped TLS verification) and plug_crypto 2.2.1 (CVE-2026-105963).

    (#2057 · long form)

v1.5.0

Choose a tag to compare

@The-Verscienta The-Verscienta released this 19 Oct 03:39
6c1924e

KilnCMS 1.5.0 is the third wedge minor on the path to 2.0. It has two headlines.

  • Relationships at Directus/Hygraph parity (relationships-plan.md). A reference field can hold several records of several types, in order, with typed details on each connection, such as the quantity of each ingredient in a recipe. It shows its other side on the records it connects to, and can be edited from either side. It can cap how many records connect to one target and choose what happens when a target is deleted. The fields admin sets a relationship up from both sides. The editor has a search picker with "Add new". The APIs can filter, read and write through relationships, and mix kiln.gen.join graduates one to a typed join table.
  • Propagation records (#1927): every publish and withdrawal is now measured end to end, and mix kiln.propagation reports its p50/p95.

Computed fields gain a formula builder, chaining and today(), and media fields can hold a gallery.

It includes three security fixes. Among them, bandit 1.13.0 fixes EEF-CVE-2026-105660 and -105659, so the app server speaks HTTP/2 again.

There are no breaking changes. After deploying, run a firing sweep once (see the Upgrade note). Otherwise mix kiln.update, or pinning the image to ghcr.io/the-verscienta/kiln_cms:1.5.0, moves you to it.

Long form: docs/changelog/v1.5.0.md —
the 1.5.0 entries as they were written when each change merged.
Every summary line below that was shortened links to its own entry there.

Upgrade notes

  • After deploying, run a firing sweep once (mix kiln.refire_all, or
    KilnCMS.Firing.Sweep.run() over bin/kiln_cms rpc), so artifacts fired
    before 1.5 stop naming draft reference targets and join the re-fire graph.

    (long form)

Added

  • Related content uses the reference picker: search, reorder, remove and
    open, over the record's own type, with the order kept.

    (#2030 · long form)

  • The fields admin asks for a relationship as one: "A relationship", then both
    sides ("Recipe links to Ingredient"), then how many on each side; the field
    list reads it back from both sides in one sentence.

    (#2025)

  • API clients can connect, disconnect and reorder references: GraphQL's
    add<Type>References, remove<Type>References and move<Type>Reference, and
    payload-link routes at /api/json/content-links.

    (#2014 · long form)

  • Reference fields gain max_sources, a limit per target, and
    on_target_delete: keep, clear or restrict on a permanent delete.

    (#2017 · long form)

  • mix kiln.gen.join <type>.<field> graduates a reference field to a typed
    Ash join resource, copies its connections, and retires the field.

    (#2016 · long form)

  • Connections can be added, removed and reordered from the record they point
    at, and each change is saved as an edit of the record that holds it.

    (#2018 · long form)

  • A reference field can name its other side, and every record it connects
    shows the records connecting to it: "Recipes using this ingredient".

    (#2015 · long form)

  • Reads follow reference fields to the records on the other end: GraphQL's
    typed references / referencedBy, and ?expand= on /api/content.

    (#2010 · long form)

  • A reference custom field can carry link fields: typed details on each
    connection, such as the quantity of each ingredient a recipe connects.

    (#2011 · long form)

  • Computed fields can use today's date: today(), years_between, and "Days
    until a date" and "Age in years" recipes, refreshed once a day.

    (#2009 · long form)

  • custom_filter filters through relationships: has, has_all, has_none
    and count on a reference field, and has/has_all/has_none on tags.

    (#2003 · long form)

  • A reference custom field can hold a list of references (multiple: true),
    with optional min_items / max_items.

    (#2000 · long form)

  • A reference custom field can link to several content types
    (target_types).

    (#2004 · long form)

  • The editor fills a reference custom field from a search picker instead of a
    select of up to 500 records.

    (#2002 · long form)

  • The reference picker can create a record and connect it in one step: "Add
    new Type" next to the search.

    (#2005 · long form)

  • Computed fields have a formula builder: pick a recipe and fill in the
    blanks, or write the formula with value and function palettes, and see the
    result live on your own content.

    (#2006 · long form)

  • A computed field can read another computed field: {{ sum(subtotal, shipping) }} over a computed subtotal.
    (#2008 · long form)

  • kilncms.dev now publishes Kiln's security policy at /security, and a
    security notice per published GitHub advisory at
    /security-notices/<ghsa-id>, with a feed.

    (#1873 · long form)

  • Tags, tag groups and categories send webhooks: tag.created, tag.updated,
    tag.deleted, and the same for tag_group and category.

    (#1965 · long form)

  • A release can adopt imported images: bin/kiln_cms rpc 'KilnCMS.Release.adopt_image_backend()'. System → Image backend labels it
    and the Mix task, each with a dry run first.

    (#1988 · long form)

  • A media custom field can hold a gallery: an ordered set of images rather
    than one.

    (#1992 · long form)

  • Every publish and withdrawal is measured end to end: one propagation
    record per transition, mix kiln.propagation for p50/p95, and a telemetry
    event to graph it.

    (#1927 · [long form](https://github.com/The-Verscienta/kiln_cms/blob/v1.5.0/docs/changelog/v1.5.0.md#propagation-...

Read more

v1.4.0

Choose a tag to compare

@The-Verscienta The-Verscienta released this 14 Oct 21:56
bc2137b

KilnCMS 1.4.0 is the second wedge minor on the path to 2.0. Its headline is the retraction guarantee (#1926): an unpublished, archived or deleted webhook can no longer be lost when an endpoint auto-disables. It is retried on its own schedule, and editors are told when it exhausts its retries. Alongside it, plugins can ship as Hex, git or path: dependencies (the kiln_plugin SDK), image uploads can go to an external backend such as Cloudflare Images, and semantic search gets a series of retrieval improvements.

It includes three security fixes. The app server now serves HTTP/1.1 only until Bandit ships a fix for EEF-CVE-2026-105659.

There are no breaking changes. Read the Upgrade notes below if your overlay's Dockerfile runs mix deps.get before copying the whole core. Otherwise mix kiln.update, or pinning the image to ghcr.io/the-verscienta/kiln_cms:1.4.0, moves you to it.

Long form: docs/changelog/v1.4.0.md —
the 1.4.0 entries as they were written when each change merged.
Every summary line below that was shortened links to its own entry there.

Upgrade notes

  • A Dockerfile that runs mix deps.get before copying the whole core must
    also copy config/project_deps_hook.exs, which mix.exs now requires.

    (long form)

  • A Dockerfile that runs mix deps.get before copying the whole core must
    first COPY sdk/kiln_plugin sdk/kiln_plugin; the core's own Dockerfile does.

    (long form)

  • A new, empty table — document_chunk_embeddings — arrives by migration;
    nothing writes to it until chunk_long_documents is turned on.

    (long form)

  • Changing document_prefix (as an e5 model swap does) now needs block
    vectors re-embedded too: mix kiln.embed_all --blocks, or a firing sweep
    (mix kiln.refire_all), as well as documents and tags.

    (long form)

Added

  • A retraction webhook (unpublished, archived, deleted) can no longer
    be lost to endpoint auto-disable, and when one exhausts its retries an
    editor is told.
    (#1926 · long form)

  • An overlay installs dependency plugins through a git-ignored
    config/project_deps.exs, locked in config/project.lock, so the core's
    mix.exs and mix.lock never change.

    (#1967 · long form)

  • Plugins can ship as Hex, git or path: dependencies: the plugin contract
    moved, under the same module names, into its own package, kiln_plugin.

    (#1909 · long form)

  • Advisory checks can ship in a dependency plugin, and mix kiln.gen.plugin --dep scaffolds one.
    (#1909 · long form)

  • A plugin can contribute an image backend (Kiln.ImageBackend) — an
    external service such as Cloudflare Images that takes new image uploads and
    renders their variants and transforms from URLs.

    (#1955 · long form)

  • System → Image backend shows the selected backend's state, whether its
    service answers, and how much of the site's library it holds.

    (#1980 · long form)

  • /api/ask can rerank its merged candidates once instead of each content
    type's, blend the reranker's order with the fused one, and hold a source
    the question names at its fused rank; all off by default.

    (#1973 · long form)

  • The reranker's compiled shape (rerank_batch_size,
    rerank_sequence_length) and how it meets the fused order (rerank_mode,
    SEARCH_RERANK_MODE) are configurable; the defaults are unchanged.

    (#1973 · long form)

  • Semantic search can see past the first 512 tokens of a long record:
    chunk_long_documents embeds the rest of its text in overlapping chunks.

    (#1972 · long form)

  • Hybrid search's relevance floor can judge the any-term (OR) keyword leg's
    hits too, and the floor is a runtime setting.

    (#1970 · long form)

  • mix kiln.embed_all --blocks re-embeds the block index too, so a model,
    pooling or document_prefix change reaches every block vector.

    (#1971 · long form)

  • Search measurement runs can scan vectors at ef_search 200 or exactly
    (KILN_HNSW_EF_SEARCH, KILN_VECTOR_SEARCH_EXACT, --ef-search, --exact),
    and the search eval reports name the scan mode they ran under.

    (#1969 · long form)

Changed

  • The browser suite now drives live co-editing: two peers type into one
    rich-text block and each sees the other's words and caret.

    (#1963 · long form)

  • The reranker reads a record's title and its search_text, not its title
    and excerpt, so a record with no excerpt is no longer judged on its title
    alone.

    (#1973 · long form)

Fixed

  • mix kiln.plugins.doctor's image-backend check no longer reports a plugin's
    backend as undeclared when the plugin module isn't loaded yet.

    (#1955)

  • Clicking a rich-text block's toolbar button keeps the caret in the text, so
    the first letters typed straight after Bold are no longer lost.

    (#1964 · long form)

  • Block vectors and the block search query now get document_prefix and
    query_prefix, so an asymmetric model such as multilingual-e5 embeds the
    block leg to spec.

    (#1939 · long form)

Security

  • The app server answers HTTP/1.1 only: Bandit's HTTP/2 stack is off until a
    fix for EEF-CVE-2026-105659 (an HTTP/2 flow-control DoS) is released.

    (#1985 · long form)

  • prosemirror-view 1.42.6 for GHSA-c8x8-7fp4-3x9w: pasting HTML into the
    rich-text editor can no longer run script.

    (#1956 · long form)

  • The rich-text editor moves to TipTap 3 for GHSA-cp6q-959q-f8rh, and keeps
    underlines it used to drop; a co-editing tab still on the old bundle edits
    solo until it reloads.

    (#1957 · long form)

Full changelog: v1.3.0...v1.4.0

KilnCMS v1.3.0

Choose a tag to compare

@The-Verscienta The-Verscienta released this 12 Oct 23:34
f45a12c

KilnCMS 1.3.0 is the first wedge minor on the path to 2.0. Its theme is that a retraction reaches every reader: a consumer now hears about every page that changes when a document changes, and hears when a published record leaves visibility. It has no migrations, no upgrade notes and no breaking changes. A plain mix kiln.update (or pinning the image to ghcr.io/the-verscienta/kiln_cms:1.3.0) moves you to it.

Added

  • Content webhooks carry data.affected (#1925). This lists the published documents whose fired artifacts embed the changed one, as type, id, slug and locale, so a consumer can invalidate those pages too instead of waiting out a TTL. @kiln-cms/client exports the AffectedDocument type, and KilnClient.Webhook documents the key.
  • Review work queues (#1953). The content list filters on records never reviewed (?reviewed=never) and on records missing a consent kind (?consent_missing=<kind>). The governance dashboard links both as work queues, and both can be saved as views.
  • mix kiln.plugins.doctor notes a plugin with no summary/0 (or the generator's TODO: placeholder), without failing the run (#1942).

Changed

  • A <type>Changed GraphQL subscription now tells anonymous subscribers when a published record is unpublished or archived, as destroyed (#1925). Before this, the policy-scoped read dropped the record as soon as it left :published, so the one event a public reader most needs never arrived. destroyed now means the record left the published feed, whether it was unpublished, archived or deleted.
  • The path forward's wedge minors are renumbered 1.3 to 1.8 (#1945).

Fixed

  • The reranker scores relevance instead of 1.0 for every pair, and a reranker model that cannot be loaded no longer stops Kiln from booting (#1941). This affects KILN_ML=1 builds only.

The long form is in docs/changelog/v1.3.0.md.

v1.2.1

Choose a tag to compare

@The-Verscienta The-Verscienta released this 11 Oct 03:18

KilnCMS 1.2.1 is a patch release on the 1.2 line, and carries one fix. It has no migrations and no upgrade notes. A plain mix kiln.update (or pinning the image to ghcr.io/the-verscienta/kiln_cms:1.2.1) moves you to it.

Fixed

  • A composite custom field no longer blanks every part, and loses what was typed, when one part fails validation (#1923). Once a record had a stored value, a composite field such as a business-hours grid or a geolocation showed every part blank as soon as one part was invalid, and the next change event saved those blanks. In practice, one half-filled day (an opening time with no closing time) could wipe a week of hours an autosave had already stored. The parts now stay as typed while the error shows.

The long form is in docs/changelog/v1.2.1.md.

v1.2.0

Choose a tag to compare

@The-Verscienta The-Verscienta released this 11 Oct 00:48
28d864e

KilnCMS 1.2.0 is a minor release on the 1.x line. It is additive under the 1.0 overlay contract, and it has no database migrations, so rolling the image back to 1.1.0 is clean. A plain mix kiln.update moves you to it; it needs no --allow-major.

Important

The toolchain moves to Elixir 1.20.4 / OTP 29.1.1, with Node 22.23.3 for assets. CI and the release image run exactly these versions. A Docker deploy needs nothing, because the image carries its own runtime. If you build from source, or overlay Kiln with your own .tool-versions, move to the same versions before mix kiln.update. mix.exs now requires elixir: "~> 1.20", so an older Elixir refuses to compile the project.

Before you upgrade:

  1. If you build from source: set .tool-versions to elixir 1.20.4-otp-29, erlang 29.1.1, nodejs 22.23.3 and install them (asdf install / mise install). mix kiln.toolchain.check confirms your declarations agree.
  2. mix kiln.update (or pin the image to ghcr.io/the-verscienta/kiln_cms:1.2.0), then redeploy.

Highlights

  • Toolchain (#1934): one Elixir/OTP/Node for development, CI and production. The split used to hide OTP 29's stricter dialyzer checks from CI, and 1.20's formatter disagreed with CI's 1.19. The image no longer builds assets with Debian's end-of-life Node 18, and its runtime base moves to Debian trixie-20261005-slim.
  • Ghost import (#1876): mix kiln.import.ghost brings over posts, pages, tags, images, SEO fields and bylines, keeps members-only posts gated, and redirects every old URL.
  • Imports from a release: bin/kiln_cms rpc 'KilnCMS.Release.import_wordpress(path, dry_run: true)', along with import_ghost/2 and import_content/2, so a Docker or Coolify deploy can migrate content without a source checkout.
  • Newsletter sign-up block: an email sign-up on any page, with double opt-in. The sign-up and unsubscribe pages now render in the site's own layout.
  • Editor: custom fields sit in the main column, under the blocks.
  • Docs: system requirements with three deployment presets (#1931), "Kiln vs" comparison pages and migration guides, and the path forward (#1924).
  • Security: decimal 3.2.0 for EEF-CVE-2026-97853, and Ash 3.34.6, so an MCP read tool's count/exists/aggregate no longer skips related resources' read policies.

The long form of every entry is in docs/changelog/v1.2.0.md.


Upgrade notes

  • Building from source now needs Elixir 1.20.4 / OTP 29.1.1 (and Node
    22.23.3 for the assets); move your project's .tool-versions to match
    before mix kiln.update.

    (long form)

v1.1.0

Choose a tag to compare

@The-Verscienta The-Verscienta released this 06 Oct 23:53
3b659a2

KilnCMS 1.1.0, the first minor release on the 1.x line. It is additive under the 1.0 overlay contract: nothing covered was removed or changed meaning, and every migration is expand-only. A plain mix kiln.update moves you to it; it needs no --allow-major.

Warning

Search now needs PostgreSQL's unaccent extension. The upgrade migration creates it, so the database role that runs migrations must be allowed to CREATE EXTENSION unaccent; most managed Postgres services allow it. The upgrade also rewrites rows: it refolds non-ASCII search text and writes a link edge for every stored :reference custom field value. Rolling the image back to 1.0.0 is safe (the schema change is expand-only), but those rewritten rows stay as they are.

Before you upgrade:

  1. Take a backup (scripts/backup.sh).
  2. Check that the migration role can create the unaccent extension.
  3. mix kiln.update (or pin the image to ghcr.io/the-verscienta/kiln_cms:1.1.0), then redeploy. Migrations run on boot.
  4. If you later restore a pre-1.1 backup onto 1.1, run mix kiln.links.backfill.

Highlights

  • A content tree (#1597): documents can sit under one another, up to five levels. A structure view lets you drag to reorder and indent to nest. URLs can follow the tree with an [ancestors] alias token, with 301s when a section moves. Published documents that no menu links to are flagged.
  • A reworked content list at /editor (#1904): it opens on a count per stage, rows show author, type and last update with one next step up front, and bulk actions appear when you select rows. Filters by author, category, tag, language and update date can be saved as views (#1593).
  • /editor/organize (#1596): semantic clusters, bulk tag review, an under-organized queue, taxonomy health and search gaps. It appears only with semantic search on.
  • Field-level localization (#1327): a field can be shared across a document's locale variants. Writes to a shared field on a translation are refused (#1860).
  • Content links (#1594): :reference custom fields are also link edges, with Linked from in the editor.
  • Search: diacritics fold, so creme brulee finds Crème brûlée (#1628). Custom fields flagged searchable are indexed as plain text, and a project extractor can decode JSON values and set their order (#1585). Ranking is faster under load (#1725).
  • Ops: per-visitor rate limits behind Fly.io, Railway and DigitalOcean proxies (#1548). A per-site /.well-known/security.txt. Deploy templates for Render, Fly.io and DigitalOcean, pinned to 1.1.0 (#1529); none of them has been verified end to end yet.
  • Security: ash 3.34.4 for EEF-CVE-2026-94201. A content link is readable only by someone who may read both of its ends.

Performance

The 1.0 metric for headless API p95 under 50 ms was partly met: the sync API's first page missed it. In 1.1 that first page stays under 15 ms p95 from 10 concurrent clients (#1713). Search is 14–19 ms p95 alone and 18–60 ms with 10 clients (#1725). Method and corpus are in docs/benchmarks.md.

The long form of every entry is in docs/changelog/v1.1.0.md.


Upgrade notes

  • Search now needs PostgreSQL's unaccent extension; the upgrade migration
    installs it, refolds non-ASCII search rows and rebuilds the title indexes.

    (#1628 · long form)

  • The upgrade writes a link edge for every stored :reference custom field
    value; after restoring a pre-1.1 backup, run mix kiln.links.backfill.

    (#1594 · long form)

Added

  • /editor/organize: semantic clusters, bulk tag review, an under-organized
    queue, taxonomy health and search gaps — only with semantic search on.

    (#1596 · long form)

  • The structure view flags published documents that no menu links to.
    (#1597 · long form)

  • A structure view for arranging a content tree: drag to reorder, indent to
    nest, reachable from the content list for one type at a time.

    (#1597 · long form)

  • A document's URL can follow the content tree: an [ancestors] alias token,
    and moving a section re-derives the paths beneath it without overwriting
    hand-written ones.

    (#1597 · long form)

  • Documents can sit under one another: set a parent from the content editor,
    with cycles, cross-site parents and anything nesting past five levels
    refused.

    (#1597 · long form)

  • System → Plugins says what each plugin adds — its blocks, field types, pages
    and content types by name — and flags a plugin with no summary.

    (#1888)

  • The content list filters by author, category, tag, language, update date
    and review health, sorts by update, publish date or title, and saves a
    filter as a named view.

    (#1854 · long form)

  • On Fly.io, Railway and DigitalOcean, rate limits can be per visitor:
    CLIENT_IP_HEADER reads the platform proxy's own client-address header.

    (#1548 · long form)

  • :reference custom fields are also ContentLink edges: Linked from in
    the editor, broken-reference warnings, and incoming_links on the API.

    (#1594 · long form)

  • Field-level localization: a field can be shared across a document's
    locale variants, or inherited along the site's fallback chain when empty.

    (#1327 · #1860 · long form)

  • Plugin blocks get editor seams: their own label, icon and description,
    field hints, a row editor for item_keys: list fields, and live rendering.

    (#1865 · long form)

  • Each published GitHub release now becomes a page on kilncms.dev at
    /releases/<version>, listed at /releases.

    (#1870 · long form)

  • Each site can publish a /.well-known/security.txt (RFC 9116), set by an
    admin at Configure → Organization → Security contact.

    (#1873 · long form)

Changed

  • The content list opens on a count per stage, rows show author, type and last
    update with one next step up front, and bulk actions appear on selection.

    (#1904)

  • Searchable custom fields are indexed as text: HTML stripped, entities
    decoded, and a project extractor can decode JSON, pick keys and set order.

    (#1585 · long form)

  • Re-indexing search text and storing an embedding no longer move a
    document's updated_at.

    (#1585 · long form)

  • The update check asks kilncms.dev's release feed first and lists the
    release's highlights; GitHub is the fallback, and forks skip the feed.

    (#1877 · long form)

  • **The sync API's first page stays under 15 ms p95 from 10
    ...

Read more