Content Management — User Journeys
Content Management — User Journeys
Section titled “Content Management — User Journeys”Last verified: Session 215 W4 T9 (30 April 2026). S215 update: Journey 5 gains Markdown Batch Ingest UI sub-section (EP2 §1.11) + Publication Review tab sub-journey (§5.2-P4B); Entry Points table grows with two new rows (Markdown Batch Ingest + Publication Review). S210 update: refreshed for S195-S209. Added S198 §1.5 Q&A inline editor (Tiptap ContentEditor for
answer_standard/answer_advanced), S197 §1.19 Source Information accordion (content-type-aware viaSourceMetadata), S197 §1.20 browse persona prompt cards (discriminated-union: filter / search / chipComposite), S206 review cadence editor on metadata sidebar, publication_status lifecycle (§5.2). Prior baseline: S188 (22 April 2026).
Overview
Section titled “Overview”Content management provides the primary interface for adding, viewing, editing, and organising knowledge base content. Users interact with content through browsing, creation, detail views, and reader modes. Role-based permissions determine which actions are available at each step.
Entry Points
Section titled “Entry Points”| Entry Point | Route | Accessible By | Purpose |
|---|---|---|---|
| Browse/Content List | /browse | All roles | Find and filter content |
| Create Content | /item/new | Editor, Admin | 4-tab content creation |
| Item Detail | /item/[id] | All roles | View and edit single item |
| Reader View | Via item detail | All roles | Distraction-free reading |
| Source Documents | Via item detail | All roles | View source file and versions |
| Batch Q&A Import | /item/new (batch tab) | Editor, Admin | Bulk question-answer import |
| Markdown Batch Ingest | /item/new (upload tab; multi-.md) | Editor, Admin | EP2 §1.11 — drag-drop multiple .md files; pre-flight + import phases; Pattern E polling for progress |
| Publication Review | /review?tab=publication-review | Editor, Admin | §5.2-P4B — triage publication_status='in_review' items (which EP2 markdown imports land in for final content) |
| MCP create tool | Claude Desktop / .ai | Editor, Admin | Programmatic create (typed provenance) |
User Journeys
Section titled “User Journeys”Journey 1: Browse and Find Content
Section titled “Journey 1: Browse and Find Content”Actor: All roles Goal: Locate specific content items using filters, search, and persona prompt cards Preconditions: User is authenticated
-
Navigate to browse view
- Route:
/browse - Components:
components/browse/ - What the user sees: Persona prompt cards (S197 §1.20), filter bar with domain/subtopic/content-type/platform/coverage-layer filters, sort controls, grid/list toggle, search bar.
- Route:
-
Cold-start: persona prompt cards (S197 §1.20)
- Action: Click a prompt card on first visit (before any filters applied)
- Card kinds — discriminated-union data model:
kind: 'filter'(8 cards) — applies filter URL params (domain, subtopic, content type, freshness, coverage layer)kind: 'search'(4 cards) — fires semantic search with the card title and adds an entry viaaddRecentSearchkind: 'chipComposite'(1 card — “Browse by domain”) — renders 3 example domain chips (top-3 bycontent_items.primary_domaincount cached 24h viahooks/browse/use-top-domains.ts) plus a “more” action
- Q&A card folds OPS-22 — clicking it IS the Q&A toggle
- Result: List updates immediately based on the card kind
-
Apply filters
- Action: Select domain, subtopic, content type, freshness status, workspace, or tags via the filter panel
- Components:
filter-bar,filter-panel,filter-section, multi-select domain/subtopic/content-type/platform/coverage-layer filters - Hook:
useBrowseFilters,useFilterDraft,useFilterPresets - Result: Content list updates to show matching items; filter badges summarise active filters
-
Save / load filter preset
- Action: Click Save Preset — preset name dialog opens
(
save-preset-dialog) - Result: Preset stored and shown in
preset-bar; reusable via single click; manageable viamanage-presets-dialog
- Action: Click Save Preset — preset name dialog opens
(
-
Select content item
- Action: Click on a content card or row
- Component:
content-card(mountsFreshnessBadge,ReviewCadenceBadge(S206),GovernanceBadge,QualityBadge,DomainBadge,VerificationBadge,PriorityBadge,StarButton) - Result: Navigates to item detail view at
/item/[id]
Variations
Section titled “Variations”- Viewer: Can browse and read but cannot edit or create. AI-mechanism fields (model names, reasoning, tokens) are not visible; classification confidence is not visible.
- Editor: Sees inline edit affordances,
QuickReviewActions, classify content button, classification confidence in the Source Information accordion (admin/editor-only carve-out). - Admin: Sees all editor actions plus delete, supersede, bulk-assign-owner, recalculate-all-freshness.
Edge Cases
Section titled “Edge Cases”- Empty filter results show a helpful empty state with suggestions.
- Content with
archived_atset is hidden from default browse; accessible via the archive filter. - Items with
publication_status='draft'are excluded from default browse (visible only in the Drafts review filter). - Items with
superseded_by != nullare excluded from default search (MCP retrieval defaultsinclude_superseded=false).
Journey 2: Create Content Manually
Section titled “Journey 2: Create Content Manually”Actor: Editor, Admin Goal: Add a new content item to the knowledge base Preconditions: User has Editor or Admin role
-
Start creation flow
- Route:
/item/new - Components:
components/create-content/,app/item/new/new-item-tabs.tsx(4-tab container) - What the user sees: Tabbed interface with four tabs — Write (manual form), URL (web import), Upload (file), Batch (Q&A bulk). Write is the default.
- Route:
-
Select template (optional)
- Action: Choose from available content templates
- Component:
template-selector; Hook:use-content-templates - Result: Form fields pre-populated based on template
-
Fill in content fields
- Action: Enter title, content body, content type, classification fieldset (domain/subtopic), provenance fieldset (source_url / source_file / source_document_id), progressive depth (brief/detail/reference).
- Mobile:
MobileStepIndicatorprovides step navigation on small screens - Validation:
ItemCreateBodySchema(Zod) validates on submit. Optional fields includeskip_dedup(admin-only override; silent-ignore for non-admin) andcontent_owner_id(admin override).
-
Submit
- Action: Click create
- API:
POST /api/items - Pipeline: validate → embed (synchronous for
auto_embed=true) → dedup soft-block → INSERT (with typedingest_source='manual', resolvedcontent_owner_id, optionallypublication_status='draft') → v1 history (DB trigger) → chunk (non-draft only) → classify → summarise → layer inference → quality score → topic suggestion → guide section suggestion - Result: 201 with
id, warnings array, dedup stamp, suggested layer, topic suggestion, guide section suggestions.
Variations
Section titled “Variations”- Q&A content type: Shows additional fields for
answer_standardandanswer_advanced. The route populatesanswer_standardfromcontentso the first PATCH edit doesn’t destroy creation content (Path 1 ss4.6 fix). - Save as draft: Toggling the Save-as-draft control sets
publication_status='draft'. Drafts are excluded from search and only visible in the Drafts review filter. Embedding generation may be deferred viaauto_embed=false. - Admin dedup override: Admin caller can set
skip_dedup: trueto bypass the suspected-duplicate stamp. Non-admin callers’ overrides are silently ignored (no 403). - Admin owner override: Admin caller can set
content_owner_idto any UUID. Non-admin overrides silently force to caller’s userId viaresolveContentOwnerId({ explicit, role, userId }).
Edge Cases
Section titled “Edge Cases”- Duplicate detection may stamp
dedup_status='suspected_duplicate'(MD5 exact match). The insert still succeeds (soft-block). - Pipeline steps that fail non-fatally return in the
warnings[]array rather than blocking creation. content_text_hashisGENERATED ALWAYS— never write it explicitly (PG rejects withcannot insert a non-DEFAULT value into column).
Journey 3: View and Edit Content Item
Section titled “Journey 3: View and Edit Content Item”Actor: All roles (view); Editor/Admin (edit) Goal: Review content details and make inline edits Preconditions: Content item exists
-
Open item detail
- Route:
/item/[id] - Components:
components/item-detail/ - Hook:
use-item-detail-data(master data hook) - What the user sees:
ItemTitleSection,ItemActionBar(Star, Share, Supersede, Delete),ContentBody,MetadataSidebar(Quality Score Breakdown, Review Schedule sub-block viaReviewCadenceEditor, Domain/Subtopic, Owner, Layer/Topic),ContentTabsandCollapsibleSectionproviding tabbed/expandable sub-layout for Provenance, Relationships, Organisation panels, related-content section (RelatedContentSection,RelatedByTags,RelatedByEntities),EntityBadges,TemporalReferencesSection,TableOfContents, the reader-view panel,VerificationHistory,VersionHistory/VersionDiffpanels, and the Source Information accordion at the bottom of the reader (S197 §1.19, content-type-aware).
- Route:
-
Edit content body (Editor/Admin only)
- Action: Click Edit on the content body
- Component:
inline-content-editor(dynamically-imported TiptapContentEditorwith GFM tables) - Hook:
use-inline-field-edit - API:
PATCH /api/items/[id]with{ field, value, regenerate_embedding?, reclassify?, change_reason? } - Result: Content updates; embedding regenerated if requested; new
content_historyrow created with author + change summary
-
Edit Q&A answer fields (Editor/Admin only — S198 §1.5)
- Action: Click Edit on the Standard or Advanced panel
(
qa-answer-display, stable testidqa-answer-panel-{standard,advanced}) - Component:
QAInlineEditor— mounts the same TiptapContentEditorwith GFM tables (single-field-at-a-time) - Per-field save-safety guard: ≥20 % shrink against the per-field baseline blocks the save
- Per-field regen-embedding checkbox in the editor footer threads
regenerate_embedding: trueinto the PATCH body. The flag resets onstartEdit/cancelEdit/ successful save so it cannot leak across fields. - Result: PATCH preserves the
Q: {question}\n\nprefix in the rebuiltcontent_items.content. Read mode renders both fields viaQAPairRenderer → ContentRenderer.
- Action: Click Edit on the Standard or Advanced panel
(
-
Edit a single metadata field (Editor/Admin only)
- Action: Click an editable field in the sidebar (priority, layer, governance review status, owner, tags, lifecycle, etc.)
- API:
PATCH /api/items/[id]with{ field, value } - Result: Field updates in place. Embedding is regenerated if a content-
affecting field changes; reclassification is NOT auto-triggered (warns
the user to call
/classifyseparately).
-
Edit publication status (Editor/Admin only)
- Action: Use the publication status control to transition between
draft,in_review,published,archived - API:
PATCH /api/items/[id]with{ field: 'publication_status', value, fromStatus } - Optimistic-concurrency guard: the route filters
.eq('publication_status', fromStatus)and returns 409 PGRST116 on stale write - Allowed transitions are computed by
lib/governance/publication-transitions.ts::computeAllowedTransitions( fromStatus, role)— the role’s allowednewStatusarray is derived fromfromStatus. - Side effects via
applyTransitionSideEffects(...)— e.g. archiving populatesarchived_at/archived_by/archive_reasonand the bidirectionalenforce_archive_state_consistencytrigger keeps the invariant in sync.
- Action: Use the publication status control to transition between
-
Edit recurring review cadence (Editor/Admin only — S206)
- Action: Open the Review Schedule sub-block in the metadata sidebar
- Component:
ReviewCadenceEditor—<input type="date">for next review date + 5-preset Select (No recurring review / Every 3 months (90) / Every 6 months (182) / Every 12 months (365) / Custom 1-1095) - API:
PATCH /api/items/:idwithfield='next_review_date'or'review_cadence_days' - Result: Updates persist; rollback on network failure restores the
last-persisted value via
lastPersistedDateRef. - ReaderView callers pass
readOnly=true— the editor is hidden.
-
View version history
- Action: Open the History panel
- API:
GET /api/items/[id]/history - What the user sees: Chronological list of versions with change
summaries, change reason (e.g.
initial_ingest,auto_v1_on_insert,owner_change), and author.
-
Rollback to previous version (Editor/Admin only)
- Action: Select a version and confirm rollback
- API:
POST /api/items/[id]/rollback - Result: New version created with content from selected version;
content_historyentry withchange_type='rollback'. Does not modifygovernance_review_statusorpublication_status.
-
Mark superseded (Admin only)
- Action: Open the Supersede dialog (
supersede-content-dialogmounted onitem-action-bar) - API:
PATCH /api/items/:idwith{ field: 'superseded_by', value: uuid|null }— null clears the pointer (un-supersede) - Result: Old row is hidden from default search; superseded_by FK points
to new row;
dedup_statustransitions to'superseded'. Direct ID lookup still returns the row so the UI can surface “this item has been replaced by ”.
- Action: Open the Supersede dialog (
Variations
Section titled “Variations”- Read-only roles: Viewer sees content + read marks + reader view but no edit affordances. AI-mechanism fields are hidden across the entire detail page.
- Keyboard shortcuts:
use-item-detail-shortcutsenables power-user navigation. - Source Information accordion (S197 §1.19): Renders content-type-aware
fields:
- Q&A pairs →
source_fileraw +section_name+ “Imported on DD/MM/YYYY” - Markdown items → ingestion-source label (“Markdown upload”, “URL import”, “File upload”, “Auto-split upload”, “Manual entry”, “Procurement library import”, “RSS feed”)
- Feed articles → feed name + published date via
feed_articles → feed_sourcesjoin - PDFs →
PdfFields(page count + extraction quality) - Email →
EmailFields - Default →
GenericArticleFields
- Q&A pairs →
- AI-visibility carve-out: Editors and admins see
classification_confidenceas a plain-text percentage row. Viewers see nothing. The accordion is collapsed by default and has no AI branding, colour coding, or accompanying mechanism fields.
Edge Cases
Section titled “Edge Cases”- PATCH updates that change content warn about potential classification staleness but do not auto-reclassify.
- Concurrent edits: last write wins for most fields;
publication_statususes optimistic concurrency (409 PGRST116 on stale write). - Saving a Q&A answer with a ≥20 % shrink against the baseline is blocked client-side.
Journey 4: Read Content in Reader View
Section titled “Journey 4: Read Content in Reader View”Actor: All roles Goal: Read content in a distraction-free format Preconditions: Content item exists
-
Open reader from item detail
- Action: Click the reader view toggle on the item detail page
- Components:
components/reader/ - What the user sees: Clean reading layout appropriate to content type
-
Content-type-specific rendering
- PDF:
pdf-reader-view/pdf-viewerwithimage-galleryfor extracted images - Web content:
iframe-viewerfor original source,reader-viewfor extracted markdown - Transcripts:
transcript-readerfor audio/video transcription content - All types:
source-metadatapanel renders the content-type-aware Source Information accordion (S197 §1.19)
- PDF:
-
Mark as read
- Action: Automatic or manual read mark
- API:
POST /api/read-marks(UPSERT idempotent) - Result: Read status tracked per user per item
Variations
Section titled “Variations”- Reader panel:
reader-panelfor side-by-side reading alongside other content. The floating overlay reader was removed in S183 P1-7 (react-rnddependency dropped).
Journey 5: Upload and Ingest Content
Section titled “Journey 5: Upload and Ingest Content”Actor: Editor, Admin Goal: Import content from files or URLs Preconditions: User has Editor or Admin role
Steps — File Upload (ingest_source='upload')
Section titled “Steps — File Upload (ingest_source='upload')”-
Select file
- Route:
/item/new(upload tab) - Component:
file-upload - Hook:
use-file-upload-pipeline - Supported: PDF, DOCX, MD, TXT (max 50MB)
- Route:
-
Upload and process
- API:
POST /api/upload(multipart form-data; admin can passskip_dedup=trueand/orcontent_owner_idUUID via form fields) - 6-step pipeline tracked in
pipeline_runs: validate magic bytes → create item (with typedingest_source='upload') → upload to storage → createsource_documentsrow + link viasource_document_idFK → extract text (PDF: unpdf; DOCX: mammoth → Turndown gfm; MD/TXT: direct read) → date extraction → dedup soft-block → embed → chunk → classify → summarise → quality score → layer + topic + guide section suggestions - Detect re-upload:
detect_reupload(filename, uploaded_by, content_hash)RPC may flagmatch_type='identical'or'new_version'(setsparent_idon the newsource_documentsrow) - What the user sees:
IngestionProgressindicator showing the 6 steps;IngestionSuccessCardon completion
- API:
-
Review result
- Result: New content item created with linked source document
- Warnings: Dedup matches, extraction quality issues, expiry-date auto-
detection (when found, sets
expiry_date+lifecycle_type='date_bound')
Steps — Markdown Batch Ingest UI (EP2 §1.11; ingest_source='upload')
Section titled “Steps — Markdown Batch Ingest UI (EP2 §1.11; ingest_source='upload')”-
Drop multiple
.mdfiles- Route:
/item/new(upload tab) — same tab as the EP3 single-file surface; routing diverges on file count + extension (all.mdand count >1 → batch route; mixed types or single non-.md→ EP3 route) - Component: extension to
components/create-content/upload-tab-content.tsx(detect.md-only multi-file → call/api/ingest/markdown) - Limits: ≤10 files, ≤1 MB per file, ≤5 MB total batch, UTF-8 only
- Route:
-
Pre-flight analysis (analyse phase)
- API:
POST /api/ingest/markdownwithphase=analyse - The orchestrator runs front-matter parse + title extraction + diff-marker scan + dedup pre-check + filename-collision check on each file. NO DB writes.
- User sees an analysis table with per-row flags:
front_matterparse status, computedtitle+ provenance,dedupVerdict.{isDuplicate, ...},sourceFileMatch,diff_markers.warning,draftOrFinalHeuristic,empty. Per-row checkboxes let editors overridedraft_or_finaland mark files forexcluded=true.
- API:
-
Import (import phase)
- User clicks “Import”; UI
POST /api/ingest/markdownwithphase=importand the per-row overrides JSON - Pattern E end-to-end: route blocks for the import duration (~80-100s
for 10 files); UI fires
GET /api/pipeline-runs/:idevery 1-2s in parallel to surface mid-flight progress (“Processing foo-final.md…”) - Per-file pipeline (sequential):
cleanMdxTags()→ dedup pre-check → INSERTcontent_itemswithpublication_statusper D-A (draft/unknown → 'draft';final → 'in_review') →classifyContent()→regenerateChunks()→ push tostored[]and conditionallydedup_flagged[]
- User clicks “Import”; UI
-
Review post-flight summary
- Result: Per-file outcome card showing
stored[],dedup_flagged[],superseded[](forward-compat reserved),skipped_excluded[],errored[]. Note:dedup_flagged[]is a SUBSET ofstored[]— soft-blocked rows ARE inserted withdedup_status='suspected_duplicate'. - Items flagged
finalland inpublication_status='in_review'and are EXCLUDED from defaulthybrid_searchuntil an admin/editor transitions them to'published'via the publication-review tab on/review(Journey 5b below).
- Result: Per-file outcome card showing
Steps — Publication Review tab (Journey 5b — admin/editor)
Section titled “Steps — Publication Review tab (Journey 5b — admin/editor)”After EP2 markdown ingest with final-flagged content (or any other path
that creates publication_status='in_review' items), admins and editors
triage them via the publication-review tab:
- Navigate to
/review?tab=publication-review(the 6th tab in the Radix Tabs surface; default tab isverified-review) - Surface lists items where
publication_status='in_review', newest first by default. - Per-row actions: Approve & publish (PATCH
publication_status='published', item joins default search/browse), Return to draft (PATCH'draft', item stays out of default search), Open in editor (link to/item/[id]). - Both transitions allowed for admin AND editor per
lib/governance/publication-transitions.ts:75-80.
Steps — URL Import (ingest_source='url_import')
Section titled “Steps — URL Import (ingest_source='url_import')”-
Enter URL
- Route:
/item/new(URL tab) - Component:
url-ingest-form
- Route:
-
Fetch and process
- API:
POST /api/ingest/url(10/min rate limit; admin can passskip_dedupand/orcontent_owner_id) - Pipeline: SSRF validate → URL identity dup check (returns
url_already_existswith existing item ref if matched) → fetch + extract via Readability + Turndown gfm → quality check (< 100 chars → 422; < 500 → warning) → embed → dedup soft-block → INSERT (with typedingest_source='url_import', source_url, source_domain, platform=‘web’, thumbnail_url, author_name) → v1 history (trigger) → classify → summarise → quality → inference - Result: Content item created from web page content
- API:
Variations
Section titled “Variations”- MCP create (
ingest_source='mcp_create'): Programmatic create viacreate_content_itemtool. Supports the typed provenance triple (source_url,source_file,source_document_id); legacymetadata.source_documentZod input is rejected. Audit row emitted topipeline_runs(pipeline_name='mcp_create_content_item') on success / partial / draft / auth-fail / catch-all paths via service-role client (S208 OPS-40). - Python URL ingest (
ingest_source='python_url'): CLIpython3 scripts/ingest.py <url>or--file urls.txtfor batch. - Python markdown ingest (
ingest_source='python_markdown'): CLIpython3 scripts/ingest_markdown.py <dir>(supports--dry-run,--limit,--skip-existing,--tag,--author,--auto-supersede,--auto-supersede-dry-run).
Edge Cases
Section titled “Edge Cases”- SSRF validation blocks private/internal URLs (
/api/ingest/url). - DOCX magic-byte validation rejects spoofed extensions (PK\x03\x04 ZIP signature check).
- PDF files over 32MB can be uploaded but not sent to Anthropic Files API for vision analysis.
- Re-upload of existing source documents triggers version detection via
detect_reuploadRPC and creates a newsource_documentsrow withparent_idlinking back to the previous version. metadata.source_documentis preserved on disk (legacy JSONB key) but new writes must go to typed columns.
Journey 6: Batch Q&A Import
Section titled “Journey 6: Batch Q&A Import”Actor: Editor, Admin Goal: Import multiple question-answer pairs at once Preconditions: Q&A data prepared
-
Enter batch data
- Hook:
use-batch-create - Component:
batch-qa-preview-table - What the user sees: Batch input + preview table
- Hook:
-
Submit batch
- API:
POST /api/items/batch(maxDuration 120s) - Auth: Single-use batch token prevents duplicate submissions
- Pipeline per item: INSERT with typed
ingest_source='upload_autosplit'→ v1 history (trigger) → embed → classify → summarise → inference → quality
- API:
-
Monitor progress
- Result: Pipeline run tracked in
pipeline_runstable (pipeline_name='batch_create') - What the user sees: Progress updates as items process sequentially
- Result: Pipeline run tracked in
Steps — Python form-library import (ingest_source='qa_import')
Section titled “Steps — Python form-library import (ingest_source='qa_import')”Stale (flagged for docubot lane): the
scripts/kb_pipeline/Python ingest referenced in this sub-journey (and the formerimport_bid_library.pyentry point) has been superseded by the cocoindex pipeline (scripts/cocoindex_pipeline/); the per-script paths below predate that migration. Theingest_source='qa_import'key literal is unchanged.
-
CLI invocation
- The form-library (Q&A) import path reads
.docxfiles via a Track-Changes-safe document opener and extracts Q&A tables from them.
- The form-library (Q&A) import path reads
-
Pipeline
- For each Q&A pair: dedup check via
check_content_hash_duplicate()+normalise_title_for_dedup()(collapses leading articles for cross- file variant detection) → INSERT (typedingest_source='qa_import') → v1 history (trigger) → post-insert helper (chunks, entity aliases, entity_mentions, entity_relationships, temporal references, layer inference)
- For each Q&A pair: dedup check via
Journey 7: Manage Source Document Versions
Section titled “Journey 7: Manage Source Document Versions”Actor: Editor, Admin Goal: Compare document versions and review changes Preconditions: Source document with multiple versions exists
-
View version chain
- API:
GET /api/source-documents/[id]/versions(viaget_document_version_chainRPC) - Components:
source-document-history,source-document-info - What the user sees: Version timeline with parent-child relationships
(
parent_idFK onsource_documents)
- API:
-
Compute and review diff
- API:
POST /api/source-documents/[id]/diff - Hook:
use-diff-review - Component:
source-document-diff-review,diff-highlighted-text - Diff modes: Q&A mode (Dice coefficient) or full-text (Myers algorithm)
- What the user sees: Side-by-side or inline diff view
- API:
-
Take action on diff
- Actions: Applied, dismissed, or pending_review
- API:
PATCH /api/source-documents/[id]/diff
-
Send to governance review (if needed)
- API:
POST /api/source-documents/[id]/send-to-review - Result: Hands off to quality-governance feature area; banner shown via
reupload-banner
- API:
Role Permissions Summary
Section titled “Role Permissions Summary”| Action | Viewer | Editor | Admin |
|---|---|---|---|
| Browse content | Yes | Yes | Yes |
| Read content / reader | Yes | Yes | Yes |
| View history | Yes | Yes | Yes |
| View layers | Yes | Yes | Yes |
| View effectiveness | Yes | Yes | Yes |
| Mark as read | Yes | Yes | Yes |
| Batch fetch workspaces | Yes | Yes | Yes |
| See classification confidence (Source Information) | No | Yes | Yes |
| Create content | No | Yes | Yes |
| Edit content (inline) | No | Yes | Yes |
| Edit Q&A answer fields | No | Yes | Yes |
| Set / change publication_status | No | Yes (transitions per role) | Yes |
| Set review cadence | No | Yes | Yes |
| Upload / URL import | No | Yes | Yes |
| Batch Q&A import | No | Yes | Yes |
| Archive content | No | Yes | Yes |
| Rollback version | No | Yes | Yes |
| Classify / summarise | No | Yes | Yes |
skip_dedup admin override | No | No (silent-ignored) | Yes |
content_owner_id override | No | No (silent-forced to userId) | Yes |
| Delete content | No | No | Yes |
| Supersede content | No | No | Yes |
| Bulk assign owners | No | No | Yes |
| Recalculate all freshness | No | No | Yes |
MCP update_publication_status to archived/published | No | Per-transition | Per-transition |
Current Limitations
Section titled “Current Limitations”- No optimistic locking on most fields — concurrent edits use last-write-
wins.
publication_statusis the exception (409 PGRST116 on stale write). - Expiry date has no edit UI — two-store architecture with no synchronisation.
- Content templates are code constants, not yet configurable via the
content_templatestable. - Batch review is limited to setting ‘pending’ status only.
- Q&A
contentfield is auto-rebuilt fromanswer_standard+answer_advanced— direct edits tocontentfor Q&A items are overwritten on the next save. - Saved filter presets are scoped to the user; there is no shared/team preset surface.
Related Documentation
Section titled “Related Documentation”- Content Management — Technical Reference
- Content Management — Workflows
- Quality and governance workflows are documented in the quality-governance feature area
- Classification and taxonomy are documented in the knowledge-organisation feature area
- AI-visibility policy:
docs/reference/ai-visibility-policy.md - Schema reference:
docs/reference/SCHEMA-QUICK-REFERENCE.md