Files
NotesAgentic/docs/contracts/Host-v1契约.md
T

56 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Rust Host v1 预览契约
状态:Rust 核心测试、clippy、Tauri 工程编译及 Windows GNU 开发可执行文件构建通过。**尚无可发布安装包,新标题栏仍待原生界面实测**。不将开发构建等同 D01–D08 全部通过。
## 命令
只允许本地 `main` WebView 使用 capability。不存在通用 shell、任意路径打开、任意 HTTP 转发或明文凭据读取命令。目录授权由原生目录选择器完成。
| 命令 | 参数 / 返回 |
| --- | --- |
| `host_capabilities` | protocol=1workspace/credentials=truecore 随进程状态返回;sync/extensions=false |
| `core_request_prepare` | timeout_ms1600000),返回一次性 request_id;最多 64 个待执行/在途请求,默认前端超时 30000 ms |
| `core_request` | request 对象含 requestId、method、path、body/bodyBase64、contentType、idempotencyKey;必须使用未过期的预登记 ID 且仅执行一次。代理认证 Sidecar 的 `/health``/api/*`,不接受前端鉴权头 |
| `core_request_cancel` | request_id;取消未发送的预登记项或终止在途 HTTP Future,重复取消无副作用 |
| `workspace_choose` | 原生选择,取消返回 null;成功返回 vault_id/path/name |
| `workspace_open` | 只允许重开应用数据目录中已持久化授权的规范化路径 |
| `workspace_recent` | 最近 20 个用户主动选择的 Vault;只保存身份、名称和路径 |
| `workspace_revoke` | 释放当前 Vault;不删除用户内容 |
| `workspace_tree` | Markdown 与目录树;file_id/path/hash/revision/deleted/is_folder |
| `workspace_read` | path,返回条目与 UTF-8 content |
| `workspace_write` | path、expectedSHA-256)、content;返回新条目 |
| `workspace_operation` | vault_id、operation_id;返回 pending/committed/conflict 与提交时条目,未知 ID 返回 null |
| `workspace_rename` | path、destination、expected;文件 ID 保持不变 |
| `workspace_delete` | path、expected;正文保存在 `.ainote/trash` |
| `workspace_mkdir` | path,相对当前授权 Vault |
当前错误通过 Tauri rejection 返回稳定 code,前端 `DesktopError` 保留该 code。主要 code 为 REVISION_CONFLICT、RECOVERY_CONFLICT、UNSAFE_PATH、PATH_CONFLICT、VAULT_ALREADY_OPEN、SCHEMA_INCOMPATIBLE、ATOMIC_REPLACE_FAILED。常规 Core 请求新增 REQUEST_CANCELLED、REQUEST_TIMEOUT 及预登记错误;前端取消/超时错误带 request_id 和 outcomenot_sent/unknown)。已经发送的写入不能推断回滚,不自动重试;按业务 operation_id 确认提交结果的完整链路仍待实现。
凭据保险库解锁前取得独立 `.lock` 文件的 OS 排他锁,持有至手动锁定、错误后锁定或实例销毁。其他实例返回 CREDENTIALS_BUSY,不读取旧快照后继续覆盖写入;错误口令释放临时锁,进程退出由 OS 释放。Windows 禁止在持锁期间替换该锁文件。
Windows 使用独立隐藏窗口注册 WTS 会话通知,锁屏、注销及本地/远程会话断开立即增加凭据撤销代际。新解析和新修改检查该代际,不等待解锁 KDF 的 Mutex;解锁过程中发生撤销则解锁失败。后台清理加密会话,系统解锁不会自动解锁凭据库。通知注册失败时凭据解锁返回 SESSION_MONITOR_UNAVAILABLE,但本地笔记继续可用。设置页每 500 ms 刷新真实锁定状态。
`credentials_backup` 不接受路径参数,以原生保存窗口选择新的 `.onxcred` 文件,只导出加密快照且拒绝覆盖已有文件。`credentials_restore(password)` 通过原生文件选择和原生确认对话框恢复,要求当前保险库已锁定。先验证口令及每条凭据,再保留恢复前的加密文件并原子替换;失败不覆盖现有库,成功后仍保持锁定。口令对应备份创建时的口令,不能通过备份绕过口令遗失。两项命令均不返回秘密或文件内容。
## 写入及恢复
Workspace schema 2 新增持久操作回执。`workspace_write` 可选 operation_idUUID),同 ID、同载荷重放返回原提交条目;不同载荷返回 OPERATION_PAYLOAD_CONFLICT。回执与文件元数据、outbox 在同一 SQLite 事务提交,即使之后再次编辑,查询仍返回对应操作的原始结果。schema 1 升级前用 SQLite VACUUM INTO 保存一致备份;旧 schema 1 Host 拒绝写入 schema 2。
Core 的 `workspace.list/read/write/mutate/operation` RPC 通过受控管道转发,严格拒绝未知字段并校验 Host HTTP 请求捕获的 vault_id。切换或撤销工作区后旧任务返回 VAULT_PERMISSION_CHANGED。普通 HTTP 与 SSE 均由 Rust 添加工作区头,WebView 不能指定。Core 笔记 CRUD 不再写入 unbound-vault,也不从旧 Core 笔记索引回退读取;Markdown 元数据随正文保存,笔记 ID 使用 Rust file_id。当前 Core 笔记 RPC 单篇上限 1 MiB,管道帧上限 8 MiB;大媒体传输与完整取消提交确认另行实现,不宣称已满足完整 A-03。
桌面检索与任务使用 Core 数据目录中的 `vault-state/<vault_id>/core.sqlite3`,不同 Vault 不共享笔记/向量/任务行。该库含持久任务,不能作为缓存整体删除。搜索前通过 Host 扫描摘要并事务更新全文投影,删除与修改使旧向量失效;向量重建通过 Host 读取正文并保持稳定 file_id。模型配置和凭据仍属设备配置,不随笔记库路由。没有授权 Vault 的知识请求明确失败,不回退全局索引。旧版无归属的 Core 任务不会自动指派给任意 Vault,其迁移入口仍待完成。
OS 文件锁配合 Rust Mutex 维持单实例 Vault 写入。Web `serialized_vault_mutation` 使用同一 OS 文件锁;发现 `.ainote/host.sqlite3` 后拒绝 Web 写入,不自动降级。已有个人 Vault 不会被测试读取或迁移。
保存前对比实际磁盘 SHA-256,先持久化包含内容的 journal,再同目录临时文件刷盘和替换,最后提交元数据及 outbox。文件已替换但数据库未提交时,启动恢复补齐同一 operation_id。摘要不匹配则保留 journal 冲突及外部正文。remote origin 不再次入 outbox。outbox 目前只持久化,**尚无上传/拉取循环**。
移动和删除另有 file_ops 日志;目标或回收正文刷盘后才删除来源,数据库失败可重放。Windows reparse point(包括 junction)、越界路径、保留目录和设备名被拒绝。最近 Vault 授权保存在应用数据目录的独立 SQLite 中,使用事务更新且不包含正文;任意路径不能绕过目录选择直接加入。大小写重命名暂报 PATH_CONFLICT,UNC 不支持;附件树、多窗口共享、目录移动/删除、稳定外部重命名识别、监听去重及完整恢复 UI 尚未实现。
本地恶意进程仍可能在路径校验与系统调用间改变文件系统;该预览不是 OS 沙箱。发布前须补句柄级路径固定及突破测试、磁盘满/掉电故障注入、真实 WebView 交互、性能门禁。
## 前端与发布
Web 模式沿用现有服务。Tauri Workspace Service 调用原生命令;Host 自动启动受认证的 Core,使用随机端口和管道交换会话;Core 不可用时返回稳定错误码。SSE 使用 `core_stream`/`core_stream_cancel`,凭据命令提供状态、解锁、手动锁定、改密及原生导入;细节与未完成项见[生产化实施记录](../development/OpenNexus生产化实施进度-2026-09-08.md)。桌面窗口关闭系统装饰,统一由应用标题栏提供拖动、最小化、最大化/还原及关闭;窗口命令只授予本地 `main` WebView。关闭请求先尝试保存,冲突或保存失败时保持窗口。标题栏下的完整应用菜单复用 `editorCommandService`,主题菜单直接调用统一主题 Store;功能页使用 `feature-page``feature-header``panel` 等主题扩展点,确保自定义主题同时作用于编辑器与应用页面。原生菜单事件和可见“段落”菜单复用 `editor.import-note-properties`;仅在源码模式、已打开笔记且无冲突时启用,转换作为单次编辑器历史事务执行。
默认 `bundle.active=false`,新增 `tauri.bundle.conf.json` 配置 Core 资源及 NSIS 目标,尚无自动更新或签名安装包。release Host 前必须执行 `uv run --directory backend --group packaging python ../scripts/build-core.py` 生成并嵌入 Core 摘要清单。开发命令为前端 `pnpm dev``cargo run --features desktop`;生产 EXE 必须在 `frontend` 目录执行 `pnpm desktop:build`,由 Tauri CLI 先构建并嵌入前端资源。不要用普通 `cargo build --release` 代替该命令,否则 Rust Host 会更新但 WebView 仍可能携带旧资源。需要对应平台 C++ 工具链和 WebView;本次 Windows 已使用系统 `x86_64-pc-windows-gnu` 工具链构建,仍不替代 MSVC 或其他平台验证。