fix: 串行化凭据所有权并响应桌面请求取消

This commit is contained in:
2026-09-08 13:16:11 +08:00
parent 8d9333d8b0
commit 0d225f308f
21 changed files with 1034 additions and 118 deletions
@@ -0,0 +1,271 @@
{
"date": "2026-09-08",
"base_commit": "6bf5127",
"known_defects": {
"F-01": "FIXED",
"F-02": "FIXED"
},
"automated_regression": "PASSED",
"production_acceptance": "NOT_PASSED",
"counts": {
"backend": {
"tests": 894,
"failures": 0,
"errors": 0,
"skipped": 0
},
"packaged-core": {
"tests": 4,
"failures": 0,
"errors": 0,
"skipped": 0
},
"sync": {
"tests": 23,
"failures": 0,
"errors": 0,
"skipped": 0
},
"community": {
"tests": 13,
"failures": 0,
"errors": 0,
"skipped": 0
},
"frontend": {
"tests": 504,
"failures": 0,
"errors": 0,
"skipped": 0
},
"rust": {
"passed": 28
}
},
"checks": [
{
"name": "rust-fmt",
"command": [
"cargo",
"fmt",
"--manifest-path",
"frontend/src-tauri/Cargo.toml",
"--check"
],
"exit_code": 0,
"seconds": 0.383,
"finished_utc": "2026-09-08T05:09:44.693513+00:00",
"artifact_directory": ".build\\acceptance\\fixes-final-6bf5127"
},
{
"name": "rust-tests",
"command": [
"cargo",
"test",
"--manifest-path",
"frontend/src-tauri/Cargo.toml",
"--features",
"desktop",
"--all-targets",
"--locked"
],
"exit_code": 0,
"seconds": 39.22,
"finished_utc": "2026-09-08T05:10:23.925087+00:00",
"artifact_directory": ".build\\acceptance\\fixes-final-6bf5127"
},
{
"name": "rust-clippy",
"command": [
"cargo",
"clippy",
"--manifest-path",
"frontend/src-tauri/Cargo.toml",
"--features",
"desktop",
"--all-targets",
"--locked",
"--",
"-D",
"warnings"
],
"exit_code": 0,
"seconds": 3.526,
"finished_utc": "2026-09-08T05:10:27.480493+00:00",
"artifact_directory": ".build\\acceptance\\fixes-final-6bf5127"
},
{
"name": "backend",
"command": [
"uv",
"run",
"--directory",
"backend",
"pytest",
"-q",
"--junitxml=G:\\OSProject\\NotesAgent-phase3\\.build\\acceptance\\fixes-6bf5127\\backend.xml"
],
"exit_code": 0,
"seconds": 199.768,
"finished_utc": "2026-09-08T05:06:18.641433+00:00",
"artifact_directory": ".build\\acceptance\\fixes-6bf5127"
},
{
"name": "packaged-core",
"command": [
"uv",
"run",
"--directory",
"backend",
"pytest",
"-q",
"tests/test_sidecar_auth.py",
"--junitxml=G:\\OSProject\\NotesAgent-phase3\\.build\\acceptance\\fixes-6bf5127\\packaged-core.xml"
],
"exit_code": 0,
"seconds": 3.742,
"finished_utc": "2026-09-08T05:06:22.396738+00:00",
"artifact_directory": ".build\\acceptance\\fixes-6bf5127"
},
{
"name": "frontend",
"command": [
"pnpm",
"--dir",
"frontend",
"exec",
"vitest",
"run",
"--maxWorkers=2",
"--reporter=default",
"--reporter=junit",
"--outputFile.junit=G:\\OSProject\\NotesAgent-phase3\\.build\\acceptance\\fixes-final-6bf5127\\frontend.xml"
],
"exit_code": 0,
"seconds": 56.45,
"finished_utc": "2026-09-08T05:10:40.765672+00:00",
"artifact_directory": ".build\\acceptance\\fixes-final-6bf5127"
},
{
"name": "types",
"command": [
"pnpm",
"--dir",
"frontend",
"type-check"
],
"exit_code": 0,
"seconds": 7.819,
"finished_utc": "2026-09-08T05:10:48.619856+00:00",
"artifact_directory": ".build\\acceptance\\fixes-final-6bf5127"
},
{
"name": "build",
"command": [
"pnpm",
"--dir",
"frontend",
"build"
],
"exit_code": 0,
"seconds": 34.154,
"finished_utc": "2026-09-08T05:11:22.812302+00:00",
"artifact_directory": ".build\\acceptance\\fixes-final-6bf5127"
},
{
"name": "sync",
"command": [
"uv",
"run",
"--directory",
"server sync",
"pytest",
"-q",
"--junitxml=G:\\OSProject\\NotesAgent-phase3\\.build\\acceptance\\fixes-6bf5127\\sync.xml"
],
"exit_code": 0,
"seconds": 9.874,
"finished_utc": "2026-09-08T05:08:10.342428+00:00",
"artifact_directory": ".build\\acceptance\\fixes-6bf5127"
},
{
"name": "community",
"command": [
"uv",
"run",
"--directory",
"community-server",
"pytest",
"-q",
"--junitxml=G:\\OSProject\\NotesAgent-phase3\\.build\\acceptance\\fixes-6bf5127\\community.xml"
],
"exit_code": 0,
"seconds": 3.162,
"finished_utc": "2026-09-08T05:08:13.520864+00:00",
"artifact_directory": ".build\\acceptance\\fixes-6bf5127"
},
{
"name": "smoke",
"command": [
"G:\\OSProject\\NotesAgent-phase3\\backend\\.venv\\Scripts\\python.exe",
"scripts/phase3-isolated-smoke.py"
],
"exit_code": 0,
"seconds": 3.411,
"finished_utc": "2026-09-08T05:08:16.933393+00:00",
"artifact_directory": ".build\\acceptance\\fixes-6bf5127"
},
{
"name": "docs",
"command": [
"python",
"scripts/check-doc-links.py"
],
"exit_code": 0,
"seconds": 7.01,
"finished_utc": "2026-09-08T05:11:29.830898+00:00",
"artifact_directory": ".build\\acceptance\\fixes-final-6bf5127"
},
{
"name": "diff",
"command": [
"git",
"diff",
"--check",
"--",
".",
":(exclude)backend/data/vault"
],
"exit_code": 0,
"seconds": 0.119,
"finished_utc": "2026-09-08T05:11:29.989493+00:00",
"artifact_directory": ".build\\acceptance\\fixes-final-6bf5127"
}
],
"remote_health": {
"checked_at": 1788844300.226044,
"url": "http://yui.kronecker.cc:18080",
"checks": [
{
"path": "/health",
"status": 200,
"expected": 200
},
{
"path": "/ready",
"status": 200,
"expected": 200
},
{
"path": "/sync/v1/handshake",
"status": 200,
"expected": 200
},
{
"path": "/sync/v1/vaults",
"status": 401,
"expected": 401
}
]
}
}
@@ -0,0 +1,42 @@
# OpenNexus 验收修复与全量回归(2026-09-08)
本次在 `feat/phase3-completion` 工作树、基线 `6bf5127` 上修复了原验收中复现的 F-01、F-02,并完成现有自动化测试的全量回归。原始失败记录保留在[首次验收报告](OpenNexus验收报告-2026-09-08.md);本报告不将尚未实现或缺少证据的生产化验收目标标记为通过。
## 修复内容
### F-01:多个凭据 Broker 覆盖快照
Stronghold 在读取快照前取得同目录独立锁文件的操作系统排他锁,并持有至凭据库锁定。第二个实例返回 `CREDENTIALS_BUSY`,设置页提供可理解的提示。锁文件独立于原子替换的快照文件;Windows 禁止其他句柄删除被持有的锁文件。解锁失败或进程退出时释放所有权。
回归测试验证两个实例交接后两次写入均保留、错误密码不遗留锁,以及真实子进程持锁时拒绝并发解锁、子进程被终止后能重新解锁并读取已提交凭据。
### F-02:桌面请求忽略取消和超时
前端和 Rust Host 使用先预留、后派发的请求协议。已取消请求不会派发;等待预留期间取消后,迟到的预留会被清理。Host 对请求使用独立截止时间和取消信号,限制最多 64 个预留,拒绝重复执行,并在退出时清理状态。取消正在读取的 HTTP 响应会丢弃请求 Future,真实 TCP 测试验证连接关闭。普通桌面请求默认超时 30 秒,可配置至 600 秒。
前端清理计时器和监听器,保留二进制传输。写请求派发后取消或超时会报告结果未知,提示先检查业务结果,不自动重试。取消不代表服务端事务回滚;业务提交结果查询仍未完成,不能据此认定完整 A-03 验收通过。协议详见 [Host v1 契约](../contracts/Host-v1契约.md)。
## 测试结果
| 范围 | 最终结果 |
| --- | --- |
| 后端 pytest | 894 通过 |
| 前端 Vitest | 93 个文件,504 通过 |
| Rust desktop 全目标测试(locked | 28 通过 |
| Sync pytest | 23 通过 |
| Community pytest | 13 通过 |
| 打包 Core 认证回归 | 4 通过(单独运行,和后端套件有重叠) |
| 三服务隔离冒烟测试 | 通过 |
| 前端类型检查、生产构建 | 通过;构建仍提示部分 chunk 大于 500 kB |
| Rust fmt、Clippy 全目标 `-D warnings` | 通过 |
| 文档链接、变更空白检查 | 通过 |
本地完整命令、退出码和日志位于 `.build/acceptance/fixes-6bf5127/``.build/acceptance/fixes-final-6bf5127/`。随文的 JSON 汇总保存命令和最终结果;原始日志属于本地构建产物。首轮新增 TCP 测试因同步等待阻塞 Tokio 清理而失败,改为异步等待线程结束;Clippy 发现 Host 参数数量超限,改为严格的结构化请求 DTO。修复后 Rust、前端及构建检查均重新通过,未改动的 Python 服务沿用本轮先前已通过结果。编辑器测试仅调整冷启动等待预算,保留原有断言。
## Sync 测试部署复核
对 [Sync 测试服务](http://yui.kronecker.cc:18080) 的公网复核结果为:`/health``/ready``/sync/v1/handshake` 返回 200,未认证访问 `/sync/v1/vaults` 返回 401。本次修复只涉及桌面端,未重新部署服务。此前 100 MiB 上传下载、并发 CAS、重启持久性等证据仍以首次验收报告为准,本次没有重复这些远程压力测试。
## 验收边界
本次结论为已知缺陷关闭、现有自动化回归通过。完整生产化验收仍未通过:操作系统级插件隔离、扩展管理、完整 Rust 同步客户端等规划能力仍有未完成项;本次也没有补充 MSVC 安装包、真实双设备桌面操作和完整故障矩阵的验收证据。不能将测试数视为规划中 30 个验收 ID 全部完成。用户 Vault 文件未纳入本次修改或提交。