Knowledge Base
This page is a complete solution guide. Using the open-source doc-knowledge plugin (com.auraboot.doc-knowledge, namespace dk) as the example, it goes from the user scenario all the way through how it becomes a knowledge source for Aura Bot, the implementation, and the common mistakes. It is a config plugin — its 5 models, 18 commands, 15 pages, and 1 dashboard are all declared in DSL JSON, with no backend Java. Every identifier below can be grepped in plugins/doc-knowledge/config/ and called against a running instance.
This plugin depends on
com.auraboot.template.project-management(the project management template) — documents can be linked to projects, so import the project management plugin first.
1. User Scenario
A manufacturer wants to consolidate drawings, specifications, reports, meeting minutes, and contracts scattered across shared drives and email, and to build up a searchable set of knowledge articles. Day to day:
- An engineer creates a document (draft) → fills in title, type, owning project, access level, body → publishes it so everyone can see it;
- When a document needs changes it is revised back to draft, edited, then republished; obsolete documents are archived, removed from the active list but still queryable;
- Each significant change leaves a version record with a change summary and content snapshot, so history can be compared later;
- Documents are organised under a category tree (product docs / policies / training material / troubleshooting);
- Documents are scoped by access level (public / internal / confidential / restricted);
- Documents can be linked to projects, so a project view can trace its specifications, design docs, and compliance certificates;
- A separate set of knowledge articles — shorter and more topic-focused than documents — follows the same draft → published → archived editorial lifecycle.
A document manager, a document editor, and a document viewer each see and can do different things.
2. Pain Points
- No lifecycle: files on a shared drive have no "draft / published / archived" state, so nobody knows which copy is final and which is still in progress.
- Broken version chains: overwrite uploads clobber the old version, so you cannot trace "what changed in the previous revision, and who changed it".
- No authorization or audit: who published, who archived, and when — none of it is recorded; publishing relies on word of mouth.
- Access control by vigilance: confidential drawings sit in public folders, guarded only by naming conventions, which is unreliable.
- Disconnected from projects: project-relevant documents are scattered, so a project cannot show all of its specs and compliance material in one click.
None of this is solved by "make another folder" — it is a problem of controlled state changes plus structured relationships.
3. The Product Approach
In AuraBoot every document action is a command that runs through the unified command pipeline:
- The "Publish" button calls
dk:publish_document, not a rawPUT /api/dk_document; the command runs authorization → state-machine validation → execution → audit → event publication in one pipeline. - The document lifecycle is guarded by the state field
dk_doc_statusplus threestate_transitioncommands (dk:publish_document/dk:archive_document/dk:revise_document); illegal transitions (for example, archiving a draft directly) are rejected by the state machine. - Version history is a real model,
dk_doc_version, attached to the document viaparentModel: dk_documentand shown as an inline sub-table on the document detail page — it inherits list, detail, search, export, and audit, sharing the same machinery as every other business entity, with no separate "version management console". - The same command is both the target of a UI button and callable from automation rules or BPM review flows — for example "auto-archive documents untouched for 18 months" sends
dk:archive_documentdirectly, with no manual second step.
4. Functional Design
4.1 Data Models (5)
| Model | Type | Purpose | Key states |
|---|---|---|---|
dk_document | entity | The primary document entity; carries body, abstract, tags, type, version label, owning category/project, and access level | dk_doc_status: draft / published / archived |
dk_doc_category | master | Document category tree (self-referencing parent dk_cat_parent_id) for logical grouping | no state machine |
dk_doc_version | entity | Document version record; parentModel: dk_document, parentField: dk_ver_document_id; carries change summary and content snapshot | follows parent document |
dk_knowledge_article | entity | Knowledge article; editorial content shorter and more topic-focused than a document | dk_article_status: draft / published / archived |
dk_project_document | reference | Many-to-many bridge linking documents and projects | no state machine |
Key document fields (config/fields.json): dk_doc_title (title), dk_doc_type (type, enum), dk_doc_project_id / dk_doc_category_id (reference), dk_doc_abstract / dk_doc_content (text body), dk_doc_access_level (access level, enum), dk_doc_author / dk_doc_owner_id (auto-filled from current_username on create).
4.2 Commands and State Machine
18 commands, named dk:<verb>_<noun> (colon separator, not dots). By type:
| Type | Commands |
|---|---|
create (5) | dk:create_document · dk:create_category · dk:create_version · dk:create_article · dk:link_document |
update (3) | dk:update_document · dk:update_category · dk:update_article |
delete (5) | dk:delete_document · dk:delete_category · dk:delete_version · dk:delete_article · dk:unlink_document |
state_transition (5) | dk:publish_document · dk:archive_document · dk:revise_document · dk:publish_article · dk:archive_article |
The document state machine: dk:publish_document (draft → published) → dk:revise_document (published → draft, to re-edit) → dk:archive_document (published → archived). Knowledge articles work the same way.
Each command is a declaration. For example, the real definition of dk:publish_document (config/commands.json):
{
"code": "dk:publish_document",
"displayName:zh-CN": "发布文档",
"displayName:en": "Publish Document",
"description": "Publish a draft document",
"type": "state_transition",
"modelCode": "dk_document",
"stateField": "dk_doc_status",
"fromStates": ["draft"],
"toState": "published",
"permissions": ["dk.document.publish"],
"extension": {
"confirmMessage:zh-CN": "确认发布此文档?",
"confirmMessage:en": "Confirm publish this document?"
}
}What the definition tells you: this is a state_transition that can only go from draft to published (fromStates contains nothing else, so publishing an already-published or archived document is rejected); it requires the dk.document.publish permission (note this is separate from dk.document.manage — being able to edit does not mean being able to publish); and it shows a confirmation dialog on click. create commands (for example dk:create_document) carry inputFields listing the fillable fields and autoSetFields declaring that dk_doc_no is auto-generated as DOC-{yyyyMMdd}-{seq}, dk_doc_status is fixed to draft, and the author is taken from current_username.
4.3 Permissions and Roles
9 permission codes, named dk.<resource>.<action> (dot separator — note that permission codes use dots while command codes use colons; they are different):
dk.document.manage dk.document.read dk.document.publish
dk.category.manage dk.version.manage
dk.article.manage dk.article.read dk.article.publish
dk.link.manage
manage covers create/update/delete/archive; publish is split out separately (publishing is a higher privilege); read is a data-type permission (resourceType: data) used for data visibility on list and detail pages.
3 roles (config/roles.json):
dk_manager(Document Manager) — all 9 permissions, including publish;dk_editor(Document Editor) — can create/update, manage versions and links, but does not havedk.document.publish/dk.article.publish;dk_viewer(Document Viewer) — onlydk.document.read+dk.article.read.
4.4 Pages
15 DSL pages (config/pages.json): list / form / detail for each of the 5 models. Plus 1 dashboard (config/dashboards/dk_dashboard.json) fed by 6 named queries (dk_dashboard_kpi / dk_docs_by_type / dk_docs_by_status / dk_articles_by_status / dk_recent_documents / dk_recent_articles). The menu (config/menus.json) is mounted under /doc-knowledge: dashboard, documents, categories, versions, articles, project documents.
4.5 As a Knowledge Source for Aura Bot
This plugin is plain document/knowledge-base CRUD; it has no built-in vector retrieval or RAG pipeline — it declares no embedding model, no answer-trace model, and no retrieval-scoring logic of its own. Its place in the AI layer is this: published documents and knowledge articles are a knowledge source that Aura Bot can answer over.
The connection is a capability the platform Agent System provides by default — not extra code in this plugin:
- Read tools are generated automatically: the DSL Tool Provider attaches
list:<modelCode>andget:<modelCode>read tools to every model, and named queries becomenq:<queryCode>. Putlist:dk_knowledge_article/get:dk_document/nq:dk_recent_documentsin an agent'stoolsallowlist and it can query the knowledge base during a turn to answer a user's question. - Permissions are the retrieval boundary: the agent runs as the calling user (see Aura Bot § Permissions). A document the user lacks
dk.document.readon is invisible to the agent too;dk_doc_access_level(public / internal / confidential / restricted) combined with ABAC policy narrows visibility further. In other words, the bot never reads content the caller cannot read. - Write commands are exposed to agents on demand: these commands carry no
agent_hint/cmd_risk_levelby default, which means they are not offered to an agent for automatic execution. To let an agent draft an article or initiate an archive, addagent_hint(when to use it) andcmd_risk_level(use L2+ for publish/archive so they route through the Approval Gate) to the relevant command so a human confirms first — see Agent Builder for the contract.
So: documents and knowledge live here, while retrieval, permissions, audit, and exposure policy all reuse the platform's single mechanism. It is not a second "AI knowledge console" — it lets AI speak through the existing models, commands, and permissions.
5. Implementation
Get the basics first. This plugin has no backend Java; it relies entirely on a few core platform contracts. Before you start, read: Models and Fields · Commands · Command Pipeline · Permissions · Plugin Manifest · Config-only Plugins · Page Designer.
To land a config plugin like doc-knowledge, the steps are:
- Write the manifest —
plugin.jsondeclarespluginId/namespace(dk) /pluginType: config/dependencies(this plugin depends on the project management template), and registers every config file inresourceDirs(models/commands/permissions/modelFieldBindings…). See Plugin Manifest. - Define models and fields —
config/models.json(5 models; the version model declares its parent-child link withparentModel+parentField) plusconfig/fields.json, with platformdataTypevalues (string/enum/reference/text…). See Models and Fields. - Declare commands —
config/commands.json; state transitions usetype: state_transition+fromStates/toState, CRUD usescreate/update/delete, and each binds permission codes inpermissions. See Commands. - Configure model-field bindings —
config/bindings.json, registered underresourceDirs.modelFieldBindings(see "Common Mistakes"). - Permissions, roles, dicts, menus, pages —
config/permissions.json/roles.json/dicts.json/menus.json/pages.json/dashboards/. - Package and import — use the
auraCLI'simport-directory-sync(the parameter is a directory path) or the platform import API; asuccess:trueresponse means the import succeeded. Make sure theproject-managementdependency is imported first.
6. Common Configuration
- Document lifecycle: the state field
dk_doc_status(dictdk_doc_status: draft / published / archived) is guarded by threestate_transitioncommands; to support "unpublish and re-edit", wiredk:revise_document(published → draft). - Access level: the field
dk_doc_access_levelpicks from dictdk_access_level(public/internal/confidential/restricted), combined with ABAC policy to control document visibility. - Category tree:
dk_doc_categoryusesdk_cat_parent_idself-reference to form a multi-level tree; documents attach to a category viadk_doc_category_id(reference). - Version snapshots: on each significant change call
dk:create_versionto write adk_doc_versionrow carryingdk_ver_change_summary(change summary) anddk_ver_content_snapshot(content snapshot); versions appear as a sub-table on the document detail page. - Project links:
dk:link_documentwrites adk_project_documentbridge row to attach a document to a project;dk:unlink_documentdetaches it. - Auto-archive: configure an automation rule that sends
dk:archive_documentfor long-untouched published documents, with no manual step.
7. Common Mistakes
- Dot-notation command codes:
dk.document.publishwill not run — command codes are colon plus verb_noun:dk:publish_document. Permission codes are the ones that use dots:dk.document.publish. Same name, different separator — don't mix them up. - Mutating the document table directly instead of going through a command: a direct UPDATE of
dk_documentstate skips state-machine validation, handlers, and audit/event publication. Every document change goes through a command. - Publishing an already-archived document:
dk:publish_document'sfromStatesonly containsdraft, so calling it on a published/archived document is rejected by the state machine — that is by design, not a bug. - Treating edit permission as publish permission:
dk.document.managedoes not includedk.document.publish(thedk_editorrole has no publish right); to let a role publish, grantdk.document.publishseparately. - Missing dependency on import: this plugin's
dependenciesdeclarescom.auraboot.template.project-management— import it before this plugin, otherwise the project references indk_doc_project_id/dk_project_documentcannot resolve. - Inline
bindingRulesinsidecommands.json: they are not imported; use a separatebindings.jsonregistered underresourceDirs.modelFieldBindings, otherwise you get[S-EXT-HANDLER] references unregistered handler. See Config-only Plugins. - Command execution payload shape: fields go in
{ "payload": { ... }, "operationType": ... }, and the target record usestargetRecordId(notrecordId) — misplacing them produces the confusing "executed successfully but fields are empty" error.
Next steps
- System overview — how plugins, commands, and the runtime fit together
- Command pipeline — the execution contract every command above runs through
- Permissions — the layered model behind the three roles above
- Plugin manifest — how a plugin declares dependencies and resource directories