Repository navigation
Releases: The-Verscienta/kiln_cms
Release list
v1.6.0
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 --applyonce after deploying
so stored:mediafield 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
:referencefield can be the page's schema.orgauthor
orcontributor, 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:userfield type that names a person on the site, always private.
(#2085 · long form) -
A type can fire
LiveBlogPosting: coverage times plus its published
updates asliveBlogUpdate, newest first and capped.
(#2075 · long form) -
A Google News sitemap at
/news-sitemap.xmlforNewsArticletypes:
the last 48 hours, at most 1,000 URLs, listed fromrobots.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.Feedpublishes
published/updated/withdrawnper site over PubSub.
(#2069 · long form) -
Kiln.SafeFetch(kiln_plugin1.3): plugins get a covered, SSRF-safe way to fetch a URL they didn't write.
(#2070 · long form) -
mix kiln.fields.convertmoves JSON-in-text values into a:groupfield.
(#2052 · long form) -
Media in delivered content carries dimensions, MIME type, focal point and variants.
(#2040 · long form) -
A
:textcustom field can also be delivered as plain text.
(#2037 · long form) -
?fields=trims the firedjsonartifact; a guide to Kiln in a native app.
(#2039 · long form) -
A
:groupcustom 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, GraphQLrelated<Type>sandrelated_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
ETagis now weak (W/"…") and
If-None-Matchis 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 setupandmix assets.buildwork on macOS 27.2: tailwind 4.3.3, and
mix assets.setupre-signs the binary ad hoc when its signature is invalid.
(#2082 · long form) -
mix setup,mix assets.setupandmix deps.compilework on OTP 29.1.1,
loading the CI/Dockerhttpcheader-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_SEARCHno longer crash-loop a
deployment whose compiled config sets the othervector_scan:mode.
(#2060 · long form)
Securit...
v1.6.0-rc.2
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.2Image: 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 --applyonce after deploying
so stored:mediafield 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
:referencefield can be the page's schema.orgauthor
orcontributor, 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:userfield type that names a person on the site, always private.
(#2085 · long form) -
A type can fire
LiveBlogPosting: coverage times plus its published
updates asliveBlogUpdate, newest first and capped.
(#2075 · long form) -
A Google News sitemap at
/news-sitemap.xmlforNewsArticletypes:
the last 48 hours, at most 1,000 URLs, listed fromrobots.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.Feedpublishes
published/updated/withdrawnper site over PubSub.
(#2069 · long form) -
Kiln.SafeFetch(kiln_plugin1.3): plugins get a covered, SSRF-safe way to fetch a URL they didn't write.
(#2070 · long form) -
mix kiln.fields.convertmoves JSON-in-text values into a:groupfield.
(#2052 · long form) -
Media in delivered content carries dimensions, MIME type, focal point and variants.
(#2040 · long form) -
A
:textcustom field can also be delivered as plain text.
(#2037 · long form) -
?fields=trims the firedjsonartifact; a guide to Kiln in a native app.
(#2039 · long form) -
A
:groupcustom 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, GraphQLrelated<Type>sandrelated_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
ETagis now weak (W/"…") and
If-None-Matchis 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 setupandmix assets.buildwork on macOS 27.2: tailwind 4.3.3, and
mix assets.setupre-signs the binary ad hoc when its signature is invalid.
(#2082 · long form) -
mix setup,mix assets.setupandmix deps.compilework on OTP 29.1.1,
loading the CI/Dockerhttpcheader-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_SEARCHno longer crash-loop a
deployment whose compiled config sets the othervector_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...
v1.6.0-rc.1
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.1Image: 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 --applyonce after deploying
so stored:mediafield 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
:referencefield can be the page's schema.orgauthor
orcontributor, 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:userfield type that names a person on the site, always private.
(#2085 · long form) -
A type can fire
LiveBlogPosting: coverage times plus its published
updates asliveBlogUpdate, newest first and capped.
(#2075 · long form) -
A Google News sitemap at
/news-sitemap.xmlforNewsArticletypes:
the last 48 hours, at most 1,000 URLs, listed fromrobots.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.Feedpublishes
published/updated/withdrawnper site over PubSub.
(#2069 · long form) -
Kiln.SafeFetch(kiln_plugin1.3): plugins get a covered, SSRF-safe way to fetch a URL they didn't write.
(#2070 · long form) -
mix kiln.fields.convertmoves JSON-in-text values into a:groupfield.
(#2052 · long form) -
Media in delivered content carries dimensions, MIME type, focal point and variants.
(#2040 · long form) -
A
:textcustom field can also be delivered as plain text.
(#2037 · long form) -
?fields=trims the firedjsonartifact; a guide to Kiln in a native app.
(#2039 · long form) -
A
:groupcustom 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, GraphQLrelated<Type>sandrelated_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
ETagis now weak (W/"…") and
If-None-Matchis 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 setupandmix assets.buildwork on macOS 27.2: tailwind 4.3.3, and
mix assets.setupre-signs the binary ad hoc when its signature is invalid.
(#2082 · long form) -
mix setup,mix assets.setupandmix deps.compilework on OTP 29.1.1,
loading the CI/Dockerhttpcheader-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_SEARCHno longer crash-loop a
deployment whose compiled config sets the othervector_scan:mode.
(#2060 · long form)
Security
v1.5.1
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
:referencefield'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
:httpcrefused
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
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.joingraduates one to a typed join table. - Propagation records (#1927): every publish and withdrawal is now measured end to end, and
mix kiln.propagationreports 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()overbin/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>Referencesandmove<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
typedreferences/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_filterfilters through relationships:has,has_all,has_none
andcounton a reference field, andhas/has_all/has_noneontags.
(#2003 · long form) -
A reference custom field can hold a list of references (
multiple: true),
with optionalmin_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 computedsubtotal.
(#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 fortag_groupandcategory.
(#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.propagationfor 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-...
v1.4.0
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.getbefore copying the whole core must
also copyconfig/project_deps_hook.exs, whichmix.exsnow requires.
(long form) -
A Dockerfile that runs
mix deps.getbefore copying the whole core must
firstCOPY 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 untilchunk_long_documentsis 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 inconfig/project.lock, so the core's
mix.exsandmix.locknever 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 --depscaffolds 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/askcan 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_documentsembeds 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 --blocksre-embeds the block index too, so a model,
pooling ordocument_prefixchange reaches every block vector.
(#1971 · long form) -
Search measurement runs can scan vectors at
ef_search200 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_prefixand
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
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, astype,id,slugandlocale, so a consumer can invalidate those pages too instead of waiting out a TTL.@kiln-cms/clientexports theAffectedDocumenttype, andKilnClient.Webhookdocuments 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.doctornotes a plugin with nosummary/0(or the generator'sTODO:placeholder), without failing the run (#1942).
Changed
- A
<type>ChangedGraphQL subscription now tells anonymous subscribers when a published record is unpublished or archived, asdestroyed(#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.destroyednow 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=1builds only.
The long form is in docs/changelog/v1.3.0.md.
v1.2.1
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
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:
- If you build from source: set
.tool-versionstoelixir 1.20.4-otp-29,erlang 29.1.1,nodejs 22.23.3and install them (asdf install/mise install).mix kiln.toolchain.checkconfirms your declarations agree. mix kiln.update(or pin the image toghcr.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.ghostbrings 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 withimport_ghost/2andimport_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:
decimal3.2.0 for EEF-CVE-2026-97853, and Ash 3.34.6, so an MCP read tool'scount/exists/aggregateno 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-versionsto match
beforemix kiln.update.
(long form)
v1.1.0
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:
- Take a backup (
scripts/backup.sh). - Check that the migration role can create the
unaccentextension. mix kiln.update(or pin the image toghcr.io/the-verscienta/kiln_cms:1.1.0), then redeploy. Migrations run on boot.- 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):
:referencecustom fields are also link edges, with Linked from in the editor. - Search: diacritics fold, so
creme bruleefindsCrème brûlée(#1628). Custom fields flaggedsearchableare 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 to1.1.0(#1529); none of them has been verified end to end yet. - Security:
ash3.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
unaccentextension; 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
:referencecustom field
value; after restoring a pre-1.1 backup, runmix 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_HEADERreads the platform proxy's own client-address header.
(#1548 · long form) -
:referencecustom fields are alsoContentLinkedges: Linked from in
the editor, broken-reference warnings, andincoming_linkson 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 foritem_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'supdated_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
...