Knowledge Base
Admin

Article statuses field definitions

Edit

Articles in the Knowledge Base move through three statuses. Editors transition them via the buttons in The Editor; the status is also visible as a coloured badge on every row of the admin landing.

Primary status values

The kb_article.status column stores one of three string values, enforced by a CHECK constraint at the schema level.

StatusBadge colourWhere visibleSet by
DRAFTGreyAdmin only.Default state for new articles. Set automatically by **Create draft** on `/admin/new`, or by the agent API import endpoint when `publish: false`.
PUBLISHEDGreenPublic reader, chat-widget, admin.Set by clicking **Publish** in the editor, or by the agent API when `publish: true`. Triggers `revalidatePath` on `/`, `/a/[slug]`, and `/admin`.
ARCHIVEDAmberAdmin only.Set by clicking **Archive** in the editor (only available when status is currently PUBLISHED) or by `POST /api/kb/admin/articles/[id]/archive`.

The pending-draft chip

A separate state lives alongside status: an article can have a draft stashed in the kb_article_draft table even while its public status remains PUBLISHED. This happens whenever an author edits a published article and clicks Save Draft without clicking Publish.

IndicatorWhereMeaning
Amber draft pending chipNext to the status badge in the editor header.The article has both a live published version AND an unpublished draft. The next time you click Publish, the draft replaces the public version.
(no chip)—No pending draft. The editor body matches the public version exactly.

The pending draft body sits in kb_article_draft.body_json. Publish deletes the draft row in the same transaction as the status update — that's how the chip clears immediately after publishing.

Status transitions

FromActionToSide effects
(no row)Create draft / agent import with publish: falseDRAFTkb_article row created, no publication.
DRAFTPublishPUBLISHEDBody sanitised on write, draft row deleted, paths revalidated.
PUBLISHEDSave Draft (after edits)PUBLISHED + draft pendingkb_article_draft row written; the public body unchanged.
PUBLISHED + draft pendingPublishPUBLISHED (chip cleared)Draft body replaces the public body; draft row deleted.
PUBLISHEDArchiveARCHIVEDPublic reader returns 404 for /a/<slug>; chat-widget hides the article.
ARCHIVEDRe-import via agent API with publish: truePUBLISHEDArticle re-appears for readers.

There is no in-UI button to un-archive an article today. The cleanest path is the agent API: import with the same slug and publish: true. Slug is preserved on upsert, so old links keep working.

Visibility matrix

Which status reaches which reader surface.

SurfaceDRAFTPUBLISHEDARCHIVED
Public reader (/, /a/<slug>, /f/<slug>)HiddenVisibleHidden
Chat-widget Help tab (folder tree, search, article view)HiddenVisibleHidden
Admin landing (/admin)Visible (with badge)Visible (with badge)Visible (with badge)
Search API (/api/kb/search)ExcludedIncludedExcluded
Public folder tree API (/api/kb/folders)ExcludedIncludedExcluded
Related articles panelExcluded (never as source or target)IncludedExcluded

The asymmetry is deliberate: archives are almost the same as deletes from a reader's perspective, but the article stays in the database, the slug remains reserved (so a future publish under the same slug works), and managers can audit the historical content.

Related articles