nex_docus/docs/sdd/releases/v1.0.0.md

17 KiB
Raw Blame History

Release v1.0.0(首个正式版本)

本文件是 v1.0.0 的发布记录与验证边界。发布内容 = git 基线 ba80d28 fix project role permission(v0.9.9-SP1 之后)+ 当前工作区未提交的发布前整改。 上线动作:本发布尚未打 git tag,需在整改提交合并后执行 git tag -a v1.0.0 -m "NEX Docus v1.0.0" 并推送,使「版本以 git 为准」的规则重新成立。

元数据

项 值
版本 v1.0.0(首个正式版本 / 第一个大版本)
git 基线提交 ba80d28 fix project role permission(main)
上一条版本标记 eea3b96 v0.9.9-SP1(非连续,其间的 5d41339/fef17e5/b3f5fb0/dfd4618 无版本标记)
git tag 待创建 v1.0.0
代码内版本字段 backend/app/core/config.py APP_VERSION = "1.0.0";frontend/package.json version = "1.0.0" — 已对齐
适用组件 backend(FastAPI + SQLAlchemy + MySQL + Redis)、frontend(React 18 + Vite + antd + ByteMD)、docker-compose 部署编排、scripts/ 运维脚本
数据库 无 schema 变更(本发布不含迁移;表结构与 docs/database.md 一致,共 18 张表)
破坏性变更 脚本路径 ./deploy.sh → ./scripts/deploy.sh;.env 移除 VITE_API_BASE_URL(详见部署与配置变更日志)

历史遗留说明:v0.9.9.md 与旧 releases/README.md 曾把代码里的 1.0.0 判定为「遗留占位」。本发布通过显式建 tag 把版本线正式推进到 v1.0.0,占位问题到此结束。

本发布范围

1. 文档编辑体验(DV-0003)

  • 编辑器默认只打开编辑区(edit / split / preview 三态可切换,选择写入 localStorage 并按用户记忆)。旧行为是编辑区与预览区同时打开。
  • 视图模式切换并入编辑器工具栏:三态分段控件由内容区标题栏移到 ByteMD 编辑器工具栏右侧,与内置「全屏」按钮同排(createPortal 注入 .bytemd-toolbar-right 末个子节点),只保留图标 + Tooltip(「编辑 · 仅编辑区」等);与重复的内置开关(文档索引 / 帮助 / 仅编辑 / 仅预览)统一隐藏,标题栏只留「未保存」标记与保存/重置。
    • ByteMD 由 Svelte 渲染且会在 StrictMode 双挂载、切换文档时重建 DOM,插槽采用 MutationObserver + rAF 持续校验(缓存节点 isConnected 失效即重找),避免 Portal 渲染到游离节点。
    • 仅分栏模式显示「同步滚动」开关;纯编辑 / 纯预览下自动隐藏。
  • 修复编辑器全屏层级:ByteMD 的 .bytemd-fullscreen 是 position: fixed 但没有 z-index,会被 .mode-switch(z-index: 1)等浮层压住,导致左侧项目树的操作按钮浮现在全屏编辑器上。现在显式抬到 var(--z-float)(900),文档索引浮标再抬一层仍可点;并补 Esc 退出全屏(自动补全等浮层打开时不抢占)。
  • Table of Contents 不再依赖预览区:新增 frontend/src/utils/markdownToc.js,大纲直接从 Markdown 源码解析(标题层级 + 滚动定位),因此在纯编辑视图下 TOC 依然可用(FloatingToc)。
  • 未保存保护:以 contentBaseline 计算 isDirty → 标题栏显示「未保存」标记;离开页面(beforeunload)与返回项目列表时拦截确认;新增全局 Ctrl/Cmd + S 保存并带 loading 并发保护。

2. UI / 交互 / 设计规范统一(跨 DV)

  • 新增设计令牌层 frontend/src/styles/design-tokens.css 与 antd 主题映射 frontend/src/theme/antdTheme.js;22 个文件中的硬编码颜色/圆角/间距替换为令牌。
  • 新增统一反馈组件 frontend/src/components/Feedback(Toast / Toast.confirm),16 处 Modal.confirm 迁移;新增路由级 PageLoading,全部路由改为 React.lazy 代码分割。
  • 新增 frontend/.eslintrc.cjs 固化前端规范;删除 33 个从未被引用的死代码组件/模块,删除无效的「语言切换」假开关。

3. 后端正确性修复

  • app/models/__init__.py 补齐 Notification、ProjectGitRepo 注册 —— 此前单独导入这两个模型会缺表,影响 metadata 完整性与新库初始化。
  • GET /api/v1/projects/{id} 由 500(MissingGreenlet)修复为正常返回:改用 require_project_read_access(..., allow_public=True) + await db.refresh(...) + serialize_project(...),响应补充 doc_count、user_role。
  • 项目角色判定统一走 normalize_project_role(历史数据角色名为大写),修复分享/仪表盘/项目接口对同一用户判定不一致的问题;projects.py 中重复的 check_project_access 死代码删除。
  • 新增回归用例覆盖角色归一化与项目读权限。

4. 仓库与运维整理

  • 脚本统一迁入 scripts/:deploy.sh(路径变更)+ 新增 start.sh 一键启动(依赖检查 / 后端 venv / 前端 vite / /health 探活)+ 新增 stop.sh;scripts/README.md 说明用途。
  • 删除 19 个与新 schema 脱节的一次性 SQL/Python 脚本、删除针对旧 compose 结构的 fix_docker_deployment.sh。
  • docker-compose.yml 去除废弃 version 字段与无效的 VITE_API_BASE_URL 构建参数;.gitignore 补 backups/、.run/;deploy.sh uninstall 行为修正。
  • 新增 backend/requirements-dev.txt 与 backend/pytest.ini,使后端测试可一条命令运行。
  • 删除根目录里与本项目无关的历史残留 .dsh-plugins/pet-dock/(第三方桌面 shell 插件,仓库内无任何引用);.gitignore 补 .claude/。

4b. 配置与安全加固

  • docker-compose.yml 补 DEFAULT_USER_PASSWORD 透传,.env.example 补齐该键 —— 此前 Docker 部署下改 .env 完全无效,新建用户恒为 User@123456。
  • 新增启动期「安全自检」Settings.security_warnings():SECRET_KEY 命中模板占位值或长度 < 16、DEFAULT_USER_PASSWORD 仍为仓库默认值时打 WARNING(只告警不阻断,兼容存量部署)。此前漏配 .env 会带着公开已知的 JWT 密钥静默上线。
  • .env.example 的 ADMIN_EMAIL 由真实域名邮箱改为 admin@example.com,与 compose / init_db.py 默认值对齐。
  • scripts/start.sh 新增 --daemon:健康检查通过后立即返回(默认仍为前台驻留 + Ctrl+C 停止),使一键启动可被 CI / 上层脚本调用。

5. 文档体系重组(docs/)

  • 根目录仅保留 README.md + docker-compose.yml + .env.example + .gitignore/.dockerignore,文档全部归入 docs/。
  • 重写:根 README.md、docs/README.md(总入口)、docs/quickstart.md、docs/database.md、docs/deploy/README.md、docs/deploy/changelog.md、backend/README.md、docs/manual/user-guide.md(13 章用户手册,替代原中文命名手册)。
  • 归档:PROJECT.md、IMPLEMENTATION_PLAN.md → docs/archive/(含登记表 docs/archive/README.md);删除内容重复且过期的 DEPLOYEE.md、README_DOCKER.md。
  • 清理文档中的明文生产凭据;修复失效链接与与代码不符的描述:健康检查统一为 GET /health(不存在 /api/v1/health)、OpenAPI 实际路径是 /openapi.json 而非 /api/v1/openapi.json、APP_NAME/ADMIN_EMAIL 默认值回填、app/utils 目录并不存在等。

能力覆盖(DV 矩阵)

DV 单元 v1.0.0 影响
DV-0001 认证与会话 无功能变更;/health 探活口径在文档中统一
DV-0002 项目与文件系统 get_project 500 修复、角色归一化、响应补 doc_count/user_role
DV-0003 文档编辑与文件操作 重点变更:默认编辑区 + 工具栏内三态切换 + 源码 TOC + 未保存保护 + Ctrl/Cmd+S + 全屏层级修复
DV-0004 RBAC 与系统管理 角色大小写归一化,读权限判定统一
DV-0005 全文检索 无功能变更;UI 令牌化
DV-0006 ZVec 向量化 无功能变更;backend/models/(本地向量模型)明确 gitignore
DV-0007 知识库 RAG 对话 UI 令牌化、Toast 反馈、SSE 约定写入 backend/README.md
DV-0008 LLM 模型配置 UI 令牌化;api_key 明文存储列为已知问题
DV-0009 分享与公开预览 角色归一化影响分享权限判定
DV-0010 通知/日志/Git/导出 模型注册修复;UI 令牌化
DV-0011 MCP 接入 无功能变更;接入说明见 docs/sdd/integrations/mcp.md

验证边界(本发布实际做过什么)

已验证(可复验)

项 命令 / 方法 结果
后端单测 cd backend && ./venv/bin/python -m pytest 40 passed,10 warnings(均为 Pydantic class Config 弃用告警)
前端静态检查 cd frontend && npm run lint 0 error / 25 warning(全部为 react-hooks/exhaustive-deps)
前端构建 cd frontend && npm run build 通过;产物见下方「已知问题」的体积表
编辑器三态 + TOC 浏览器实测(headless Chrome + CDP,1680×980,临时项目,用后已清理) 默认 编辑 且 .bytemd-preview{display:none};分栏 641/641;预览模式下左栏 Markdown 工具栏隐藏;TOC 来自源码大纲,编辑模式下点条目光标跳到目标行;切换文件(编辑器重挂载)后分段控件仍在;超大文档(>250000 字符)与 PDF 不出现分段控件
工具栏三态切换与全屏同排 同上 工具栏右侧顺序:编辑/分栏/预览(88×24)→ 全屏图标(24×24),垂直中心差 0px,工具栏高 33px 无重叠;≥1100px 视口不换行;明/暗主题配色一致
全屏层级与 Esc 退出 同上 .bytemd-fullscreen z-index:900 + fixed 覆盖 1680×980;.mode-switch(z-index:1)被完全压住(elementFromPoint 落在编辑器内);Esc 两次均退出并恢复布局
未保存保护 同上 输入 → 「未保存」标记出现;Cmd+S → 保存成功且标记消失;不脏时返回不弹框;脏时弹框且「继续编辑」保持现场
项目详情接口 GET /api/v1/projects/{id} 有权 200(含 doc_count/user_role)、不存在 404、他人私有 403,与 /files/{id}/tree 口径一致
模型注册 遍历 Base.metadata.tables 与线上库双向 diff 18 张表,差异为空
本地一键启动 ./scripts/start.sh --daemon → curl /health → ./scripts/stop.sh 脚本返回 0;后端 GET /health healthy、前端 :5173 200、.run/*.pid 保留
安全自检 tests/test_security_selfcheck.py 占位/短 SECRET_KEY、默认 DEFAULT_USER_PASSWORD 均被告警;加固后的配置零告警
文档链接完整性 全仓 Markdown 相对链接检查(排除 storage/、venv、models/) 0 断链(归档内 _assets/*.png 为预期缺图)
凭据泄露扫描 全仓明文口令扫描 仅剩 .env.example / compose / deploy.sh 的模板默认值(.env.example 内的真实域名邮箱已改占位)
文档命令/路径可执行性 逐条比对脚本与端点:GET /、/health、/docs、/openapi.json、deploy.sh --help 的子命令表、start.sh --help 一致(GET / 返回 version=1.0.0;/api/v1/health 与 /api/v1/openapi.json 均不存在,文档已修正)

未验证(发布风险,需在上线前补做)

  • Docker 端到端:本机 Docker daemon 不可用,docker compose up -d --build + ./scripts/deploy.sh upgrade 本发布未实测,只做静态审查(Dockerfile / nginx.conf / compose 已逐行核对,结论见 OI-5/OI-13/OI-14)。上线前必须演练一次:storage bind mount、SSE 流式对话、/mcp 反代、init_db.py 在空库上建表。
  • MCP 真实客户端接入:仅有接口级验证,未用真实 MCP 客户端跑通 DV-0011 全链路。
  • Git 仓库同步真实远端:project_git_repos 的 push/pull 未在真实远端验证(依赖外部环境凭据)。
  • 多浏览器 / 移动端适配:仅在 Chromium 内核验证;Safari/Firefox 与窄屏未测。
  • 升级回归:本发布无 DB 迁移,但未在「旧库 + 新代码」上做过完整冒烟(共享开发库含真实数据,禁止写测)。

已知问题(开放项)

编号 优先级 内容 建议处置
OI-P0 P0(阻塞上线) 远端 Redis(192.168.124.203)rdb_last_bgsave_status=err,最近一次成功 RDB 已距今数小时,当前靠 stop-writes-on-bgsave-error=no 临时放开写入。该参数非持久配置,Redis 重启后恢复默认 → 全量写入返回 MISCONF 上线前由运维排查磁盘/fork 内存并恢复 RDB;上线前把该参数写入正式配置或彻底修复 bgsave
OI-1 P1 敏感信息明文入库:share_links.access_pass、project_git_repos.token、llm_model_config.api_key(详情接口回传原文) 下一版本引入对称加密/KMS + 掩码回显;先限制详情接口权限
OI-3 P1 前端 0 自动化测试;后端仅 40 个用例,权限/文件系统覆盖薄 建 vitest + testing-library 基线,优先覆盖 DV-0002/0003/0004
OI-5 P1 frontend/Dockerfile 中 rm -rf package-lock.json && npm install 导致前端构建不可重现。根因已定位:package-lock.json 在 macOS/arm64 上生成,packages 里只有 @rollup/rollup-darwin-arm64,缺少 @rollup/rollup-linux-x64-musl,直接 npm ci 会在 Alpine 镜像内因 rollup 缺原生二进制而失败(脚本注释提到的正是这个 bug) 用 npm install --cpu=x64 --os=linux --include=optional(或 npm install --package-lock-only --force)重生成 lockfile 并验证含 linux-musl 条目,再切 npm ci;或把构建阶段换成 glibc 基础镜像。未做:本发布无法验证 Docker 构建,故保持现状不改
OI-6 P2 前端产物偏大:antd 1302 kB(gzip 408)、index 1242 kB(gzip 387)、index 919 kB(gzip 301)、index 522 kB(gzip 161) 按需引入 antd 图标/组件、拆分 ByteMD 相关 chunk、提高 manualChunks 粒度
OI-7 P2 超大组件:DocumentEditor 1724 行、DocumentPage 1620 行、Chat 1638 行、ProjectList 1501 行 按 DV 切片拆分子组件与自定义 hook
OI-8 P2 eslint 25 warning(全部为 react-hooks/exhaustive-deps)。原 ProjectList.jsx 成员弹窗里 4 处输出成员/用户列表的 console.log 已删除,notifications.py 4 处 print() 降级日志已改 logger(console.log/print() 全仓归零) 逐个消解 exhaustive-deps,CI 开启 --max-warnings 0
OI-9 P2 重复实现:shares.py 内本地 get_project_or_404;generate_share_code 在 projects.py 与 shares.py 各一份;api/knowledgeBase.js 命名遗留 收敛到 project_service 与统一命名
OI-10 P2 配置键名两套体系:backend/.env(STORAGE_ROOT/PROJECTS_PATH/USERS_PATH/TEMP_PATH)与根 .env(STORAGE_PATH) 下一版本统一并保留一个发布周期的兼容读取
OI-11 P2 超级管理员访问他人私有项目返回 403(全站口径已一致),但仪表盘提供全局统计 需产品明确超管边界(数据面 vs 管理面),再决定是否放开
OI-12 P3 Pydantic class Config 弃用告警 10 处;磁盘遗留 storage/projects_bak(61M)、backup/nex_docus_20260311.sql(均已 gitignore) 迁 model_config;离线归档后删除磁盘垃圾
OI-13 P1 docker-compose.yml 默认把 MySQL 3306 与 Redis 6379 发布到宿主机所有网卡(${MYSQL_PORT:-3306}:3306)。配合默认口令/占位 SECRET_KEY,等同于把数据库直接暴露到局域网 默认改绑回环:"127.0.0.1:${MYSQL_PORT:-3306}:3306";确需远程访问时用 .env 显式声明监听地址,并在主机防火墙拦截
OI-14 P2 MySQL 数据目录挂在 ${STORAGE_PATH}/mysql,而 ${STORAGE_PATH} 又整体 bind mount 进后端容器当作文档存储根(STORAGE_ROOT=/data/nex_docus_store)→ 后端容器内可见数据库文件,且 deploy.sh backup 打包 storage 时会连正在写入的 datadir 一起归档 数据库与文件存储分目录(如 ${DATA_PATH}/mysql),备份脚本显式排除 datadir
OI-15 P2 compose 里 SECRET_KEY/ADMIN_PASSWORD/DB_PASSWORD 等都有公开已知的兜底默认值,漏配 .env 时静默使用。本发布已加启动告警,但仍属"默认可用即不安全" 下一版本移除敏感项兜底值,缺配即启动失败(fail-fast)

上线清单(发布执行顺序)

  1. 按提交划分合并改动(编辑器 / UI 规范 / 后端修复 / 脚本 / 文档 / 配置 / 测试)。
  2. git tag -a v1.0.0 -m "NEX Docus v1.0.0" && git push origin v1.0.0。
  3. 先解决 OI-P0(Redis RDB),再执行部署。
  4. Docker 演练:./scripts/deploy.sh upgrade → 登录 → 打开文档编辑 → AI 问答 → 分享预览。
  5. 立即修改默认管理员密码(两套初始口令见部署变更日志),并在 .env 显式设置: ADMIN_PASSWORD=<随机值>、DEFAULT_USER_PASSWORD=<随机值>、SECRET_KEY=$(openssl rand -hex 32)。
  6. 确认 GET / 返回 version=1.0.0,并且 docker compose logs backend | grep 安全自检 无输出(有输出说明第 5 步没做完)。
  7. 按 OI-13 把 MySQL/Redis 端口绑到 127.0.0.1(或确认主机防火墙已拦截)。