Skip to content
bitzorcas
中EN

Concept

Documents 文档中心

源码校验的 Documents 模块说明书,覆盖知识库、分类、版本化内容、发布、访问规则、白板、协作、搜索与当前产品边界。

Last updated

Documents 提供多租户知识库、树形分类、版本化文档、发布与归档、标签、访问规则和白板模型。它的内容聚合与版本快照已经可以支撑后台知识管理,但访问规则、成员、搜索索引、文件转换和实时协作仍有明显的“模型已经存在,产品闭环尚未形成”现象。

1. 模块要解决的问题

Documents 把“可编辑文本”提升为具有业务生命周期的内容资产:

  • 知识库组织内容域,分类与父文档提供导航层级;
  • Document 保存正文、元数据、状态和完整版本快照;
  • 发布、取消发布、归档和回滚由聚合方法保护;
  • 标签、访问规则、知识库成员和白板成员作为聚合内 JSON 集合保存;
  • QueryShape 读模型提供详情、列表与树查询;
  • 内存搜索、文档缓存、文件服务、云盘端口和协作端口提供扩展接缝。

它不负责二进制文件资产安全、通用搜索引擎或评论线程。Files、Search、Comments 是独立模块;当前 Documents 内部的同名服务不能替代这些平台模块。

2. 当前结构

当前未形成稳定调用链

认证客户端

生成式 /api/v1 端点

Mediator 管道
认证 / 部分授权 / 事务 / 审计

Commands
知识库 / 分类 / 文档 / 白板

Query handlers
详情 / 列表 / 树 / 版本

统一聚合
KnowledgeBase / Category / Document / Whiteboard

嵌入 JSON
成员 / 标签 / ACL / 版本

DocumentsQueryShapeReadModelStore

内部服务
搜索 / 缓存 / 文件 / 协作 / 云盘

三个项目的职责分配如下:

项目主要内容依赖方向
BitzOrcas.Platform.Documents.Contracts聚合、DTO、权限/功能目录、查询端口、事件、云盘/协作端口不暴露 ORM 或连接器 SDK
BitzOrcas.Platform.Documents.Application公开命令与查询、处理器、映射、内存搜索/缓存/文件服务依赖 Contracts 与框架抽象
BitzOrcas.Platform.Documents.InfrastructureQueryShape 读模型、协作默认实现、云盘适配器、索引订阅方依赖 Application/Contracts 与连接器

3. 聚合关系不是外键完整性

KnowledgeBaseIdKnowledgeBaseIdoptional KnowledgeBaseIdCategoryIdParentId self-referenceParentId self-reference

KnowledgeBase

DocumentCategory

Document

Whiteboard

MembersJson

MembersJson

VersionsJson

TagsJson

AccessRulesJson

图中的关系是领域标识关系,不等于所有入口都做了引用校验。当前 CreateDocument 不验证知识库、分类或父文档是否存在,也不验证分类是否属于指定知识库;CreateWhiteboard 不验证可选 KnowledgeBaseId;CreateKnowledgeBase 不验证 ParentId 或环。分类创建只在有 ParentId 时验证父分类属于同一知识库。

4. HTTP 表面

文档与版本

方法与路由用例通用动作
POST /api/v1/documents/创建 Draft 和 1.0.0Create
GET /api/v1/documents租户列表,最多 100/页仅认证
GET /api/v1/documents/{id}完整详情仅认证
PUT /api/v1/documents/{id}更新元信息Update
PUT /api/v1/documents/{id}/content新建 Patch 版本Update
GET /api/v1/documents/{id}/versions版本列表仅认证
GET /api/v1/documents/{id}/versions/{version}单版本仅认证
GET /api/v1/documents/{id}/versions/diff简化行级差异仅认证
POST /api/v1/documents/{id}/versions/{version}/rollback以旧内容创建新 PatchUpdate
POST /api/v1/documents/{id}/publishDraft → PublishedUpdate
POST /api/v1/documents/{id}/unpublishPublished → DraftUpdate
POST /api/v1/documents/{id}/archivePublished → ArchivedUpdate
POST/DELETE .../tags增删标签Update
POST/DELETE .../access-rules增删 ACL 数据Update
DELETE /api/v1/documents/{id}软删除Delete

“仅认证”表示消息没有实现 IAuthorizedRequest;端点仍受默认认证约束,但不会经过框架的资源动作授权决策。

知识库、分类与白板

资源创建/写入读取当前注意点
知识库/api/v1/knowledgebases、/{id}、/{id}/membersdetail/list/treeSetKnowledgeBaseAccessCommand 没有生成端点;读取只做租户过滤
分类/api/v1/documents/categories/、/{id}/tree?knowledgeBaseId=权限目录没有 category 权限定义;树构建无环检测
白板/api/v1/whiteboards、/{id}/data、成员、归档、删除detail/list权限目录没有 whiteboard 权限定义;成员不参与授权

搜索与建议查询实现了 IAuthorizedRequest,却没有 [GenerateEndpoint],所以它们目前不是 HTTP 表面。协作服务、文档文件服务和云盘端口也没有本模块公开端点。

5. 文档生命周期

Create + version 1.0.0rollback creates a newpatchpublishunpublishrollback creates a newpatcharchiveremove tag or ACL is stillallowed

Draft

Published

Archived

当前聚合没有 Draft → Archived,也没有 Archived → Draft/Published。归档会阻止正文、元信息、发布、取消发布、新增标签和新增访问规则;但移除标签、移除访问规则以及成员类操作的规则并不一致,不能把 Archived 理解成全字段不可变。

每个版本是完整正文快照,不是增量补丁。版本包含 VersionNumber、Content、SHA-256、UTF-8 字节数、变更摘要、创建人/时间和发布标记。普通更新只增加 Patch,因此 1.0.0 之后是 1.0.1;当前没有 Major/Minor 升级入口。

6. 从创建到发布的客户端示例

发布一篇知识库文章
public async Task PublishArticleAsync(
HttpClient api,
string knowledgeBaseId,
CancellationToken cancellationToken)
{
// 1. 创建时正文与第一个完整快照一并写入;调用者必须是 User。
using var create = await api.PostAsJsonAsync(
"/api/v1/documents/",
new
{
knowledgeBaseId,
categoryId = (string?)null,
parentId = (string?)null,
title = "订单取消操作手册",
description = "面向客服和运营的处置步骤",
content = "# 订单取消\n\n先核对支付状态。",
contentType = "Markdown",
languageCode = "zh-CN",
allowComments = true,
allowCollaboration = false
},
cancellationToken);
create.EnsureSuccessStatusCode();
var document = await create.Content.ReadFromJsonAsync<DocumentDto>(cancellationToken);
// 2. 每次内容更新都会保存完整快照并把 Patch 加一。
using var update = await api.PutAsJsonAsync(
$"/api/v1/documents/{document!.DocumentId}/content",
new
{
content = "# 订单取消\n\n1. 核对支付状态。\n2. 记录取消原因。",
changeSummary = "补充审计要求"
},
cancellationToken);
update.EnsureSuccessStatusCode();
// 3. Publish 请求没有 expectedVersion;并发编辑窗口需由客户端自己收敛。
using var publish = await api.PostAsync(
$"/api/v1/documents/{document.DocumentId}/publish",
content: null,
cancellationToken);
publish.EnsureSuccessStatusCode();
}
public sealed record DocumentDto(string DocumentId, string CurrentVersion);

这段代码展示真实路由和当前并发边界。生产编辑器应在保存前重新读取 CurrentVersion,并在服务端增加显式 expectedVersion/并发令牌;仅靠客户端比较不能消除竞态。

7. 权限、功能与租户的真实矩阵

层已有事实当前缺口
认证生成端点默认要求认证不代表资源级可见性
通用授权29 个写命令实现 IAuthorizedRequest公开 GET 查询没有实现;搜索查询没有 HTTP 路由
权限目录document 6 项、knowledgebase 4 项category/whiteboard 资源常量存在,但没有权限定义
动作映射create/update/delete/view 可派生Publish、标签、ACL 都使用 Update;publish/manage 目录项没有对应动作
ACL/成员数据可创建、删除、序列化没有进入 handler/read model 的准入判断
Featuredocuments.manage,默认关闭Documents 源码未见运行时 Feature 决策
租户文档/知识库/分类/白板读写按 User.TenantId未使用 EffectiveTenantId;协作会话读模型甚至没有租户谓词

在这些差距修复前,不要向外承诺“私有知识库”“按成员可见”“文档 ACL”或“功能套餐已生效”。如果业务必须上线,应在网关/应用层增加失败关闭的访问策略,并用契约测试证明所有读取与写入路径一致。

8. 持久化与计数

四个主聚合都直接标注表元数据,使用统一聚合持久化:

  • DocsDocument:租户 + 软删除;版本、标签、ACL 为 JSON 列;
  • DocsKnowledgeBase:租户 + 软删除;成员为 JSON 列;
  • DocsDocumentCategory:租户 + 软删除;同知识库、同父级、同名具有唯一索引;
  • DocsWhiteboards:租户 + 软删除;画布 JSON 与成员 JSON 同行保存;
  • DocsCollaborationSession:租户 + 软删除;参与者 JSON 同行保存,但当前内存协作服务不持久化它。

KnowledgeBase.DocumentCount 与 DocumentCategory.DocumentCount 有领域增减方法,却没有接入 Create/Delete Document 处理器。因此删除知识库/分类时依赖计数的判断不能作为可靠引用完整性。知识库删除会额外查询文档仓储,分类删除只看可能失真的计数。

9. 当前可以依赖与不能依赖的能力

能力结论
租户内文档 CRUD、完整版本快照、发布/取消发布/归档可用,但需补资源访问控制与并发策略
知识库/分类树可用作导航;必须防止脏 ParentId 与环
标签、ACL、成员持久化仅数据模型可用;ACL/成员不是当前安全控制
白板 JSON 版本更新单请求版本冲突可检测;没有 JSON/大小校验与实时传输
搜索仅内部 200 条内存搜索;无 HTTP 路由,不是共享 Search 引擎
文档缓存服务已注册但业务 handler 未调用
文档上传/下载内部简化服务,无端点;上传不保存,PDF/Word 下载不是格式转换
实时协作单实例内存、默认 Hub 只记录日志,不可用于多实例生产
云盘中性端口和 adapter 已存在;无 Documents 用例和组合根注册闭环

10. 阅读路径

  1. 正文、版本、发布与回滚
  2. 知识库、分类、成员与访问规则
  3. 读取、搜索、缓存、文件与云盘
  4. 白板、协作会话与实时边界
  5. 测试、可观测性与生产门禁

关联章节:Authorization、Multitenancy、Files、Auditing。

11. 最小源码核对

Terminal window
# 列出真正生成的 HTTP 表面。
rg -n '^\[GenerateEndpoint' src/Platform/Documents -g '*.cs'
# 对比授权消息与无 IAuthorizedRequest 的读查询。
rg -n 'IAuthorizedRequest|IQuery<Result' \
src/Platform/Documents/BitzOrcas.Platform.Documents.Application -g '*.cs'
# 检查 ACL、成员和计数是否进入 handler;当前预期只有模型/命令命中。
rg -n 'HasAccess\(|DefaultAccessLevel|IncrementDocumentCount\(|DecrementDocumentCount\(' \
src/Platform/Documents -g '*.cs'

返回平台模块目录

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%