First Class Modules
Knowledge Core
Turns tenant knowledge into owned, revisioned, reviewable records that connect to business context, answer questions, support permission-aware AI/RAG, and learn safely from resolved support work.
module.knowledge-articlesUse Knowledge Core for policies, procedures, product help, FAQs, playbooks, support resolutions, and other maintained reference material whose ownership, revision, freshness, audience, and AI use must remain explicit.
The bundled renderer key is module.knowledge-articles. First-class means BuildWithHQ supplies a native, typed, secured runtime experience inside normal app provisioning and the signed-in user's existing permissions.
What it does
Turns tenant knowledge into owned, revisioned, reviewable records that connect to business context, answer questions, support permission-aware AI/RAG, and learn safely from resolved support work.
Key capabilities
- Create Draft knowledge and publish or archive it through permission-checked lifecycle actions.
- Preserve immutable revisions, publication history, authority, AI eligibility, and optimistic-concurrency evidence.
- Assign one primary accountable owner to a user or DataRole and schedule recurring review work.
- Relate knowledge to any authorized
RecordIdand retrieve bounded contextual knowledge without copying the business record. - Capture unanswered questions, repeated occurrences, usage, feedback, and secured knowledge-gap signals.
- Register only Published, AI-eligible revisions for secured semantic/multimodal retrieval with exact citations.
- Bring current support knowledge into fenced GoClaw Inbox context and turn resolved cases into sanitized Draft candidates.
Ownership, revisions, and lifecycle
Each item remains one canonical Record and Knowledge Core item. Its lifecycle is Draft, Published, or Archived; publication and archive are explicit permission-checked actions. Editing creates an immutable revision instead of erasing the evidence behind an earlier answer or citation. Stale browser updates are rejected through the item's expected update timestamp.
An active primary owner is either a named user or a DataRole, never an ambiguous mixture. Ownership makes review and escalation accountable without granting the owner access beyond normal tenant, DataRole, record, field, and location rules.
Reviews and freshness
A review policy sets the interval, due-soon window, stale threshold, and whether a review Task is created. Due work appears through the existing Tasks and Universal Inbox attention surfaces. An authorized reviewer can confirm the current revision, revise and republish it, reassign the review, or archive the item. Confirming current schedules the next review without pretending the content changed.
Freshness is evidence, not decoration. Current, due-soon, due, and stale states help users and AI distinguish maintained guidance from material that needs review. Stale content does not silently become authoritative merely because it still matches a search.
Relations and contextual knowledge
Knowledge can be linked to a customer, product, case, work order, conversation, file, or any other authorized RecordId. Related and contextual reads traverse the existing secured record graph within bounded depth and result limits. A relation improves context; it never grants access to either endpoint.
Questions, feedback, and knowledge gaps
When a user or GoClaw cannot find authoritative evidence, Knowledge Core records a question instead of fabricating an answer. Repeated occurrences are grouped inside the same tenant and may be assigned, answered, closed, or converted into a normal GeneratedCandidate Draft for review.
Usage and feedback such as helpful, outdated, or incorrect remain linked to the visible item and context. The health view combines repeated questions, weak/no-evidence retrieval, negative feedback, stale high-use sources, overdue reviews, and missing owners into secured gap signals. Aggregate counts never reveal an inaccessible question or source.
Secured AI, RAG, and citations
Only an explicitly Published and AI-eligible revision enters the canonical AI source, document-element, chunk, visual-index, and embedding pipeline. Tenant, CanAiReadRecords, DataRole, location, record, and field security are applied before model context is assembled and again when stored record identities are returned.
Answers retain the Knowledge item, immutable revision, authority, publication/review freshness, source, page, and visual evidence needed for a citation. Contextual record links can improve ranking, but relevance never grants access. Draft, archived, deleted, AI-excluded, or unauthorized material is absent from normal retrieval.
Universal Inbox, GoClaw, and support learning
Universal Inbox remains the support attention layer. GoClaw must hold the current claim/lease and exact ActivityVersion before assembling secured support context. Customer-visible citations include only support-eligible sources the represented user may disclose; internal-only knowledge is omitted. Read-only diagnostics can describe current account state, while RAG explains how the system should work. Neither authorizes a mutation.
After a case is Resolved or Closed, the controlled learning path accepts structured symptom, product area, likely cause, diagnostic steps, verified resolution, and affected-version fields—not the raw transcript. The support-resolution-v1 sanitizer removes credentials, secrets, PII, and tenant-specific identifiers. The result is an idempotent SupportResolution Draft with GeneratedCandidate authority, a source Inbox/version link, one owner, and a review Task. It remains unavailable to normal RAG until an authorized human reviews, marks it eligible, and publishes it.
OpsAtlas — AI Operational Knowledge Core
Your company’s operating knowledge, mapped and available on demand.
OpsAtlas is the thirteenth Build This product pattern and a complete product experience built on Knowledge Core. It turns SOPs, policies, manuals, training, system documentation, and hard-won tribal knowledge into maintained operating memory for employees and permission-bound AI assistants.
What OpsAtlas can do
- Ingest approved SOPs, policies, manuals, training material, system documentation, and tribal knowledge.
- Chunk, embed, version, and relate that knowledge while retaining source and revision evidence.
- Respect department, DataRole, location, record, field, and
CanAiReadRecordspermissions before retrieval or model context. - Give employees evidence-backed answers to How do we do this? with exact sources, revisions, and freshness.
- Launch the appropriate BuildWithHQ workflow from an answer while preserving action permission, approval, and current-context checks.
- Give GoClaw agents and approved MCP tools the permitted operational context they need before they plan or act.
- Reduce repetitive internal questions and accelerate employee onboarding.
- Standardize procedures across teams and locations without flattening their access boundaries.
- Preserve institutional knowledge when employees, contractors, or specialists leave.
- Identify unanswered questions, weak answers, stale sources, negative feedback, and documentation gaps.
The continuous knowledge flywheel
| Stage | What happens |
|---|---|
| Capture | Bring approved operating sources and reusable support knowledge into accountable collections. |
| Understand | Extract text and visual evidence, create revisions, relate business context, and build secured semantic indexes. |
| Retrieve | Return the strongest authorized current guidance with citations, freshness, and explicit gaps. |
| Act + Improve | Start governed workflows, collect usage and feedback, answer questions, and route Draft improvements to their owners. |
Capture → Understand → Retrieve → Act + Improve is continuous: each real question or support outcome can reveal what should be reviewed, clarified, or added next without automatically promoting private or generated material.
OpsAtlas and CompanyIQ answer different questions
| Product pattern | Primary question | Focus |
|---|---|---|
| OpsAtlas | How do we operate? | Current procedures, policy, training, operating guidance, evidence, and the governed workflow that follows. |
| CompanyIQ | What is happening in the business, and where is the opportunity? | Signals, company context, risks, opportunities, evidence-backed insights, and reviewable next actions. |
The two products can share BuildWithHQ’s secured records, relationships, AI retrieval, and action foundations. OpsAtlas organizes the business’s operating memory; CompanyIQ uses permitted business evidence to understand change and opportunity.
Common uses
- Owned product documentation, policies, procedures, FAQs, and employee help.
- Customer-safe help centers and support answers with exact current citations.
- Contextual playbooks linked to customers, products, cases, work orders, files, and conversations.
- Permission-aware AI/RAG sources whose authority and freshness must be inspectable.
- A controlled support learning loop that turns reusable resolutions into reviewable Drafts.
How it connects
Knowledge Core composes with Files and Web Links for source evidence, Record Relations for business context, Tasks and Universal Inbox for review/support attention, GoClaw for fenced assistance, and the existing AI ingestion/retrieval chain for cited answers. The Knowledge item and immutable revision remain the source of truth throughout.
Where applicable, its records use the universal RecordId conventions so they can participate in secured relationships, activity history, favorites, dynamic fields, notifications, Inbox attention, and global search without copying the source record.
Security and data boundary
Every list, item, relation, review, question, feedback, support-context, and AI path derives the SaaS app, tenant, user, DataRole, location, record, field, and permission scope from verified server identity. CanAiReadRecords is required before AI context. Publication, ownership, review, support learning, and archive actions have separate permission checks; customer-visible context excludes internal-only sources.
- The authenticated service derives the SaaS app, tenant account, user, DataRole, and location scope; browser identifiers are never authorization proof.
- The page editor composes React components with validated data bindings. Those bindings call typed runtime APIs, whose application services execute reviewed stored procedures.
- List, search, detail, relation, activity, favorite, and write operations reapply their required server-side permissions.
Add it to an app
- Open the SaaS app in the Developer Console and add the validated
module.knowledge-articlesblock to the pages and existing user-type menus that need Knowledge Core. - Create collections around reader/support journeys and assign their audience, default owner, review policy, and existing DataRole/location visibility.
- Create or migrate source items as Drafts, confirm their authority and AI/support eligibility, then publish through the reviewed lifecycle.
- Link knowledge to relevant Records, configure the review worker/Tasks and Inbox attention, and enable GoClaw support context only for permitted users and queues.
- Test Draft/Published/Archived visibility, revision restore, stale updates, owner review, questions/feedback, cross-tenant/location denial, AI-read denial, internal-source exclusion, exact citations, stale Inbox activity, and Draft support learning before publishing an exact app version.
Copy/paste the native knowledge page
The native block is the compatibility reader/editor for searchable articles, drafts, detail, dynamic fields, relationships, activity, and favorites. Paste it for the fastest page. Use the custom Knowledge Core workspace below when you need explicit lifecycle, ownership, reviews, questions, and health:
{
"blocks": [
{ "_id": "knowledge-library", "_type": "module.knowledge-articles", "props": {}, "children": [] }
]
}
Custom unstyled Knowledge Core workspace
This uses the version 2 Knowledge Core contract. Search, lifecycle, type, location, and pagination are applied by sp_kc_ListKnowledgeItemsSecured; the component receives only its authorized page.
import { FormEvent, useEffect, useState } from "react";
import type { KnowledgeCoreDetail, KnowledgeCoreList, KnowledgeHealth, KnowledgeLifecycleStatus } from "@buildwithhq/module-sdk";
import { getKnowledgeCore, getKnowledgeHealth, listKnowledgeCore } from "./api";
const empty: KnowledgeCoreList = { contractVersion: 2, pageNumber: 1, pageSize: 50, totalRecords: 0, totalPages: 0, canCreate: false, canManage: false, items: [] };
export function KnowledgeCoreWorkspace({ locationId = "" }) {
const [draftSearch, setDraftSearch] = useState("");
const [search, setSearch] = useState("");
const [lifecycle, setLifecycle] = useState<KnowledgeLifecycleStatus | "">("");
const [knowledgeType, setKnowledgeType] = useState("");
const [page, setPage] = useState(1);
const [result, setResult] = useState<KnowledgeCoreList>(empty);
const [health, setHealth] = useState<KnowledgeHealth | null>(null);
const [selected, setSelected] = useState<KnowledgeCoreDetail | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const controller = new AbortController();
Promise.all([
listKnowledgeCore(search, lifecycle, knowledgeType, controller.signal, locationId, page, 50),
getKnowledgeHealth(controller.signal),
]).then(([items, status]) => { setResult(items); setHealth(status); })
.catch((caught: unknown) => { if (!controller.signal.aborted) setError(caught instanceof Error ? caught.message : "Knowledge could not be loaded."); });
return () => controller.abort();
}, [knowledgeType, lifecycle, locationId, page, search]);
function submit(event: FormEvent) { event.preventDefault(); setPage(1); setSearch(draftSearch.trim()); }
async function open(recordId: string) { setSelected(await getKnowledgeCore(recordId)); }
return <section className="knowledge-core">
<h1>Knowledge Core</h1>
{health && <p>{health.publishedCount} published - {health.reviewDueCount} reviews due - {health.openQuestionCount} open questions - {health.staleCount} stale</p>}
<form role="search" onSubmit={submit}><label>Search<input value={draftSearch} onChange={e => setDraftSearch(e.target.value)} /></label><label>Lifecycle<select value={lifecycle} onChange={e => { setPage(1); setLifecycle(e.target.value as KnowledgeLifecycleStatus | ""); }}><option value="">All</option><option>Draft</option><option>Published</option><option>Archived</option></select></label><label>Type<input value={knowledgeType} onChange={e => { setPage(1); setKnowledgeType(e.target.value); }} /></label><button>Search</button></form>
{error && <p role="alert">{error}</p>}
<ol>{result.items.map(item => <li key={item.recordId}><button onClick={() => void open(item.recordId)}><strong>{item.title}</strong><span>{item.lifecycleStatus} - {item.authorityLevel} - {item.freshnessStatus}</span><small>Revision {item.currentRevisionNumber}{item.isAiEligible ? " - AI eligible" : ""}</small></button></li>)}</ol>
<nav><button disabled={page <= 1} onClick={() => setPage(value => value - 1)}>Previous</button><span>Page {result.pageNumber} of {Math.max(1, result.totalPages)}</span><button disabled={page >= result.totalPages} onClick={() => setPage(value => value + 1)}>Next</button></nav>
{selected && <article><h2>{selected.title}</h2><p>{selected.summary}</p><div>{selected.articleBody}</div><small>{selected.lifecycleStatus} - revision {selected.currentRevisionNumber} - {selected.freshnessStatus}</small></article>}
</section>;
}
Draft, revise, publish, archive, and restore
Every edit creates immutable revision evidence. Update, publish, archive, and restore use the latest updatedUtc; after every mutation re-fetch detail before enabling another action. Restoring an old revision creates a new Draft—it does not erase later history.
import type { KnowledgeCoreDetail, KnowledgeCoreWrite } from "@buildwithhq/module-sdk";
import { archiveKnowledgeCore, createKnowledgeCore, getKnowledgeCore, publishKnowledgeCore, restoreKnowledgeCoreRevision, updateKnowledgeCore } from "./api";
export const knowledgeReplacement = (current: KnowledgeCoreDetail): KnowledgeCoreWrite => ({
expectedUpdatedUtc: current.updatedUtc, slug: current.slug, title: current.title,
summary: current.summary || "", articleBody: current.articleBody || "", category: current.category || "",
knowledgeType: current.knowledgeType, authorityLevel: current.authorityLevel,
locationId: current.locationId || undefined, reviewPolicyId: current.reviewPolicyId || undefined,
isAiEligible: current.isAiEligible, isSupportEligible: current.isSupportEligible,
});
export function createRunbookDraft() {
return createKnowledgeCore({ slug: "incident-runbook", title: "Incident runbook", articleBody: "Draft steps", knowledgeType: "Procedure", authorityLevel: "Reference", isAiEligible: false, isSupportEligible: false, changeNote: "Initial draft" });
}
export async function revise(current: KnowledgeCoreDetail, articleBody: string) {
await updateKnowledgeCore(current.recordId, { ...knowledgeReplacement(current), articleBody, changeNote: "Reviewed procedure" });
return getKnowledgeCore(current.recordId);
}
export async function publish(current: KnowledgeCoreDetail) {
if (!current.canPublish) throw new Error("The signed-in user cannot publish this item.");
await publishKnowledgeCore(current.recordId, current.updatedUtc, "Approved for publication");
return getKnowledgeCore(current.recordId);
}
export async function archive(current: KnowledgeCoreDetail) {
await archiveKnowledgeCore(current.recordId, current.updatedUtc, "Retired guidance");
return getKnowledgeCore(current.recordId);
}
export async function restoreAsDraft(current: KnowledgeCoreDetail, knowledgeRevisionId: string) {
await restoreKnowledgeCoreRevision(current.recordId, knowledgeRevisionId, current.updatedUtc, "Restore for review");
return getKnowledgeCore(current.recordId);
}
Collections, accountable ownership, and review signoff
One primary owner may be an active tenant user or a DataRole—not both. Assigning ownership never grants record access. Review actions preserve their own optimistic-concurrency timestamp and create/advance the configured Task/Inbox attention.
import type { KnowledgeCollection, KnowledgeReviewCycle } from "@buildwithhq/module-sdk";
import { addKnowledgeCoreCollectionItem, beginKnowledgeReview, completeKnowledgeReview, createKnowledgeCoreCollection, getKnowledgeCoreOwners, listKnowledgeCoreCollections, listKnowledgeReviews, reassignKnowledgeReview, removeKnowledgeCoreCollectionItem, removeKnowledgeCoreOwner, setKnowledgeCoreOwner, updateKnowledgeCoreCollection } from "./api";
export const createOperationsCollection = () => createKnowledgeCoreCollection({ name: "Operations", description: "Approved operating procedures", isSupportCollection: true, sortOrder: 10 });
export const renameCollection = (current: KnowledgeCollection, name: string) => updateKnowledgeCoreCollection(current.collectionId, {
expectedUpdatedUtc: current.updatedUtc, name, description: current.description || "",
parentCollectionId: current.parentCollectionId || undefined, defaultReviewPolicyId: current.defaultReviewPolicyId || undefined,
isSupportCollection: current.isSupportCollection, sortOrder: current.sortOrder, isActive: true,
});
export const addToCollection = (collectionId: string, recordId: string) => addKnowledgeCoreCollectionItem(collectionId, recordId, 0);
export const removeFromCollection = (collectionId: string, recordId: string) => removeKnowledgeCoreCollectionItem(collectionId, recordId);
export const makeUserPrimaryOwner = (recordId: string, ownerUserId: string) => setKnowledgeCoreOwner(recordId, { ownerUserId, responsibilityType: "Owner", isPrimary: true });
export const makeRolePrimaryOwner = (recordId: string, dataRoleId: number) => setKnowledgeCoreOwner(recordId, { dataRoleId, responsibilityType: "Owner", isPrimary: true });
export const removeOwner = (knowledgeOwnerId: string) => removeKnowledgeCoreOwner(knowledgeOwnerId);
export async function confirmCurrent(review: KnowledgeReviewCycle) {
const begun = await beginKnowledgeReview(review.reviewCycleId, review.updatedUtc);
if (!begun.updatedUtc) throw new Error("Review did not return its concurrency token.");
return completeKnowledgeReview(review.reviewCycleId, begun.updatedUtc, "ConfirmedCurrent", "Content remains current");
}
export const reassignReviewToRole = (review: KnowledgeReviewCycle, assignedDataRoleId: number) => reassignKnowledgeReview(review.reviewCycleId, review.updatedUtc, { assignedDataRoleId });
export const loadGovernance = () => Promise.all([listKnowledgeCoreCollections(), listKnowledgeReviews()]);
export const loadOwners = (recordId: string) => getKnowledgeCoreOwners(recordId);
Questions, feedback, and measurable gaps
When evidence is missing, record a question instead of generating a confident answer. Repeated questions group inside the same tenant. Answer against an authorized Knowledge record or convert the question into a GeneratedCandidate Draft; it still requires human review and publication before normal RAG can use it.
import type { KnowledgeQuestion } from "@buildwithhq/module-sdk";
import { answerKnowledgeQuestion, assignKnowledgeQuestion, convertKnowledgeQuestion, createKnowledgeQuestion, getKnowledgeFeedback, getKnowledgeGaps, listKnowledgeQuestions, recordKnowledgeFeedback } from "./api";
export const ask = (questionText: string, contextRecordId?: string) => createKnowledgeQuestion(questionText, contextRecordId);
export const assignQuestionToRole = (question: KnowledgeQuestion, assignedDataRoleId: number) => assignKnowledgeQuestion(question.knowledgeQuestionId, question.updatedUtc, { assignedDataRoleId });
export const answerFromKnowledge = (question: KnowledgeQuestion, answerText: string, answerKnowledgeRecordId: string) => answerKnowledgeQuestion(question.knowledgeQuestionId, question.updatedUtc, answerText, answerKnowledgeRecordId);
export const convertToReviewedDraft = (question: KnowledgeQuestion) => convertKnowledgeQuestion(question.knowledgeQuestionId, { expectedUpdatedUtc: question.updatedUtc, slug: `question-${question.knowledgeQuestionId}`, title: question.questionText, knowledgeType: "FAQ", authorityLevel: "GeneratedCandidate" });
export const markHelpful = (recordId: string, contextRecordId?: string) => recordKnowledgeFeedback(recordId, "Helpful", undefined, contextRecordId);
export const loadImprovementQueue = (page = 1) => Promise.all([listKnowledgeQuestions("Open", undefined, page, 50), getKnowledgeGaps(undefined, 90, 50)]);
export const loadFeedback = (recordId: string) => getKnowledgeFeedback(recordId);
Optional starter styling
.knowledge-core { width: 100%; max-width: none; }
.knowledge-core form, .knowledge-core nav { align-items: end; display: flex; gap: .75rem; }
.knowledge-core ol { list-style: none; margin: 1rem 0; padding: 0; }
.knowledge-core li button { background: transparent; border: 0; display: grid; gap: .2rem; padding: .75rem 0; text-align: left; width: 100%; }
.knowledge-core article { border: 1px solid var(--line, #d8dee8); margin-top: 1rem; padding: 1rem; white-space: pre-wrap; }
Exact lifecycle and supporting routes
| Area | Routes | Canonical procedures |
|---|---|---|
| Items | GET/POST /api/modules/knowledge-core; GET/PUT /{recordId} | sp_kc_ListKnowledgeItemsSecured, sp_kc_GetKnowledgeItemSecured, create/update |
| Lifecycle/revisions | POST /{recordId}/publish, /archive, /restore; GET /revisions | Publish, archive, immutable history, restore-as-Draft |
| Collections/owners | /collections, /{recordId}/owners, /unowned | sp_kc_ListCollectionsSecured, collection membership, secured owner operations |
| Reviews/health | /reviews, /health | Due-review lifecycle and secured health aggregation |
| Questions/feedback/gaps | /questions, /{recordId}/feedback, /gaps | Evidence-preserving improvement loop |
Lists are bounded to 200 rows per page. AI/RAG eligibility does not grant access: only Published, explicitly eligible content that survives tenant, DataRole, location, record, field, and CanAiReadRecords checks enters model context. Generated or support-derived candidates remain Draft until a permitted human publishes them.
Build a professional Knowledge Core dashboard
These six registry-backed presentation blocks let a designer turn the secured Knowledge Core API into a complete admin page without writing a chart, grid, status badge, empty state, or timeline from scratch. The normal operational API begins at /api/modules/knowledge-articles; a dashboard-wide count or trend should come from a separate purpose-built presentation binding so the browser never downloads a broad record population to calculate one number.
The ZIP contains this feature's fictional design composition at pages/first-class/knowledge-core-sample.json, its executable authenticated page at pages/first-class/knowledge-core-live.json, and the catalog-driven FirstClassPresentationGallery.tsx. Use the sample only for visual design. The live page calls the real native API and reviewed stored procedures under the signed-in user's scope.
| Payload kind | Runtime block | Useful Knowledge Core projection |
|---|---|---|
metric-set | core.metric-strip | Published, draft, due-review, stale, and gap counts |
entity-list | core.entity-list | Important articles, owners, freshness, and use |
progress-list | core.progress-list | Distribution by freshness, lifecycle, category, or owner |
series-chart | core.series-chart | Draft, publish, review, use, and gap activity |
data-grid | core.presentation-grid | One bounded article page with lifecycle evidence |
timeline | core.timeline | Revision, publication, review, retrieval, feedback, gap, and archive |
Copy/paste design preview: all six blocks
This complete static page document renders immediately in Puck/Monaco and is useful while styling a template. Its names, counts, dates, and IDs are fictional design fixtures; static preview values are not live tenant facts.
Copy the complete six-block page JSON
{
"blocks": [
{
"_id": "knowledge-core-metrics",
"_type": "core.metric-strip",
"props": {
"title": "Knowledge operations",
"asOfUtc": "2026-09-04T18:00:00Z",
"items": [
{
"key": "published",
"label": "Published",
"value": 684,
"format": "number",
"tone": "success"
},
{
"key": "review",
"label": "Review due",
"value": 31,
"format": "number",
"tone": "warning"
},
{
"key": "draft",
"label": "Drafts",
"value": 24,
"format": "number",
"tone": "neutral"
},
{
"key": "gaps",
"label": "Open gaps",
"value": 12,
"format": "number",
"tone": "danger"
}
]
},
"children": []
},
{
"_id": "knowledge-core-recent",
"_type": "core.entity-list",
"props": {
"title": "Knowledge needing attention",
"hasMore": true,
"items": [
{
"id": "knowledge-core-sample-1",
"recordId": "knowledge-core-record-1",
"primary": "Escalation playbook",
"secondary": "Support operations - owner: Maya Chen",
"status": {
"key": "review-due",
"label": "Review due",
"tone": "warning"
},
"trailing": "14 uses"
},
{
"id": "knowledge-core-sample-2",
"recordId": "knowledge-core-record-2",
"primary": "Escalation playbook - Follow-up",
"secondary": "Support operations - owner: Maya Chen - Updated two hours ago by the assigned owner",
"status": {
"key": "in-review",
"label": "In review",
"tone": "primary"
},
"trailing": "Today"
},
{
"id": "knowledge-core-sample-3",
"recordId": "knowledge-core-record-3",
"primary": "Escalation playbook - West region",
"secondary": "Support operations - owner: Maya Chen - Related to three visible records at the Reno location",
"status": {
"key": "on-track",
"label": "On track",
"tone": "success"
},
"trailing": "3 related"
},
{
"id": "knowledge-core-sample-4",
"recordId": "knowledge-core-record-4",
"primary": "Escalation playbook - Customer response",
"secondary": "Support operations - owner: Maya Chen - Waiting for an external response before work can continue",
"status": {
"key": "scheduled",
"label": "Scheduled",
"tone": "warning"
},
"trailing": "Tomorrow"
},
{
"id": "knowledge-core-sample-5",
"recordId": "knowledge-core-record-5",
"primary": "Escalation playbook - Regional operations review with a deliberately long title",
"secondary": "Support operations - owner: Maya Chen - This deliberately longer supporting line verifies wrapping, truncation, responsive spacing, and dense dashboard behavior.",
"status": {
"key": "needs-attention",
"label": "Needs attention",
"tone": "danger"
},
"trailing": "Review",
"tertiary": "Long-content fixture: verify keyboard focus, wrapping, narrow columns, and mobile overflow before publishing."
},
{
"id": "knowledge-core-sample-6",
"recordId": "knowledge-core-record-6",
"primary": "Escalation playbook - Completed preview",
"secondary": "Support operations - owner: Maya Chen - Closed after review with its related evidence retained",
"status": {
"key": "complete",
"label": "Complete",
"tone": "success"
},
"trailing": "Closed"
}
]
},
"children": []
},
{
"_id": "knowledge-core-bystatus",
"_type": "core.progress-list",
"props": {
"title": "Knowledge freshness",
"items": [
{
"key": "current",
"label": "Current",
"value": 611,
"maximum": 684,
"displayValue": "611",
"tone": "success",
"status": {
"key": "current",
"label": "Current",
"tone": "success"
}
},
{
"key": "due",
"label": "Due soon",
"value": 42,
"maximum": 684,
"displayValue": "42",
"tone": "warning",
"status": {
"key": "due",
"label": "Due soon",
"tone": "warning"
}
},
{
"key": "stale",
"label": "Stale",
"value": 31,
"maximum": 684,
"displayValue": "31",
"tone": "danger",
"status": {
"key": "stale",
"label": "Stale",
"tone": "danger"
}
}
]
},
"children": []
},
{
"_id": "knowledge-core-trend",
"_type": "core.series-chart",
"props": {
"title": "Knowledge lifecycle",
"variant": "bar",
"defaultPeriodKey": "d7",
"periods": [
{
"key": "d7",
"label": "7 days",
"labels": [
"Fri",
"Sat",
"Sun",
"Mon",
"Tue",
"Wed",
"Thu"
],
"series": [
{
"key": "primary",
"label": "Published",
"tone": "primary",
"values": [
8,
5,
4,
12,
15,
11,
17
]
},
{
"key": "secondary",
"label": "Reviewed",
"tone": "success",
"values": [
6,
4,
3,
9,
12,
10,
14
]
}
]
}
]
},
"children": []
},
{
"_id": "knowledge-core-table",
"_type": "core.presentation-grid",
"props": {
"title": "Authorized knowledge",
"columns": [
{
"key": "article",
"label": "Article",
"type": "text",
"align": "left"
},
{
"key": "owner",
"label": "Owner",
"type": "text",
"align": "left"
},
{
"key": "freshness",
"label": "Freshness",
"type": "status",
"align": "left"
},
{
"key": "uses",
"label": "Uses",
"type": "number",
"align": "right"
},
{
"key": "review",
"label": "Next review",
"type": "date",
"align": "left"
}
],
"rows": [
{
"id": "knowledge-core-row-1",
"recordId": "knowledge-core-record-1",
"cells": {
"article": "Escalation playbook",
"owner": "Maya Chen",
"freshness": {
"key": "due",
"label": "Review due",
"tone": "warning"
},
"uses": 14,
"review": "2026-09-10T00:00:00Z"
}
},
{
"id": "knowledge-core-row-2",
"recordId": "knowledge-core-record-2",
"cells": {
"article": "Escalation playbook - Follow-up",
"owner": "Maya Chen",
"freshness": {
"key": "in-review",
"label": "In review",
"tone": "primary"
},
"uses": 15,
"review": "2026-09-04T15:42:00Z"
}
},
{
"id": "knowledge-core-row-3",
"recordId": "knowledge-core-record-3",
"cells": {
"article": "Escalation playbook - West region",
"owner": "Maya Chen",
"freshness": {
"key": "on-track",
"label": "On track",
"tone": "success"
},
"uses": 16,
"review": "2026-09-04T12:18:00Z"
}
},
{
"id": "knowledge-core-row-4",
"recordId": "knowledge-core-record-4",
"cells": {
"article": "Escalation playbook - Customer response",
"owner": "Maya Chen",
"freshness": {
"key": "scheduled",
"label": "Scheduled",
"tone": "warning"
},
"uses": 17,
"review": "2026-09-03T21:07:00Z"
}
},
{
"id": "knowledge-core-row-5",
"recordId": "knowledge-core-record-5",
"cells": {
"article": "Escalation playbook - Regional operations review with a deliberately long title",
"owner": "Maya Chen - This deliberately longer supporting line verifies wrapping, truncation, responsive spacing, and dense dashboard behavior.",
"freshness": {
"key": "needs-attention",
"label": "Needs attention",
"tone": "danger"
},
"uses": 18,
"review": "2026-09-03T16:31:00Z"
}
},
{
"id": "knowledge-core-row-6",
"recordId": "knowledge-core-record-6",
"cells": {
"article": "Escalation playbook - Completed preview",
"owner": "Maya Chen",
"freshness": {
"key": "complete",
"label": "Complete",
"tone": "success"
},
"uses": 19,
"review": "2026-09-02T19:14:00Z"
}
}
],
"page": {
"pageNumber": 1,
"pageSize": 6,
"totalRecords": 684,
"totalIsExact": true,
"hasMore": true
}
},
"children": []
},
{
"_id": "knowledge-core-timeline",
"_type": "core.timeline",
"props": {
"title": "Knowledge activity",
"hasMore": true,
"items": [
{
"id": "knowledge-core-event-1",
"recordId": "knowledge-core-record-1",
"occurredUtc": "2026-09-04T17:58:00Z",
"title": "Review requested",
"description": "Escalation playbook entered its scheduled review window.",
"actor": "Knowledge Core",
"tone": "warning"
},
{
"id": "knowledge-core-event-2",
"recordId": "knowledge-core-record-2",
"occurredUtc": "2026-09-04T15:42:00Z",
"title": "Review requested - Follow-up",
"description": "Escalation playbook entered its scheduled review window. Updated two hours ago by the assigned owner.",
"actor": "Avery Patel",
"tone": "primary"
},
{
"id": "knowledge-core-event-3",
"recordId": "knowledge-core-record-3",
"occurredUtc": "2026-09-04T12:18:00Z",
"title": "Review requested - West region",
"description": "Escalation playbook entered its scheduled review window. Related to three visible records at the Reno location.",
"actor": "Sam Rivera",
"tone": "success"
},
{
"id": "knowledge-core-event-4",
"recordId": "knowledge-core-record-4",
"occurredUtc": "2026-09-03T21:07:00Z",
"title": "Review requested - Customer response",
"description": "Escalation playbook entered its scheduled review window. Waiting for an external response before work can continue.",
"actor": "Maya Chen",
"tone": "warning"
},
{
"id": "knowledge-core-event-5",
"recordId": "knowledge-core-record-5",
"occurredUtc": "2026-09-03T16:31:00Z",
"title": "Review requested - Regional operations review with a deliberately long title",
"description": "Escalation playbook entered its scheduled review window. This deliberately longer supporting line verifies wrapping, truncation, responsive spacing, and dense dashboard behavior.",
"actor": "Automation",
"tone": "danger"
},
{
"id": "knowledge-core-event-6",
"recordId": "knowledge-core-record-6",
"occurredUtc": "2026-09-02T19:14:00Z",
"title": "Review requested - Completed preview",
"description": "Escalation playbook entered its scheduled review window. Closed after review with its related evidence retained.",
"actor": "Jordan Lee",
"tone": "success"
}
]
},
"children": []
}
]
}Copy/paste React composition
Copy InteractivePresentationComponents.tsx and its optional CSS from the Professional Foundation Developer Kit, then add this module-specific composition. It is semantic and unstyled by default; pass styled after importing interactive-presentation-components.css for the supplied polished foundation. Either version accepts only a bounded already-authorized document and fails closed through the shared strict parsers.
import {
EntityList,
MetricStrip,
PresentationGrid,
ProgressList,
SeriesChart,
Timeline,
} from "./InteractivePresentationComponents";
export interface KnowledgeCorePresentationData {
readonly metrics: unknown;
readonly recent: unknown;
readonly byStatus: unknown;
readonly trend: unknown;
readonly table: unknown;
readonly timeline: unknown;
}
export interface KnowledgeCorePresentationProps {
/** Pass only the already-authorized presentation document returned by the API. */
readonly data?: KnowledgeCorePresentationData | null;
readonly loading?: boolean;
readonly error?: boolean;
readonly styled?: boolean;
/** Record identity is navigation context; the detail API must authorize it again. */
readonly onOpenRecord?: (recordId: string) => void;
}
export function KnowledgeCorePresentation({
data,
loading = false,
error = false,
styled = false,
onOpenRecord,
}: KnowledgeCorePresentationProps) {
if (error) return <p role="alert">The Knowledge Core presentation could not be loaded.</p>;
if (loading || !data) return <p role="status">Loading Knowledge Core presentation...</p>;
return (
<main className={styled ? "bwhq-api-example" : undefined}>
<header>
<p>Knowledge Core</p>
<h1>Knowledge operations</h1>
<p>Published knowledge, review freshness, ownership, gaps, retrieval use, and lifecycle evidence.</p>
</header>
<MetricStrip data={data.metrics} styled={styled} />
<div className={styled ? "bwhq-api-example__split" : undefined}>
<ProgressList data={data.byStatus} styled={styled} />
<EntityList data={data.recent} styled={styled} onOpenRecord={onOpenRecord} />
</div>
<SeriesChart data={data.trend} styled={styled} />
<PresentationGrid data={data.table} styled={styled} onOpenRecord={onOpenRecord} />
<Timeline data={data.timeline} styled={styled} onOpenRecord={onOpenRecord} />
</main>
);
}
Copy the live, authenticated module page
This document has no placeholder key and needs no invented endpoint. Save it to a page and add that page to a User Type menu. The registered native component calls /api/modules/knowledge-articles, uses the current tenant session, and preserves the module's real list, detail, create/update, pagination, empty, loading, and error behavior. Dynamic Records discovers the organization's real tenant-owned modules when no module key is configured.
Copy the executable live page
{
"blocks": [
{
"_id": "knowledge-core-live",
"_type": "module.knowledge-articles",
"props": {},
"children": []
}
]
}The server derives SaaS app, organization, user, DataRoles, locations, module-specific membership/privacy, and any AI-read gate from verified identity. A returned identifier can select a detail target, but the detail or write endpoint authorizes it again. Page layout, status, tone, totals, action names, and identifiers never grant authority.
Start with a few high-value collections, one accountable owner per item, and a practical review interval. Mark content AI-eligible only when its audience, authority, source, and freshness are suitable for model context; missing evidence should create a question, not a confident guess.
A renderer being bundled in the tenant application does not make its data visible in every app. The server returns only components and records authorized for the current app and signed-in user; unavailable or unauthorized blocks fail closed.
Capability review: 2026-09-14. For exact current technical availability, use the generated API Map and first-class module inventory.