Smail/docs/模拟部署与最新构建.md
smail 9c450f1734
Some checks are pending
Security Checks / security (push) Waiting to run
运行时配置清理阶段检查点
2026-10-05 01:31:34 +08:00

9.0 KiB
Raw Blame History

模拟部署与最新构建

已确认要求

  • 源码继续放在 backend/、frontend/。
  • 生产、开发模拟部署均使用 yunx-test/,禁止把 out/ 当运行目录。
  • 配置固定为 config/ 中的五个 JSON;证书及加密密钥归 ssl/;数据库归 data/;日志归 log/。
  • 保留独立的 smail、smail-admin。Windows 使用 .exe 后缀。
  • 前端开发仍使用原源码目录的 Vite 热更新。
  • 不清空现有业务库,不删除原证书、密钥及历史备份。

当前任务状态

  • [✓] 修改前的文档基线已提交并推送。
  • [✓] 源码指纹和产物 SHA-256 校验已加入构建、部署入口。
  • [✓] 开发启动入口固定使用 yunx-test,没有沿用旧后端;日志与进程路径已核对。
  • [✓] Vite 从原 frontend 源码启动,使用模拟部署目录的域名和证书;浏览器已确认加载开发客户端。
  • [✓] 停服备份、无损迁移到 yunx-test,原配置、证书、账号库和备份全部保留。
  • [✓] 配置事务与历史备份迁入 data/smail-state.db,五个 JSON 仍是生效配置文件。
  • [✓] 密钥、TLS、DKIM、ACME 和审计日志迁到最终目录,目录检查通过。
  • [✓] 三个内置插件已编译并嵌入主程序;运行解包目录位于操作系统临时目录,不混入部署根目录。
  • [✓] 迁移后的完整构建、产物哈希校验通过;审计导出修复后再次执行前端 138 项、部署 4 项及全量 Go 测试,全部通过。
  • [✓] Windows 标准构建与后端测试入口共用工作区互斥量,4 项部署回归通过。
  • [✓] 新目录开发运行、登录后刷新保持会话、配置读取和配置审计 CSV Blob 验收通过。
  • [✓] HTTPS Cookie 属性及 CSRF 缺失、错误、正确令牌分支已实际验证。
  • [✓] 构建互斥及审计导出修复后的完整部署、重启和源码指纹复查通过。
  • [✓] 审计 Blob 错误保留最近认证状态;真实页面密码确认、自动重试及成功提示通过,下载文件落盘尚未核验。
  • [!] Windows 生产模拟启动受管理员恢复 Named Pipe 权限限制,未降级或绕过保护。
  • [!] Windows 生产插件隔离尚不可用,不能把插件打包成功视为真实插件运行验收。
  • [ ] 配置保存后文件与历史状态数据库的浏览器写入验收。
  • [ ] 全新初始化、忘记密码、二次验证、强制改密与普通用户权限的独立完整流程验收。

已实现入口

完整构建并部署二进制,不覆盖配置和数据库:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File deploy/deploy-runtime.ps1

完成运行数据迁移后,启动前后端:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File deploy/start-dev.ps1 -Service all

后端启动总是先完整编译、部署和校验。单独启动前端会校验当前源码与部署产物,不允许搭配过期后端。缺少迁移后的配置、账号库或密钥时拒绝启动,不会创建另一份空库。

构建收据保存在 out/build-state.json,不混入部署根目录。已有程序被覆盖前备份至 out/deployment-history/。历史前端编译目录归档至 out/build-history/,不删除生成物,也不将历次散列资源重复嵌入新程序。

构建与测试互斥

Windows 下,deploy/build.ps1 与 node test/run.mjs backend 共用工作区命名互斥量。构建计算指纹、归档嵌入资源之前就获取锁,测试从调用 Go 到退出始终持锁。遇到冲突立即拒绝执行并给出中文提示,不能继续移动资源或使用历史产物冒充成功。

锁标识由源码目录生成:同一登录会话内,不同工作区可并行;同工作区必须串行。正常退出和进程异常结束均不需要删除锁文件。不同 Windows 登录会话、直接调用 go test、直接调用 Vite 或单独插件构建不在该锁的保证范围内,不能与完整构建并发执行。

# 前端、部署回归和后端依次执行,记录统一进入 test-log。
node test/run.mjs all -p 2 ./...

# 只检查构建互斥及后端参数转发。
node test/run.mjs deployment

新增的 PowerShell 文件使用 UTF-8 BOM,以便 Windows PowerShell 5.1 正确解析中文提示;JavaScript、Go 和 JSON 不因此添加 BOM。

前端热更新只更新源码开发页面,不会自动重编嵌入前端的主程序。源码修改完成后,仍须通过标准完整部署/重启入口刷新 yunx-test,不能只刷新浏览器就宣称运行包已更新。

2026-09-08 实测记录

  • 迁移备份与核对收据:test-log/deployment-migration-20260908-183213/receipt.json。
  • 互斥修复后的完整自动化测试:test-log/run-2026-09-08T10-57-18-160Z-42364/,前端 131 项、部署 4 项、Go 全量测试均通过。
  • 完整构建期间,通过标准入口启动的后端测试被互斥量拒绝,退出码为 1:test-log/run-2026-09-08T11-00-20-202Z-41728/backend.log。这次失败属于预期防护结果,不是 Go 代码测试失败。
  • 审计导出修复后的前端回归:test-log/run-2026-09-08T11-05-45-804Z-42172/,138 项全部通过。
  • 当前代码再次执行 node test/run.mjs all -p 2 ./...:test-log/run-2026-09-08T11-16-56-516Z-46036/,前端 138 项、部署 4 项和全量 Go 测试全部通过。自动化测试使用独立测试环境,不清空正在运行的业务数据库。
  • 浏览器页面为 https://example.com/#/,前端 80 跳转 HTTPS 443,后端开发接口监听 5201。
  • 浏览器真实登录后强制忽略缓存刷新,收件箱与用户信息接口仍正常。配置状态、基础、邮件、证书、历史备份及插件列表读取成功。
  • 配置审计导出返回 text/csv Blob;真实页面已完成“确认当前密码 → 自动重试 → 审计记录已导出”,但尚未核验下载文件落盘。
  • 缺失或错误 CSRF 请求头均返回业务错误码 100,提示“请求来源校验失败”;当前接口使用 HTTP 200 包装业务错误,不能只看 HTTP 状态判断成功。
  • 正确 CSRF 请求返回 CSV;HTTPS 登录响应中会话 Cookie 为 Secure/HttpOnly/SameSite=Lax,CSRF Cookie 为 Secure/SameSite=Strict。后者允许前端读取用于请求头,不应加 HttpOnly。
  • Cookie 响应验证使用独立临时登录会话,结束后已退出;未将密码、Cookie 值或令牌写入测试记录。
  • 生产模拟失败记录:test-log/production-runtime-20260908.log。开发运行明确停用管理员恢复通道,生产不能复用这一豁免。

审计导出最近认证修复

登录超过最近认证时限后,导出接口返回 HTTP 403、业务错误码 405,以及 RECENT_AUTH_REQUIRED。原先 Axios 使用 responseType: 'blob' 时把 JSON 错误包装为 Blob,错误拦截器读不到业务错误码,只显示“无权访问”;导出操作也未接入现有的密码确认重试流程。

修复后,仅解析不超过 1 MiB、JSON 类型且具有非零数字 errorNo 的 Blob 错误信封;CSV、正常 JSON 导出、未知或损坏内容保持原样。导出操作复用最近认证流程,取消确认不误报失败,认证后最多重试一次,不放宽后端权限要求。

浏览器真实请求链已复核:

  1. reqid=1113:POST /api/v1/audits/config 返回 403,页面弹出“确认当前密码”。
  2. reqid=1114:POST /api/v1/security/reauth 返回 200,身份确认成功。
  3. reqid=1115:自动重试 POST /api/v1/audits/config 返回 200,页面提示“审计记录已导出”。

验收记录不保存密码、Cookie 值、CSRF 令牌或导出审计内容。

最终运行核对

2026-09-08 19:15 左右,node deploy/check-runtime.mjs 与 node deploy/build-state.mjs verify --deployed 均通过:

  • out/build-state.json 记录构建源码提交为 9855a20,构建时间为北京时间 19:06:33。
  • 部署产物与当前源码指纹一致;之后的检查点或仅文档提交不会改变源码指纹,不需因此重复替换运行包。
  • 后端进程 PID 26148,路径为 D:\Desktop\Smail\yunx-test\smail.exe,带明确的开发恢复通道停用参数。
  • 前端进程 PID 21008,使用原 frontend/node_modules/vite/bin/vite.js,监听 443;后端 5201 /api/ping 与前端 HTTPS 均返回 200。
  • yunx-test 根目录仅有 config/、ssl/、data/、log/、smail.exe、smail-admin.exe;config/ 仅有约定的五个 JSON。

上述 PID、构建时间和请求编号是本次验收快照;下次启动或验收必须重新检查,不应直接沿用。

验收边界

此次是保留现有业务数据的迁移验收,未清空数据库,不是生产首次初始化验收。旧根目录的 config/、data/、ssl/ 是保留的迁移来源,不是当前服务的生效目录。

生产管理员恢复、Windows 插件隔离、其他完整账号流程仍有未通过或未验证项目。编辑器异步包仍有约 809 kB 的 Vite 体积告警;不能宣称全部功能或全部优化均已完成。