契约版本:1.6 状态:已确认,LibreOffice 离线文档转换与 PDF 预览基线 适用范围:前端、后端、数据库、联调、测试与验收
本文件是第一阶段业务功能的唯一执行契约。Codex 会话开始工作前必须完整读取本文件,不得只读取摘要。
约束优先级如下:
DMS_API_CONTRACT.md 中与接口表达有关的约定;FUNCTION_AND_API_SPECIFICATION.md;CODEX_BACKEND_PERSISTENCE_GUIDE.md;低优先级材料与本契约冲突时,以本契约为准。执行会话不得自行选择旧版本规则,不得未经确认扩大范围。发现本文件与接口契约互相冲突时必须停止相关实现并提交统领会话裁决。
FUNCTION_AND_API_SPECIFICATION.md 和 CODEX_BACKEND_PERSISTENCE_GUIDE.md 仍可作为背景、字段设计和实施建议的参考,但不能单独作为最终验收依据。
将当前前端模拟界面建设为可持久化、可鉴权、可审计的方案计划文档管理系统,形成以下最小业务闭环:
backend/dms-storage/ 保存文件。recycle目录;| 角色 | 代码 | 功能边界 |
|---|---|---|
| 普通用户 | USER |
浏览有权访问的已发布方案;查看、下载共享附件 |
| 管理员 | ADMIN |
浏览文档、进入后台管理及日志审计;管理分类、方案、附件、挂载和权限 |
登录成功后,后端返回用户可访问模块 allowedModules。前端不得仅根据本地角色字符串猜测导航入口。
固定模块代码:
DOCUMENT_BROWSERBACKEND_MANAGEMENTAUDIT_LOGMAIN;SUB_PLAN;ATTACHMENT;categoryId 必须为空;ALL_AUTHENTICATED;PUBLIC,前端不得修改;固定状态:
DRAFT:草稿;PUBLISHED:已发布;ARCHIVED:已归档。规则:
PUBLISHED 文档;allowedActions 决定;| 代码 | 名称 | 比较值 |
|---|---|---|
PUBLIC |
公开 | 10 |
INTERNAL |
内部 | 20 |
SECRET |
秘密 | 30 |
CONFIDENTIAL |
机密 | 40 |
TOP_SECRET |
绝密 | 50 |
访问方案时,用户密级比较值必须大于或等于文档密级比较值。判断顺序为:
登录状态
→ 用户有效状态
→ 文档有效状态和发布状态
→ 密级
→ 管理员业务特权
→ 可见范围与 ACL
→ 具体操作权限
共享附件固定为 PUBLIC,因此对全部有效登录用户共享。
固定可见范围:
ALL_AUTHENTICATED:通过前置检查的所有登录用户;ORGANIZATION:权限集合只能包含组织主体;CUSTOM:权限集合可以包含组织和人员主体。第一阶段 ACL 只表达“允许”,不表达显式拒绝。
组织权限覆盖该组织及其有效下级组织。人员允许记录与组织允许记录取并集,不存在“人员拒绝覆盖组织允许”的规则。
主案权限包含五个独立动作:
VIEWDOWNLOADEDITCONFIG_PERMISSIONDELETE子方案动态使用主案 ACL,但仍按子方案自身密级和状态执行前置检查。
localStorage,否则放入 sessionStorage;左侧:
categoryId 筛选文档。右侧页签:
MAIN;MAIN 和 SUB_PLAN,不显示附件;主搜索框:
文档操作:
allowedActions 决定。选中主案后,下方加载:
选中子方案时,下方不加载主案关联管理区。
统计卡片固定口径:
分类管理:
方案管理:
共享附件:
ADMIN 可进入,管理员具有 AUDIT_LOG 模块;允许类型:
.doc.docx.pdf.xls.xlsx规则:
预览规则:
415 PREVIEW_UNAVAILABLE;所有普通业务删除均为逻辑删除。
存在有效子分类或有效主案、子方案时,返回冲突。
ATTACHMENT_IN_USE;仅管理员可以查询回收站及执行恢复。正式路径为:
GET /api/v1/recycle-bin/documents
POST /api/v1/recycle-bin/documents/{id}/restore
旧路径 /api/v1/documents/{id}/restore 永久废止,不得实现重定向、别名或兼容调用。
恢复范围只包含 MAIN、SUB_PLAN 和 ATTACHMENT。不支持分类、用户或组织恢复,不支持批量恢复、物理删除、自动清理、独立恢复ACL或挂载关系,也不移动、复制或删除原始文件。
通用恢复规则:
deleted_at 非空;rowVersion,冲突时不得静默覆盖;VIEW_DOCUMENT 审计。主案采用关系恢复方案B:只恢复与本次主案删除具有相同文档ID、deletedAt和updatedBy的级联删除ACL及挂载关系。更早的历史删除关系不恢复。无效或禁用权限主体、已删除或不存在的附件跳过并计数;已存在有效同主体ACL或同附件挂载时整体冲突回滚。
ORGANIZATION恢复后必须至少有一个有效且 canView=true 的组织权限;CUSTOM允许空权限集合,普通用户默认无权访问;ALL_AUTHENTICATED权限集合必须为空;子方案恢复要求父主案与根主案指向同一有效 MAIN,不恢复独立ACL,恢复后动态继承主案当前最新权限并重新统计主案子方案数。
共享附件恢复后继续固定为 PUBLIC、ALL_AUTHENTICATED,分类、父文档和根文档均为空;不创建ACL,不恢复任何历史挂载。若异常存在指向已删除附件的有效挂载关系,恢复必须返回关系冲突。
恢复新增错误码固定为:
DOCUMENT_NOT_DELETED
FILE_INTEGRITY_MISMATCH
FILE_PATH_INVALID
RESTORE_FILE_CHANGED
RESTORE_CATEGORY_INVALID
RESTORE_PARENT_INVALID
RESTORE_PERMISSION_INVALID
RESTORE_RELATION_CONFLICT
具体HTTP状态、message和details结构以 DMS_API_CONTRACT.md 1.1为准。错误不得泄露绝对路径、哈希、SQL、数据库连接信息或内部异常堆栈。
至少记录:
文档恢复使用审计动作 RESTORE_DOCUMENT。恢复成功审计与恢复事务原子提交;最小范围内恢复失败不写业务审计,只写安全应用日志和统一错误响应。
sys_audit_log 是追加写表:
created_at,不要求 updated_at、deleted_at、is_deleted、row_version;sys_user 保存 auth_version;authVersion;auth_version;auth_version,使该用户全部已签发 Token 失效;backend/dms-storage/ 是文件内容的事实来源;sys_user 必须增加 auth_version;doc_document 必须增加可空的 attachment_type;row_version 乐观锁;READ COMMITTED;backend/src/** AI 模块不得被新 DMS 业务直接调用。逻辑删除关系的有效唯一性采用 MySQL 生成列:
active_marker = IF(is_deleted = 0, 1, NULL)
至少建立以下唯一约束:
doc_attachment_binding:
UNIQUE(main_document_id, attachment_document_id, active_marker)
doc_permission:
UNIQUE(document_id, subject_type, subject_id, active_marker)
这允许保留多条历史删除记录,同时保证同一业务关系只有一条有效记录。
B8实现必须新增迁移 0002_add_restore_audit_action,不得修改 0001_initial_schema。该迁移只扩展 sys_audit_log.action_type CHECK以加入 RESTORE_DOCUMENT,并在 doc_document 增加回收站索引:
INDEX(is_deleted, deleted_at, id)
迁移不得新增表或修改历史审计,必须提供安全的upgrade和downgrade。
统一预览接口 GET /api/v1/documents/{id}/preview 行为:
application/pdf;application/pdf;415 PREVIEW_UNAVAILABLE;转换错误码:
PREVIEW_CONVERTER_UNAVAILABLE:转换器未启用或 LibreOffice 可执行文件不存在/不可执行;PREVIEW_CONVERSION_TIMEOUT:转换超出配置时间;PREVIEW_CONVERSION_FAILED:LibreOffice 退出码非零、未生成输出或输出非有效 PDF。缓存规则:
backend/dms-storage/preview/;preview/{fileHash}.pdf,可通过前两位哈希分层;DOC 正文检索规则:
content_extract_status 标记为 FAILED,不得写入空字符串冒充成功;search_text。只有同时满足以下条件,第一阶段才算完成:
DMS_API_CONTRACT.md;updated_at 的统一UTC时间范围检索。content_text;DOCX 仍使用原生 DOCX 解析提取正文。backend/dms-storage/preview/;覆盖上传后使用新文件哈希生成新缓存。backend/dms/resources/ui-dictionaries.zh-CN.json,部署时可通过 DMS_UI_DICTIONARY_CONFIG_PATH 指向外部UTF-8 JSON文件。roleCodes、allowedModules、documentTypes、documentStatuses、securityLevels、visibilityTypes、attachmentTypes、subjectTypes、allowedActions、categoryTypes、enabledStatuses、auditResults、auditActions、auditTargets。GET /api/v1/documents、GET /api/v1/main-plans/{id}/sub-plans和GET /api/v1/main-plans/{id}/attachments统一支持可选的 updatedFrom、updatedTo。updatedFrom表示文档 updated_at >= updatedFrom,updatedTo表示文档 updated_at <= updatedTo;同时提供时为闭区间,且开始时间不得晚于结束时间。Z格式;后端接受合法带时区ISO 8601并归一化为UTC,禁止把无时区时间当作UTC。400 INVALID_ARGUMENT及requestId。执行会话不得直接修改本文件。需要变更时,应:
版本1.1经统领会话批准,引入独立回收站资源和单条文档恢复;旧文档恢复路径继续永久废止。
版本1.2经统领会话批准,引入只读统一UI字典配置和查询接口,不修改既有枚举、数据库结构或业务语义。
版本1.3经统领会话批准,统一三个既有列表接口的文档更新时间范围检索,不新增路径、数据库字段、索引或迁移;Office预览不得占用1.3版本。
Q2-B实现时必须同步将OpenAPI info.version升级为 1.3.0。
ADMIN 和 USER。ADMIN返回DOCUMENT_BROWSER、BACKEND_MANAGEMENT、AUDIT_LOG,USER只返回DOCUMENT_BROWSER。四个审计查询接口和文档统计接口仅ADMIN可访问。历史AUDITOR必须失效旧Token、停用并逻辑删除,不得提升为ADMIN。409 CATEGORY_NOT_LEAF,并在details返回categoryId和childCategoryCount。已直接存放有效MAIN的叶子分类不得新增有效子分类,也不得成为分类移动目标。CategoryNode.documentCount表示当前JWT用户在该分类完整有效子树内有权查看的有效MAIN数量。关键词过滤保留祖先节点时,计数仍基于完整业务子树,不按过滤后的可见节点截断。GET /api/v1/documents支持includeDescendants。未传categoryId时查询全部可见MAIN;传分类并设置true时查询该分类及全部有效后代;false或缺省时精确匹配分类。PUBLISHED、CUSTOM且初始ACL为空。SUB_PLAN创建不接收categoryId、status或visibilityType,分类继承父MAIN,状态固定PUBLISHED,可见范围动态继承父MAIN。编辑同样不接收status和visibilityType,SUB_PLAN也不接收categoryId;主案改分类时同步有效子方案的分类冗余。nosniff和private, no-store,并执行授权、相对路径、普通文件、存在性、大小、SHA-256、扩展名、文件头及Office ZIP结构校验。DOC、XLS、XLSX返回415 PREVIEW_UNAVAILABLE。预览不增加downloadCount且不写DOWNLOAD_DOCUMENT审计。doc_document保存content_text、content_extract_status和content_extracted_at;search_text升级为LONGTEXT并组合名称、摘要、标签和正文。DOCX提取段落、表格、页眉页脚,PDF提取文本层;DOC为UNSUPPORTED。提取失败不丢失原文件。回填命令只允许显式连接dms_test且不得自动执行。DMS_BUSINESS_TIMEZONE,默认Asia/Shanghai,非法值在应用配置加载阶段失败。本版本数据库迁移为0003_q3_business_alignment_and_content_search,OpenAPI版本为1.4.0。