Files
NotesAgentic/docs/development/OpenNexus生产化实施进度-2026-09-08.md
T

422 lines
66 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.
# OpenNexus 生产化实施进度
工作树:`G:\OSProject\NotesAgent-phase3`,分支:`feat/phase3-completion`。用户已授权实施,正式名称为 OpenNexus。保留旧应用 identifier、内部包名和数据目录约定,避免更名导致旧数据不可见。个人 Vault 的已有改动不属于本次交付。
**状态:实施中,未 done,未通过生产发布门禁。** 本文记录工程进度,不将单元测试或开发机运行替代[生产化计划](../architecture/第三阶段生产化工程规划与验收目标.md)中 AE 的完整验收。
## 当前状态摘要
截至 `7b69537`Host Sync capability 已开启,扩展 capability 仍关闭。笔记与 Task CRUD 已接入当前 Rust Vault;同步具备上传/拉取、冲突解决、非空初始合并、100 MiB 续传、主题和编辑器偏好、持久退避。Workspace 当前 schema 10(上传尝试记录增量后)。凭据备份/恢复及 WTS 撤销已实现,但实机锁屏验收仍缺。
最近完整测试:后端 900 项(Task 增量后)、前端 517 项、Rust desktop 52 项;后两者在重试持久化增量后复跑。以下各节为历史增量,出现的旧 capability、旧 schema 和旧测试数量描述对应当时状态,以本摘要及后续增量为准。OS 沙箱、Rust 扩展管理、剩余逻辑数据类别、完整故障/性能/发布验收仍未完成。
## 持续实施增量
- Rust 同步新增 schema 4 inbox/boundary、稳定远端 file_id、remote 来源的移动/删除日志和冲突保留。真实 HTTP 双客户端测试覆盖历史拉取、零回流、本机提交回放保护和同改冲突;文件提交前后的 inbox 重启测试通过。冲突解决和用户界面正在继续实施,仍不开放完整 Sync capability。
- Rust 同步上传队列与 HTTP 客户端已实现首批链路:持久绑定、spool、冻结远端基线、offset 查询续传及原子确认。20 次离线编辑/重启重试、解绑隔离测试通过;真实本地 Sync 服务验证 20 条 revision 与 100 次提交重放。Sync capability 仍保持 false,等待双向同步、会话与 UI 完成。
- 桌面全文/向量投影按 Vault 隔离,搜索前经 Host 对账文件摘要;向量重建从 Host 读取正文并保留 file_id。任务和笔记关联使用同一 Vault 的持久库。新增测试覆盖同路径双 Vault 隔离、变更/删除刷新、稳定 ID 和任务跨 Vault 不可见;真实 Core 测试增加全文搜索与删除后的检索验证。
- 检索隔离增量最终后端全量 899 项通过,真实 Core/Vault 搜索集成和 Rust desktop 全目标 Clippy 通过。语义重建的稳定 ID 测试使用显式测试 Embedding,不作为真实模型质量或性能证据。
- Core 笔记 CRUD 已经由受控管道接入当前授权 Rust Vault,保留稳定 file_id,支持 CAS 和跨 Vault 拒绝。新增 schema 2 操作回执,记录写入/移动/删除提交结果,升级前保存 schema 1 一致备份。同一写入操作重放 100 次不新增 outbox,也不覆盖后续编辑。
- 真实 Python Core + 临时 Rust Vault 集成测试覆盖创建、列表、修改、并发冲突、移动、删除、跨 Vault 拒绝和提交查询;Rust desktop 全目标 35 项通过。Core 检索投影、后台任务取消的完整提交边界、大媒体和 UI 提交确认仍需继续实现,不能将 CRUD 接通等同整个 AI 工作流验收完成。
- 此增量后端全量 897 项、前端全量 94 文件/506 项通过;Rust desktop 全目标 Clippy 与文档链接检查通过。旧 Core 打包产物尚未重新构建,不将开发解释器进程测试作为最新安装包证据。
- 已修复多实例凭据覆盖与桌面请求取消/超时,证据见[全量回归](OpenNexus验收修复与回归-2026-09-08.md)。
- 新增加密凭据备份、原生确认恢复、恢复前留存和逐条完整性验证。Windows 新增 WTS 锁屏/注销/断开通知,原子撤销解析资格;解锁不会随系统返回而自动恢复。设置页同步锁定状态,提供备份和恢复入口。
- 备份恢复、错误口令保护、锁屏后解析/写入拒绝、原生窗口通知测试通过;后者向专用测试窗口注入消息,不等于真实锁屏时延验收。前端两项交互测试、类型检查、Rust desktop 全目标 Clippy 通过。凭据旧库确认清除和迁移故障矩阵仍待补齐。
## 已实现的链路
- Rust 管理 Core 进程组;使用 stdin 引导、随机 loopback 端口、HMAC 握手、独立代际与会话令牌。每个请求先认证,拒绝浏览器 Origin、重复鉴权头及旧代际。Host 关闭时关闭管道并清理进程组,重启具有退避和次数上限。
- 常规 JSON/二进制及 SSE 请求经原生命令进入 Core。SSE 支持游标、跨 UTF-8 分片及取消;每次流累计不超过 64 MiB,最多 16 个并发流。二进制上传暂为 64 MiB,尚未满足原媒体页面 128 MiB 的完整能力。
- Core 可由 PyInstaller 构建为带运行时的 onedir。构建脚本生成 SHA-256 清单;release Host 编译时嵌入清单,启动前验证文件集合与摘要,拒绝链接、额外文件和篡改。新增 NSIS 资源配置,但尚未生成或验证签名安装包。
- Stronghold 采用 Argon2id 口令派生和单文件快照;解锁期间 Store 中仍保存 AEAD 密文。提供状态、解锁、手动锁定、改密和原生选择旧库导入命令,不提供 WebView 通用明文读取命令。
- Fernet 迁移先验证所有条目与冲突,备份密文和封装主密钥,持久化新库后重新打开逐条比较,最后切换所有权标记。旧文件保留,旧 Python 凭据 API 检测标记后拒绝读写。Core 凭据解析经 Host 管道,不在桌面 Core 使用环境变量凭据回退。
- 同步服务按已确认 offset 修复磁盘超前,磁盘不足时拒绝续传;对象上传与校验使用流;下载先验证完整摘要再响应。完成回执支持重复确认且不重复计费。过期上传每分钟清理,CLI 提供独立清理入口;启动入口支持共享 staging 的两个 worker。ready 检查数据库、staging 和对象存储,429 带 Retry-After。
## 已执行的检查
- 后端全量复跑 894 项测试通过,测试数据使用隔离目录。
- 前端现有 91 个文件、495 项测试通过;新增流式通道测试后,针对性 4 个文件、8 项测试通过;前端类型检查和生产构建通过。构建仍有部分既有大分块警告。
- Rust 15 项库测试、Core 清单完整性测试通过;两个真实 Python Core 集成测试通过,其中一个完整执行 HTTP 凭据写入、管道分发和 Stronghold 解析,确认响应与 Core 目录不泄露秘密。
- Rust desktop 全目标 Clippy `-D warnings` 通过;工具链为 Windows GNU 1.98.1,不能作为 MSVC 发布证据。
- 同步服务 23 项隔离 SQLite 测试通过,包含 100 次重复 complete。不是 PostgreSQL/MinIO 双 worker 压测。
## 尚未完成的工程和验收
| 范围 | 尚需完成 |
| --- | --- |
| Sidecar | AI 笔记读写接入当前 Rust Vault;完整路由 DTO 与取消提交确认;恢复诊断、更新事务;128 MiB 媒体传输;签名包、干净 VM 和 20 次冷启动 |
| 凭据 | OS 锁屏联动;备份恢复与用户确认清除旧库;迁移所有边界故障注入;按真实扩展身份绑定域许可 |
| OS 沙箱 | 平台隔离实现、Host broker、资源预算与恶意二进制验证;当前未启用无沙箱第三方进程 |
| Rust 扩展管理 | 签名验证、ZIP 安全边界、持久安装/升级/回滚事务、旧包迁移、撤回与运行时生命周期 |
| 同步客户端 | Rust push/pull、持久 cursor/inbox、附件续传、绑定隔离、冲突保留与解决 UI、默认/可选数据分类 |
| 同步生产服务 | 真 PostgreSQL/MinIO 两 worker 竞争与负载验证;部署、最小权限、备份恢复、指标与运行手册 |
| 发布 | 统一逐 ID 验收 runnerMSVC 签名安装更新包、SBOM/依赖扫描;两台独立设备 E-01–05 |
Core 的独立数据目录目前不等于已授权 Vault。Python 旧笔记写入口在 desktop 模式明确拒绝,不能据此宣称 AI 笔记工作流完成。Host `sync/extensions` 能力仍为 false。缺少实机与签名环境不构成其余普通工程尚未完成的理由。
## 增量:可恢复的同步冲突解决
- Workspace schema 5 在修改文件前持久保存解决选择和三个操作 ID;保留本地、采用远端、另存副本均通过现有文件 journal 提交,再归档旧上传队列。启动下一轮 push/pull 时恢复未完成的解决事务。
- 旧任务进入 conflict/archived 后拒绝上传或提交回执更新;未解决文件暂停发送,其他文件仍可推进。同路径删除后重建使用新的远端 file_id,原删除身份保留为 tombstone。
- 两个独立 Rust Workspace/会话通过真实本地 Sync HTTP 服务验证三种选择最终收敛及副本独立身份。新增三项测试覆盖文件已提交但解决记录未提交时重启、删除对编辑、远端删除后重建与恢复旧身份。
- Rust desktop 全目标 42 项通过,Clippy `-D warnings` 通过。测试服务使用隔离 SQLite/文件对象存储;尚不代表 PostgreSQL/MinIO 部署验收。不同文件身份占用同一路径仍返回明确的需改名错误,解决界面和 Host 会话接入继续实现中。
## 增量:Host Sync 会话、轮询和设置页
- 登录/刷新会话按规范化服务器地址和账户分隔,令牌只保存在 Stronghold Sync scope。手动锁定也增加撤销代际,正在等待的网络操作在下一次 50ms 检查时取消;锁定后不再解析新令牌。
- 设置页提供登录、创建/选择远端库、空库初始绑定、暂停/恢复、退出、解绑和冲突选择。绑定与覆盖决定使用界面确认;HTTP 只有显式勾选测试选项才能启用。冲突使用当前本地摘要做 CAS,旧原始快照仍保留。
- Host 提供每 5 秒串行同步,先完成固定拉取窗口再发送本地作业;SQLite schema 6 保存暂停偏好。网络失败使用有界退避并尊重 Retry-After;认证、权限、协议等错误停止自动重试并显示。绑定变化/暂停取消旧轮次。
- 真实本地 HTTP 服务验证 Stronghold 会话存储、强制刷新、关闭重开保险库后复用、退出后旧令牌 401。新增 UI 测试验证密码清空、测试 HTTP 显式传参、确认取消和冲突 CAS 参数。Rust 全目标 43 项与前端全量 95 文件/508 项通过,正式 TypeScript 两项目检查通过。前端测试仍输出既有 KaTeX quirks/localhost:3000 连接警告,没有失败项。
- 尚未完成:后台轮询真实桌面实机验收、初始非空合并预览、外部文件变化捕获、附件流式持久化及全故障矩阵、数据分类和不同身份同路径解决。不能据此标记所有 S/E 验收 ID 已通过。
## 增量:外部编辑捕获与大附件崩溃续传
- Workspace schema 7 将新 write/rename/delete journal 和 outbox 的正文替换为不可变 payload 引用,先 fsync 文件再记录摘要/长度;兼容旧内联正文恢复与上传迁移。100 MiB 不再写入 SQLite 正文列。暂不执行历史 payload GC。
- 独立 sync_observed 保存上次提交快照;文件树/编辑器读取更新 files 缓存不会吞掉外部变更。后台捕获外部新增、编辑、删除,采用快照校验且不向外部编辑器写回。重复扫描不新增 outbox;删除捕获支持重启恢复。
- 当前文件分类允许 Markdown 和 attachments 下常用附件类型,排除隐藏目录、已知缓存/日志/模型目录和可执行包扩展名;普通 JSON/配置不会直接复制。旧/新待发作业均检查分类,未支持的远端类型拒绝应用并保留游标。默认任务/Skill/配置等逻辑记录的白名单尚待实现,不作为 S-08 完整证据。
- 真实本地 HTTP 100 MiB 测试每 10 MiB 在服务端写入后、响应前强杀独立 Rust 客户端,共 10 次。恢复进程复用同一设备会话、查询服务端 offset,最终上传/下载长度、SHA-256、file_id 一致且远端落盘无回流;两个临时 Vault 的元数据文件均小于 5 MiB。最初测试错误地重新登录生成不同设备,按协议无法复用原上传,现已改为通过 stdin 传递同一受控测试会话。
- 此测试尚未覆盖完整 S-02 的每个 pull 边界 kill 20 轮,也不代表四并发服务 RSS 或生产 MinIO 性能验收。外部 rename 的稳定身份识别和目录大规模扫描优化继续实施。
- 本增量 Rust desktop 全目标 46 项通过、1 个受父测试驱动的独立进程辅助入口标记 ignored(父测试实际运行并强杀该入口 10 次);Clippy `-D warnings` 通过。
## 增量:非空初始合并与文件身份关联
- 同名独立创建的文件支持保留本地、采用远端、另存副本;先通过 journal 留存旧身份内容,再采用远端稳定身份,旧队列封存。三种选择及中途重开各 20 轮通过,真实双客户端也完成了同名创建后的收敛。
- schema 8 保存固定远端初始快照。设置页展示上传/下载/相同/冲突预览,每页 100 条;服务器、账户、远端或本地 Vault 变化会清除预览。确认时复核摘要,发生变化返回 SYNC_PREVIEW_CHANGED。初始同步只应用各文件最新可见版本,不重放历史旧路径;历史 tombstone 仅初始化远端基线,不删除本地文件。
- 初始文件全部落盘或持久保留冲突后,cursor 才一次推进到快照 boundary;任何未完成初始快照都禁止 push。逐文件提交前后重启各 20 轮通过,真实第三个 Workspace 完成相同内容身份采纳、本地独有上传、远端独有下载和冲突解决。
- Host 保存身份别名,旧文件引用仍可解析;Core 每个 Vault 的投影在身份采纳时同事务迁移本地任务链接,避免外键删除把任务 note_id 清空。新增后端关联测试通过。
- 目前快照最多处理 100000 条历史 revision,超限明确拒绝;大库快照/扫描性能、任务和配置逻辑同步、完整分类故障矩阵及签名/沙箱等其他生产门槛继续实施。
- 本增量后端全量 900 项、Rust desktop 全目标 49 项通过(另 1 个父测试使用的进程辅助入口);Sync 界面 3 项交互测试、两个 TypeScript 项目检查和 Clippy `-D warnings` 通过。
## 增量:Task 逻辑记录
- Task v1 使用专用命名空间和 Rust 字段白名单,秘密字段、未知字段/版本在 journal 前拒绝;普通配置文件仍不纳入同步。任务不依赖 Core SQLite 的全量复制,也不触发目标设备自动执行任务。
- 桌面 Task CRUD 已交由 Host 持久文件和 outbox;同操作创建重复 20 次返回同一结果,不同字段重用 ID 拒绝;更新/删除同样通过操作回执。已有当前 Vault 任务逐条迁移,保留原表且可重复完成迁移。
- 真实 Core HTTP 验证任务创建/更新/删除/重放、跨 Vault 拒绝、旧任务来源保留;真实 Sync HTTP 验证两客户端任务状态与删除传播。记录列表有 4 MiB 分页上限,读取有 1 MiB 文件上限。
- 本地文件 ID 采纳后的 task note_id 通过别名解析,上传前生成持久规范化引用,避免把本机旧 ID 留给另一设备。其余逻辑记录类别继续实施。
- Task 增量后端全量 900 项、Rust desktop 全目标 50 项通过(另 1 个父测试驱动的进程辅助入口),Clippy `-D warnings` 通过。
## 增量:主题与编辑器偏好逻辑记录
- Host 新增两个仅限主窗口、校验当前 Vault 的偏好命令;Rust 逐字段校验主题和编辑器设置,普通 JSON、权限、密钥和本机路径不进入记录。
- 设置编辑先保存按 Vault 隔离的持久草稿,再通过 CAS 写入 Workspace。覆盖选择串行等待在途写入,选择远端期间的新编辑不被丢弃;存储删除失败时保留内存及磁盘草稿并报告失败。远端主题应用不产生同步回流。
- 初始上传和合并预览包含当前偏好;空库下载不提前创建记录。真实双客户端 HTTP 测试新增主题记录传播,嵌套未知字段和非法值由 Rust 测试验证。
- 本增量全量前端 97 文件 / 515 项通过;其后补充存储故障修复,两文件 7 项针对性测试通过。TypeScript 两项目检查通过,Rust desktop 全目标通过(数量见测试日志),Clippy `-D warnings` 通过。测试日志为 `.build/preferences-frontend-tests.log``.build/preferences-rust-tests.log`。生产签名、OS 沙箱、Skill/配置等未完成项仍未通过整体验收。
## 增量:跨重启的同步退避和停止状态
- Workspace schema 9 持久保存每个绑定的错误码、失败次数、下次重试时间及 halted 状态。旧 schema 升级前保留独立 SQLite 备份。重启后自动同步沿用该状态;成功、同账户登录恢复或手动继续会清除当前绑定状态。
- 取消/切换绑定不增加失败次数,旧绑定回调不能修改新绑定;保存的错误仅允许有长度限制的机器码,不保存服务端任意响应正文。Retry-After 和指数退避保持 1–3600 秒限制。界面对停止自动重试状态不再显示误导性的倒计时。
- 连续关闭重开 20 次验证失败次数与时间保留,另验证认证停止、状态清除、取消、错误正文过滤和新旧绑定隔离。当前是绑定级轮次状态;每个上传作业的独立尝试历史、强制刷新后的 401 重试和完整服务故障矩阵仍需完成。
- 全量前端 97 文件 / 517 项、Rust desktop 全目标 52 项通过(另 1 个父测试驱动并强杀的辅助入口);TypeScript 两项目检查和 Clippy `-D warnings` 通过。日志 `.build/retry-frontend-tests.log``.build/retry-rust-tests.log`。Core 打包正在更新,不视为签名发布包。
## 增量:最新 Core 打包与 20 次冷启动
- 使用锁定 packaging 环境重新生成 PyInstaller onedir,清单包含 1523 个文件。构建日志 `.build/core-build-production.log`,产物 `.build/sidecar/dist/opennexus-core``.build/sidecar/manifest.json`
- 新增显式打包测试 `cargo test --locked --features desktop --test core_bundle packaged_core_twenty -- --ignored`,调用实际可执行文件并在每次启动前校验完整文件清单。20 个独立临时数据目录、20 个不同会话代际、带鉴权和代际头的 HTTP 健康请求全部成功,逐次退出后端口关闭。测试耗时 95.64 秒,日志 `.build/core-packaged-cold-starts.log`。初版测试遗漏代际请求头导致拒绝,修正测试后通过。
- 该测试按要求先构建后显式运行,普通源码全目标测试会跳过此入口。Clippy `-D warnings` 通过。此证据来自当前 Windows 开发机,不能替代干净 VM、MSVC 签名安装包、两台真实设备或完整 A-01 验收。
## 增量:401 恢复与每作业持久尝试记录
- 协调器对可重放的同步轮次收到 401 时仅强制刷新一次;刷新仍校验设备身份且受凭据锁撤销。刷新失败或第二次 401 返回停止错误,403 不刷新。普通非幂等业务创建没有套用重放包装。
- 真实本地 HTTP 测试先在隔离数据库中提前过期 Access Token,确认读取经一次刷新恢复;删除测试会话后 Refresh 也被拒绝,不重新登录、不注册新设备。另注入连续 401 和 403,分别确认最多两次与一次操作调用。
- Workspace schema 10 保存每个上传作业的累计尝试次数与 running/failed/interrupted/succeeded 结果;普通取消通过析构记录中断,进程强杀则由重开修复。文件已确认而结果未记录时,恢复以已持久的 ack 为准。错误只保存限定机器码;待处理作业最多展示 20 项恢复记录。
- 20 次重开验证尝试累加且冻结的提交载荷不变;取消测试确认无需重启即显示 interrupted。真实 100 MiB 十次强杀后,重开查询准确显示 10 次尝试与 interrupted,最终继续上传、下载与摘要校验通过。测试过程使用独立临时 Vault 和服务账号。
- Rust desktop 全目标 53 项通过,之后新增取消测试单独通过;更新后的真实 HTTP 集成再跑通过。两个 ignored 入口分别是已在前轮显式运行的打包测试和父测试实际驱动的强杀辅助进程。前端 SyncSettings 5 项、两项目 TypeScript 检查及最终 Clippy `-D warnings` 通过。日志 `.build/job-recovery-rust-tests.log``.build/job-recovery-http-tests.log`;本增量无 Python 变更。
- 此增量不等于完整 S-02/S-03 故障矩阵,pull 各边界 20 次强杀、同目标 rename 与历史恢复等完整验收仍需推进。
## 增量:Rust 扩展签名与 ZIP 验证基础
- 新增 Rust Release v1 验签及有界 ZIP 检查,真实 Python canonical JSON/Ed25519 向量验证通过;逐个签名字段篡改、错误公钥/签名者、撤回和键撤销均拒绝,ZIP 摘要另行核对。
- ZIP 原始中央目录预检阻止映射覆盖隐藏重复项、本地头不一致和重叠数据。测试覆盖穿越、Windows 特殊路径、Unicode 大小写重名、文件/目录前缀、链接、加密和 CRC 损坏。Theme 的 5/10 MiB 与 100 条、其他包的 10/50 MiB 与 2048 条边界和超界通过。
- 新增锁定依赖 ed25519-dalek 2.2.0 与 unicode-casefold 0.2.0;复用已存在的 zip 8.6.0、Unicode normalization。声明 Rust 下限调整到 ZIP 库要求的 1.88,实际验证仍使用本机 GNU 1.98.1,尚无最低工具链或 MSVC 发布证据。
- Rust desktop 全目标 58 项通过(另两个既有显式/辅助入口 ignored),随后补充较新 Unicode 大小写映射,4 项包验证测试复跑通过,最终 Clippy `-D warnings` 通过。日志 `.build/extension-verification-rust-tests.log`。期间一次链接被仍在运行的测试 EXE 占用;确认原进程完成后,针对性测试重跑通过。
- 此批只验证包,不提取、不安装、不执行。清单身份/权限和 schema、在线撤回复核、单一安装库、迁移及事务尚未完成,extensions capability 维持 false,完整 D-0104 仍未通过。
## 增量:有界类型清单与发行一致性校验
- `verify_package` 串联签名、ZIP 全字节检查和清单解析,返回经过检查的摘要清单及声明内容。清单最多 1 MiB / 32 层 / 10000 节点 / 单文档;重复键、循环别名、文件包含、未知 schema_version 和非法 JSON 拒绝。YAML 解析关闭环境插值与文件包含特性,错误不回显正文。
- Theme 保持专用 theme_idSkill/Plugin 兼容 Runtime 实际包使用的 id 与专用类型 ID,双声明冲突拒绝。发现并修复 Community 服务此前会拒绝项目自带 id 清单的兼容问题;两端均使用 markdown-workbench/note-reviewer 实际文件验证。
- 版本与权限集合须匹配发行;人设/模板/MCP/模型基本结构和递归秘密字段校验已加入。此处尚不替代各 Runtime 完整配置 schema、运行许可与 OS 沙箱。
- 锁定 serde-saphyr 1.2.0 的 deserialize 特性与传递依赖,按其要求将声明 Rust 下限调整至 1.89;实际仍为 GNU 1.98.1,不作为最低工具链测试证据。
- Community 全量 15 项通过(两个既有弃用警告);Rust desktop 全目标 61 项通过(两个既有特殊入口 ignored)。随后核对 Theme 专用 ID,7 项扩展验证复跑与最终 Clippy `-D warnings` 通过。日志 `.build/extension-manifest-rust-tests.log`
- 安全解包写盘、在线来源/撤回复核、安装库迁移、依赖与配置升级事务、授权和运行生命周期仍须实现,完整 D-01–04 和整体生产化继续进行。
## 增量:Rust 持久扩展暂存库
- 新增独占应用目录的扩展暂存库 schema 1;只接收通过签名、ZIP、清单检查的发行。先 fsync 不可变 ZIP 对象,再在同一 SQLite 事务保存版本元数据和操作回执。来源/命名空间/包/版本组成不可变身份,签名内容改变不得原地替换。
- 同操作重放返回原回执,仍重新检查撤销标志和 ZIP 完整性;不同请求重用操作 ID 拒绝。数据库和分页列表仅声明 staged,不声明安装/启用,也不产生运行许可。暂不清理无引用对象,避免中断后删除恢复材料。
- 对象写入后、版本记录后、回执记录后、事务提交后,各注入错误并重开 20 轮,均恢复为一份版本及回执。另验证独占锁、不可变发行、撤销重放拒绝、对象损坏拒绝、数据库及 WAL/SHM/journal 预置硬链接拒绝且目标原文件不变。
- Rust desktop 全目标 64 项与 Clippy `-D warnings` 通过;日志 `.build/extension-store-rust-tests.log`。这些是受控错误注入,不能替代完整 D-03 的真实断电/磁盘满矩阵。安全解包、活动版本和配置切换、在线信任/撤回、旧库迁移及运行生命周期尚待接入。
- 同轮复查远端测试 Sync 的 `/ready` 返回 503 / DEPENDENCY_UNAVAILABLE,正继续定位;不视为服务器验收通过。
## 远端测试服务就绪复查
`http://yui.kronecker.cc:18080/health` 返回 200 / status=ok`/ready` 返回 503 / DEPENDENCY_UNAVAILABLE。SSH 域名地址与公开 AAAA 地址均在认证前关闭连接、未返回 banner,尚无法读取 Docker/数据库/对象存储诊断。未执行任何远端修改,也未判定为密码错误。已询问 SSH 入口是否改变;本地工程继续推进,不因这一单项暂停整体目标。证据 `.build/acceptance/sync-readiness-current.json`
## 增量:确定性依赖锁与兼容性预览
- 暂存库新增只读依赖预览,固定根发行,只使用同来源候选;无命名空间的键归属当前命名空间,显式 namespace/package 也必须来自同来源。较新版本优先,遇到菱形冲突会回溯选择满足全部约束的版本,结果按依赖先于使用者输出。
- 裸完整版本表示精确约束;范围采用明确的 Rust SemVer 语法,未知范围拒绝。应用 min/max、平台和架构不兼容拒绝;缺包、版本冲突、依赖环或预算超限不返回部分计划。
- 锁定结果绑定包身份、完整签名发行、ZIP、签名者、权限及目标应用/平台/架构。选中包重新从暂存对象读取并校验签名和清单;重开后摘要稳定,归档损坏会拒绝。尚无安装/停止实例的副作用。
- 预算为同源 4096 候选 / 64 MiB 元数据、200 解析包、10000 搜索展开与 4 MiB 预览编码。测试覆盖输入乱序、菱形回溯、环、缺包、精确版本、平台不兼容、来源/命名空间隔离、深图和过大预览。
- Rust desktop 全目标 69 项通过(两个既有特殊入口 ignored);其后补充预览编码上限,4 项依赖测试和最终 Clippy `-D warnings` 通过。日志 `.build/extension-dependencies-rust-tests.log`。依赖使用已锁定的 semver 1.0.28。
- 正式安装的在线撤回复核、权限确认、解包与包/配置原子切换、健康检查和回滚仍未完成,不能据此通过完整 D-03/D-04。
## 增量:目录句柄内安全解包
- 新增 extension_unpack,入口重新验证签名、ZIP 和类型清单,在应用私有 staging 根目录下创建随机 UUID 目录。子目录逐级以 nofollow 句柄打开,输出使用 create_new;ZIP 内路径不用于环境绝对路径写入。依赖锁定 cap-std / cap-fs-ext 4.0.3。
- 写入后重新遍历,核对精确文件集合、内容摘要和总展开大小;拒绝多余空目录、缺失/额外文件、符号链接、硬链接和 Windows reparse 文件。树摘要使用路径长度、路径、文件长度及文件内容组成的明确编码,独立于 ZIP 摘要和既有 Python package_digest,不可混用。
- 文件逐个 sync_all,Unix 同步目录项;失败目录保留隔离状态,不标记为当前安装。未验证 Windows 断电持久性,也未将静态链接测试等同于完整并发替换攻击防护。
- 17 项扩展模块回归和全目标 Clippy -D warnings 通过,日志 `.build/extension-unpack-tests.log`。新增实际 Windows junction 越界拒绝、硬链接替换拒绝、原文件不变、篡改/缺失/额外文件及空目录拒绝测试。
- 此模块尚未接入持久安装操作、在线撤回复核、权限审批、原子切换或健康检查;扩展执行能力仍关闭。远端 Sync ready=503 和 SSH 认证前断开问题也尚未解决,不宣称整体生产化验收完成。
## 增量:持久化解包准备与升级恢复
- ExtensionStore.prepare 接入已验证暂存包,要求调用者提供当前签名者和撤销状态;首次及重放均核对签名、归档、清单,重放还重新读取已准备目录的精确文件集合和摘要。数据库中的目录名只接受规范 UUID,不能提供任意路径。
- schema 2 新增 prepared_packages,记录每个不可变包的准备目录和树摘要。解包完成、记录写入、事务提交三个边界分别注入错误并重开 20 次,最终只有一份有效记录,重放结果稳定。提交前遗留的隔离目录暂不回收,避免误删恢复材料;这不是安装事务或真实断电验收。
- schema 1 升级前 VACUUM INTO 创建独立备份并同步。测试验证原暂存版本不变、备份可读且仍为 schema 1、重复打开不再备份;修复 Windows 只读文件句柄无法执行备份 sync_all 的问题。
- 19 项扩展回归通过,日志 `.build/extension-prepare-tests.log`。当前仍只产生准备结果,未开放扩展执行或自动授予权限;在线信任刷新、依赖集合安装、配置切换、健康检查及回滚继续待完成。
## 增量:Host 运行许可内容绑定
- 新增 extension_permitHMAC-SHA256 绑定来源、命名空间、包/版本、ZIP/展开/签名者摘要、入口、参数数组、环境声明、权限集、Vault、平台、策略版本及到期时间。BTree 容器提供确定性编码,令牌本身仅为认证码;未向 renderer 提供参数或环境声明。
- Authority 使用系统随机密钥,销毁时清零;到期边界、不同 Authority、全部失效后的旧令牌均拒绝。环境凭据使用 scope 声明,调用方不得向声明填入实际秘密。输入和编码大小有上限,入口穿越、错误环境名和 HTTP 社区来源拒绝。
- 测试逐字段改成另一份仍合法的声明,确认认证码不再匹配,避免把输入格式拒绝误认为绑定测试通过;另测到期、密钥轮换、路径及体积边界。21 项扩展回归与全目标 Clippy -D warnings 通过,日志 `.build/extension-permit-tests.log`
- 这是许可认证原语,尚未接入安装确认、在线信任、锁定事件、运行沙箱或 broker。它不证明用户已同意,也不授予执行能力;完整 C/D 验收仍未通过。
## 增量:包与配置活动指针的组事务
- extension_transaction 在单一 SQLite 事务中保存旧状态、整组新包/配置指针和 checking 日志;期望 revision 不匹配、重复 slot、已有待检查事务或操作 ID 被不同请求重用均拒绝。健康结果提交后才清除 pending;失败整体恢复旧元组,首次安装失败移除新指针。
- 暂存库 schema 3 接入,升级 schema 1/2 前保留对应备份。switch_prepared 重新检查签名归档和准备目录,并按 Vault、来源、命名空间和包 ID 推导 slot,拒绝跨 Vault 指针。打开库时未完成 checking 自动回滚,不恢复任何执行许可。
- 三个切换边界分别注入错误并重开 20 次,两个包与各自配置始终匹配;另测 CAS、busy、操作重放、失败首次安装、健康成功后重开保留、目录损坏拒绝及 Vault 绑定。24 项扩展回归和全目标 Clippy -D warnings 通过。
- 这仍是安装事务的存储层:配置只要求对象,完整类型 schema/秘密剥离、依赖计划和用户确认复核、在线撤回、停旧实例、沙箱内迁移、真实健康探测及 UI 尚待编排。不能把注入错误重开测试当成 D-03 断电/磁盘满完整矩阵,也不能开启 extensions capability。
- 本轮 Rust desktop 全量回归 78 项通过,2 个既有特殊入口 ignored;实际 Sync 子进程中断恢复由父测试执行通过。全量日志 `.build/extension-transaction-rust-full.log`
## 增量:切换前的签名配置 schema 校验
- switch_prepared 从重新验证的签名清单读取 configuration_schema,配置不能自带替代 schema。未声明时只接受空对象;声明使用 Draft 2020-12、离线 jsonschema 0.55.0(关闭默认网络/文件解析功能),启用格式检查和线性正则引擎。
- schema 与配置各限 64 KiB、4096 节点、24 层;当前拒绝所有引用,包括本地引用,避免 Host 执行递归 schema。高级正则、其他 schema draft 不接受;此限制应在安装 UI 中明确展示,尚无完整配置编辑 UI。
- 配置递归拒绝常用秘密字段;writeOnly / x-opennexus-secret 声明禁止持久化对应值,包括条件和组合分支,不能通过 anyOf 的另一个分支绕过。此规则对条件分支采取保守拒绝;秘密应由后续凭据 broker 提供,任意普通字符串不能被自动识别为秘密。
- 测试覆盖嵌套类型、范围、未知属性、错误 schema、引用、深度/体积、秘密声明和组合绕过;安装入口拒绝秘密配置后事务表保持为空。26 项扩展回归通过,日志 `.build/extension-config-tests.log`
- 这不替代各扩展类型的完整运行配置契约、用户确认、在线信任与沙箱,也没有完成配置迁移/导入秘密的完整流程。整体生产化继续未完成。
## 增量:社区在线信任复核入口
- 新增 HTTPS Community 客户端,复核 source_id、原固定公钥/命名空间、键撤销、发行撤回及完整发行内容。重复版本、键替换、未知响应、非 200(含重定向)、离线均拒绝;不接受刷新时自动信任新键。每请求 15 秒、JSON 4 MiB、集合 4096 项上限。
- Checked 凭据由客户端内部构造,绑定规范来源、完整发行摘要和公钥摘要,单调时钟 30 秒过期;不序列化持久保存。switch_online 限同源组,所有准备目录与配置检查后、写入事务前再次复核时效。
- 受控真实 HTTP socket 测试覆盖正常、撤销、键替换、撤回、内容变化、重复版本、503、302 和过期;HTTP 仅测试内部替换 URL,公开构造器只允许 HTTPS。27 项扩展回归与 Clippy 全目标检查通过,日志 `.build/extension-trust-tests.log`
- 尚未取得真实 HTTPS Community 部署验收;固定键来源仍要求 Host 信任设置提供,尚无设置 UI/轮换确认和运行期撤销停止循环。底层 switch_prepared 仍是未接 IPC 的内部安装存储原语,正式入口应调用 switch_online;离线本地包需独立信任流程。不能据此开启扩展执行或通过 D-04。
## 增量:Host 持久来源公钥确认
- 安装库 schema 4 新增来源/命名空间/键 ID 信任记录,包含来源身份、固定公钥和启用状态。升级前保留旧 schema 备份;旧暂存发行不会自动变成受信来源。
- confirm_trust 绑定完整候选摘要和原 revision,首次确认、密钥轮换或禁用均需匹配的确认数据;并发改变后的旧确认拒绝。同一规范来源 URL 不允许混入第二个 source_id。该 API 尚未接入用户 UI,传入摘要本身不证明已获得用户同意,未来只允许受控主窗口确认流程调用。
- switch_online 不再接受外部 source_id 参数,使用已确认且启用的 Host 信任设置,要求公钥与暂存签名者相同后才联网。测试验证未知来源、禁用和不匹配公钥均在写入安装日志前拒绝;不会因暂存包验签通过而自动信任其签名者。
- 29 项扩展回归与全目标 Clippy -D warnings 通过,日志 `.build/extension-trust-settings-tests.log`。覆盖重开恢复、候选确认不匹配、轮换 CAS、禁用持久化、来源身份冲突和在线入口拒绝。
- 来源设置 UI、确认路由、撤销状态持久传播、运行期停用、迁移及真实安装编排仍未完成,整体生产化继续未完成。
## 增量:撤销和撤回的持久拒绝
- Community 复核区分 EXTENSION_KEY_REVOKED 与 EXTENSION_RELEASE_WITHDRAWN;先匹配固定公钥/身份或完整发行内容,再接受对应撤销状态,避免把另一份元数据的撤回误记到当前包。
- schema 5 保存持久拒绝记录。键撤销绑定来源、命名空间、键 ID 和公钥摘要;发行撤回绑定来源、命名空间、包与版本。在线入口收到确切撤销后写入,网络失败不会写入;普通信任确认不会清除拒绝记录。
- 在线及底层准备切换均检查持久拒绝。重启后仍拒绝,发行撤回不影响其他版本,旧键撤销不自动禁止另一个显式确认的新公钥,但新公钥也不能复活已撤回版本。
- 30 项扩展回归与全目标 Clippy -D warnings 通过,日志 `.build/extension-revocation-tests.log`。测试覆盖持久性、信任确认后仍拒绝、不同版本/来源/公钥范围和网络失败不污染拒绝记录。
- 尚未接入运行中实例和工具注册表的撤销轮询/停止,不能据此声明 D-04 的 5 秒撤销目标通过。恢复旧指针仍可保留数据,但不授予运行许可。
## 增量:完整安装预览与持久确认计划
- installation_preview 组合确定性依赖锁、全部包权限、配置、准备目录/展开摘要、信任设置摘要、目标 Vault/应用/平台/架构及当前活动 revision。未信任、已撤销、错误配置、非计划包配置或待健康检查事务均拒绝,预览不切换活动指针或授予许可。
- install_confirmed 首次执行重新生成预览并比较确认摘要,再进入在线复核。schema 6 保存操作 ID 对应的请求摘要、确认摘要和冻结切换组,网络或进程中断重试沿用原组;改变请求/确认并重用 ID 拒绝。重试仍经过来源/撤销/归档/配置检查和活动 revision CAS。
- 31 项扩展回归与全目标 Clippy -D warnings 通过,日志 `.build/extension-install-preview-tests.log`。新增预览重开摘要稳定、应用版本/活动状态变化使预览失效、错误确认在联网前失败、未知配置拒绝,以及确认计划重开重放不重新选择内容的测试。
- 真实主窗口确认 UI、Host 注入的应用/平台信息、旧实例停机、沙箱迁移和健康探测仍待接入。确认摘要 API 本身不证明用户授权;本轮没有执行第三方包或宣称整体生产化完成。
## 增量:受控桌面信任确认与预览命令
- Host 启动时打开应用数据目录 extensions-host 安装库并持有独占锁;新增 extension_trust_review / extension_trust_confirm / extension_install_preview 命令,Tauri ACL 仅授予本地主窗口,命令额外核对 main 标签,未增加远程来源权限。
- 信任复核把完整候选、原 revision 和摘要保存在 Host 内存,返回随机 review_id。最多 64 个待确认项、两分钟单调时钟有效期;确认仅接收 ID 和摘要,不能替换候选。成功消耗凭据,过期/重用/不匹配及并发设置改变拒绝。
- 安装预览由 Host 注入应用版本、OS 与架构,renderer 只提交根包、当前 Vault 和配置;后台阻塞任务中保持 Vault 绑定稳定并调用完整预览。尚未开放实际安装执行命令。
- 桌面二进制 5 项测试和全目标 Clippy -D warnings 通过,日志 `.build/extension-commands-tests.log`。新增确认凭据生命周期与并发冲突测试;ACL 文件及生成权限项已更新。
- 前端确认对话框、桌面包下载/暂存入口、安装执行编排、沙箱及真实 UI 验收尚待完成;extensions capability 仍关闭。本轮不宣称生产化或 D-04 完成。
## 增量:社区来源确认界面接入 Host
- 桌面社区检查来源后请求 Host 复核,对话框展示 source_id、候选公钥、原有设置和确认摘要;只有点击确认才调用 Host 确认命令,成功后更新本地目录设置。启用/停用也经同一确认流程更新 Host,旧本地来源不自动迁入信任库。
- 新增 extensionTrustService,规范 HTTPS 来源、公钥解码和数量限制;确认只传 Host 签发的 review_id 与摘要。两分钟过期或并发冲突提示重新检查;多键确认是逐键调用,部分失败可能已有部分键完成确认,界面不声称整组成功,需重新检查后处理。
- 来源发现保留服务端 source_id,Web 开发保留本地来源流程。对话框中的错误可见,忙碌时禁止重复确认。
- 前端全量 99 文件 / 521 项通过,两套 TypeScript 项目检查通过;日志 `.build/extension-trust-ui-tests.log`。新增服务参数/非法输入测试与 Vue 组件确认前无写入、Host 拒绝后不保存测试。测试使用 Host mock,不等同于真实桌面 UI 端到端验收。
- 桌面包下载暂存、安装确认 UI 与执行编排、沙箱、真实双端及部署验收仍未完成;整体生产化目标继续进行。
## 增量:桌面 Host 下载和验证暂存
- 主窗口新增 extension_stage 命令。桌面社区按钮提交签名发行元数据给 Host,剥离 release_id/withdrawn/download_path 展示字段,Host 使用固定来源设置自行复核在线发行并取得归档地址;renderer 不再调用浏览器下载及旧 Python/主题安装路径。
- 归档地址由复核的发行 ID 构造,并要求服务端 download_path 精确匹配。下载禁止重定向、限制主题 5 MiB/其他 10 MiB,并按签名声明大小执行流式上限;下载后重新验签、检查 ZIP 与类型清单,并核对信任时效,再写入不可变暂存对象及操作回执。
- Host 下载在后台阻塞任务中执行,持有安装库锁保持串行。当前 UI 取消不取消已派发的原生暂存任务,任务最多受请求超时约束且只产生暂存;后续需接入统一取消/进度流程。
- 32 项扩展回归、Clippy 全目标、6 项前端针对性测试和两套 TypeScript 项目检查通过。Rust 日志 `.build/extension-download-tests.log`;真实 socket 覆盖归档内容错误、无 Content-Length 超长流、302 拒绝和正确 Python 签名归档。
- 桌面文案明确“已校验并暂存,尚未安装或启用”。缺失依赖自动获取、完整安装 UI、停止实例/健康探测、沙箱和真实 HTTPS 部署验收仍待完成,不视为整体生产化完成。
## 增量:原生暂存取消与提交状态查询
- 暂存采用独立 Host Requests 预留/领取/取消流程,60 秒总期限,派发前取消不会运行任务;等待安装库锁时也检查取消。网络 future 由 Lease 驱动取消,同步暂存各持久边界复查取消状态。
- 主窗口新增 prepare/cancel/status 命令及 ACL。客户端在预留后注册取消,覆盖预留响应与派发之间的竞争;取消后查询持久操作回执,若提交先完成则返回“取消前已完成暂存”。同一页面未开始其他任务时保留这条结果。
- 回执查询不把已提交状态伪装成取消回滚。提交前取消可能留下不可见的孤立归档对象,暂存版本/回执事务回滚;提交后取消保留原回执。未增加对象 GC 或跨重启任务列表。
- 33 项扩展回归、4 项请求生命周期测试、7 项前端针对性测试、全目标 Clippy 和两套 TypeScript 项目检查通过;日志 `.build/extension-cancel-tests.log`。请求生命周期包含真实 socket 取消关闭测试,新增对象写入后/回执记录后/提交后的取消回执区分。
- 完整任务进度列表、跨重启 UI 恢复、安装执行编排与沙箱仍未完成;整体目标继续进行。
## 增量:桌面暂存列表和安装预览界面
- 新增仅本地主窗口可用的 extension_staged 分页命令,界面从 Host 持久安装库加载暂存包,每页 20 项;暂存完成后刷新,重启不依赖 renderer 缓存重建包列表。
- DesktopPackages 对话框允许输入根包配置,调用 Host 完整预览,展示依赖拓扑顺序、请求权限和检查后的配置。当前 Vault、请求代次和选中根包共同约束返回结果,切换 Vault 关闭预览并丢弃迟到响应。
- 5 项前端针对性测试、两套 TypeScript 项目检查和 Rust 全目标 Clippy -D warnings 通过。新增组件测试验证使用 Host 列表、精确 Vault/配置参数、只发预览命令,以及切库后不显示旧权限结果。
- 页面明确安装执行尚未开放;依赖包配置编辑、自动取得缺失依赖、正式确认执行、沙箱与真实端到端验收仍未完成。整体生产化目标继续进行。
## 修复:多公钥来源的原子确认
- 新增 extension_trust_confirm_group,前端一次提交整组 Host 复核凭据。Host 先核对数量、重复凭据、过期与摘要,再由安装库 savepoint 一次确认同来源全部键;不同来源/来源身份或重复键拒绝。
- 任一后续键发生 revision 冲突时,前面已执行的更新全部回滚;确认凭据只在整组成功后一起消耗。此变更替代此前文档中逐键确认可能部分成功的流程。
- 34 项扩展回归、2 项 Host 确认测试、3 项前端针对性测试、全目标 Clippy 和两套 TypeScript 项目检查通过。日志 `.build/extension-trust-group-tests.log`。验证后续键冲突后重开仍无部分更新,以及失败保留有效凭据、成功全部消耗。
- 真实桌面确认链路端到端、安装执行、沙箱及总体生产化验收仍未完成。
## 增量:Windows Job Object 资源容器
- 新增 extension_job,创建无可继承句柄的 Job,设置组提交内存 512 MiB、活动进程默认 16、关闭最后句柄时杀死进程;不启用 breakaway。CPU 使用 hard cap,按系统活动逻辑处理器数向下取整分配至单核等效份额;任一设置失败不返回可用容器。
- assign_suspended 明确要求调用方持有尚未恢复的 CREATE_SUSPENDED 进程,出错须终止它,全部隔离/许可检查后才能 ResumeThread。该模块只有资源约束,尚未接入第三方运行入口,也不具备文件、网络或身份隔离。
- 4 项真实 Windows 进程测试与全目标 Clippy -D warnings 通过,日志 `.build/extension-job-tests.log`。三个 ignored 条目是由父测试实际启动的辅助入口。验证进程配额为 1 时第二进程被拒绝且从未恢复、关闭 Job 后进程退出、受管理后代计数归零、显式终止,以及正常 32 MiB 分配成功/600 MiB 分配失败。
- 测试初次使用固定等待观察进程计数失败,改为最多 5 秒等待计数收敛后通过;不将单次固定延时当作清理证明。生产参数测试读取 OS 返回的内存、进程和 CPU 配置,但尚未完成长时间 CPU 压力、10 秒超限终止及 scratch 配额测试。
- API 依据 Microsoft Job Objects 与 JOBOBJECT_CPU_RATE_CONTROL_INFORMATION 文档: https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects 、 https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_cpu_rate_control_information 。AppContainer、文件/网络 broker、恶意程序矩阵及实际扩展调用仍待完成,不能据此通过 C 项或开启 extensions capability。
## 增量:AppContainer 配置所有权与原生身份验证
- 新增 extension_container::Profile,为每个实例创建随机 OpenNexus.sandbox 名称、无声明能力的 AppContainer 配置,校验 SID 并提供 OS 返回的配置目录。同名已存在时拒绝,不接管或删除旧配置;显式 remove 报告清理失败,Drop 尝试最终清理并释放 SID。
- 真实 Windows 测试创建两个配置验证 SID 不同、重复名称失败不破坏原配置、显式删除后可重新创建。另用 SECURITY_CAPABILITIES 创建挂起的系统进程,先加入 Job,再读取 TokenIsAppContainer、TokenAppContainerSid 与 TokenCapabilities,确认容器身份、精确 SID 和零能力;没有恢复命令解释器执行。
- 空环境及仅 SystemRoot 的启动尝试返回 Windows 203;使用明确的 SystemRoot 和指向容器自身目录的 LOCALAPPDATA/TEMP/TMP 后通过。此处是测试启动环境,不是完整生产环境/参数构造器。
- 两项 AppContainer 原生测试与全目标 Clippy -D warnings 通过,日志 `.build/extension-container-tests.log`。API 依据 Microsoft CreateAppContainerProfile / DeleteAppContainerProfile / Launch an AppContainer 文档。所有测试创建的配置通过所属对象清理,未借用既有用户配置。
- 生产启动器、包只读 ACL、独立 scratch 配额、原始网络拒绝实测、文件与网络 broker、崩溃后孤立配置清理以及恶意程序矩阵仍待完成。当前不声明完整沙箱,也未开启 extensions capability。
## 增量:按句柄授予 AppContainer 包只读执行权限
- Profile 新增 grant_package_read_execute,只对 Host 已打开并验证的单个文件或目录增加该实例 SID 的读取/执行 ACE,不启用子项继承。通过 GetSecurityInfo / SetEntriesInAclW / SetSecurityInfo 操作同一对象句柄,分配的安全描述符与 ACL 由 RAII 释放;拒绝重解析对象、硬链接、空 DACL 和权限不足的句柄。调用方仍须按句柄验证整个包并在启动期间持有这些句柄,不接受 renderer 任意路径。
- 关闭 ACL 继承是为了避免 OS 自动向未检查子项传播授权;每个包目录和文件必须逐项验证和授权。该原语只增加权限,不会清除预先存在的宽泛 ACL,也尚未接入生产启动器,因此不构成对恶意并发替换或任意现有目录的完整安全证明。
- 4 项真实 Windows AppContainer 测试通过:指定文件授权前无法读取,仅授权目录仍不能读取子文件,文件单独授权后读取成功;相邻未授权文件和另一实例仍被拒绝;新建文件、覆盖包文件失败,原内容保持不变;硬链接与只读句柄不能用于授权。每次试验均先以零能力挂起创建,检查精确容器 SID,加入 Job 后再执行受控测试命令。
- 首轮使用 type 输出到 nul 的测试返回非零,改用 set /p 从文件重定向读取后验证成功;没有改变生产权限掩码来迁就该测试。系统 cmd.exe 仅用于这些固定测试命令,生产扩展入口仍禁止 shell 拼接。
- API 依据 [Microsoft SetSecurityInfo 文档](https://learn.microsoft.com/en-us/windows/win32/api/aclapi/nf-aclapi-setsecurityinfo)。当前未完成生产启动器、包树授权编排、scratch 配额、网络/文件 broker 和恶意程序矩阵;extensions capability 仍关闭,整体生产化目标继续进行。
- 本轮完整回归:cargo test --features desktop 共 98 项通过、5 项 ignored;其中 4 项为父测试实际驱动的 Job/Sync 辅助进程入口,另一项是需要单独执行的打包 Core 20 次冷启动,本轮没有重跑该项。真实 Core/Stronghold、笔记桥接、凭据所有权和 Sync 中断恢复集成全部通过。前端全量 101 个文件、525 项通过;Rust 全目标 Clippy -D warnings 通过。日志分别为 `.build/host-production-full-tests.log``.build/frontend-production-full-tests.log``.build/host-production-clippy.log`。全库 diff 检查提示用户 Vault 文件已有尾部空行,未修改用户内容;本次代码与文档单独检查通过。
## 增量:AppContainer 环回网络行为验收夹具
- 新增独立原生 Rust 网络探针,由测试编译到独立临时包,按句柄授予容器读取执行权限。直接以绝对入口创建挂起进程,检查容器身份、精确 SID、零能力并加入 Job 后执行;不经 shell。探针仅属于测试夹具,不参与生产扩展启动。
- 在 Windows 11 24H210.0.26100.4061)、Rust 1.98.1 x86_64-pc-windows-gnu 上,分别对 IPv4 127.0.0.1 和 IPv6 ::1 的动态 TCP/UDP 监听端验证。相同探针在容器外、隔离尝试前后均成功访问;容器内 TCP 在 2 秒连接期限内超时,未被监听端接受;UDP send_to 返回成功,但监听端在进程结束后额外观察 200 ms 仍无数据。测试不把 UDP send 成功等同于报文送达。
- 初次要求 Winsock 10013 的断言失败;进一步探测明确为 TCP 超时,并分别保留超时、访问拒绝、其他错误退出码。当前断言检查允许的网络失败类型和监听端无接收,并排除加载失败、参数错误、控制端不可用。Microsoft 文档说明环回隔离可能表现为丢包:[Windows 防火墙 UWP 连接排查](https://learn.microsoft.com/zh-cn/windows/security/operating-system-security/network-security/windows-firewall/troubleshooting-uwp-firewall)。此次未捕获 WFP 事件,不能将超时唯一归因到某条过滤规则。
- 全部 5 项 AppContainer 测试和全目标 Clippy -D warnings 通过,日志 `.build/extension-container-network-tests.log``.build/extension-container-network-clippy.log`。测试没有增加 loopback exemption 或修改系统防火墙设置。
- 这只是当前机器上 TCP/UDP 环回行为的有限时间观察,不覆盖公网、私网实际服务、DNS、原始 socket、跨机器或最低 OS 版本,也不能据此通过完整 C-01/C-03。生产启动器、受限 broker、scratch 配额等仍待完成,整体目标继续进行。
## 增量:原生启动参数与隔离环境构造
- 新增 Windows LaunchData,为明确的绝对 .exe 入口编码 CRT 参数数组,正确处理空参数、空格、引号前反斜杠和末尾反斜杠;拒绝相对入口、非 .exe、路径引号/NUL、参数 NUL、数量与长度超限。入口仍须由调用方校验并持有,构造器本身不验证包、许可或沙箱能力,也不允许据此执行 shell 配置。
- 环境块只使用 Host 提供的 SystemRoot、容器 LOCALAPPDATA、scratch TEMP/TMP 和明确声明/解析的变量,不读取父环境。变量名限 ASCII、大小写归一排序,拒绝重复和覆盖保留变量、非法名称与 NUL。原生路径使用 UTF-16 保留未配对代理项,避免 display() 有损转换。环境块含双 NUL,并要求调用方使用 CREATE_UNICODE_ENVIRONMENT。
- 参数与环境均限制在 32767 个 UTF-16 单元内,预分配容量并在加入内容前检查界限,避免构造过程因扩容留下额外值副本;Drop 清零两个缓冲区。此清理不替代调用方对已解析凭据的生命周期和清理责任。
- 真实 AppContainer 探针使用该构造器启动,比较完整 argv 和完整环境变量集合:空串、空格、中文/emoji、引号/反斜杠、换行及 &|%PATH% 均原样收到,环境恰好为四个基础变量加 CUSTOM,未继承 PATH 等 Host 环境。测试也保留容器 SID/零能力/先挂起后入 Job 的核对。
- 45 项扩展回归通过、3 项 Job 辅助入口 ignored(由父测试实际调用),全目标 Clippy -D warnings 通过。日志 `.build/extension-launch-regression-tests.log``.build/extension-launch-clippy.log`。API 依据 [Microsoft CRT 参数解析](https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments?view=msvc-170) 和 [CreateProcessW](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw)。尚未覆盖所有第三方运行时的自定义命令行解析。
- 当前仍未开放第三方执行:正式启动器的许可/包句柄绑定、生产环境凭据解析、scratch 限额、broker 与完整端到端验收继续实施,不能据本轮参数测试认定生产化完成。
## 增量:Windows 挂起进程所有权与恢复边界
- 新增 extension_process:使用零能力 SECURITY_CAPABILITIES、明确环境、容器自身工作目录、不可继承句柄和隐藏窗口创建挂起进程,先加入默认资源 Job,再核验 TokenIsAppContainer、精确 SID 和零 TokenCapabilities。属性列表、原生句柄及 Job 均有所有权清理;创建、入 Job 或身份核验失败不返回可恢复进程。
- Suspended 与 Running 分开,resume 消耗挂起对象,要求 ResumeThread 返回预期挂起计数 1;不能经同一对象重复恢复。Profile 借用延续到进程对象释放,防止 Host 提前删除配置。Running 提供最多 60 秒的有界等待和整组主动终止;对象释放也终止 Job,关闭句柄并等待根进程退出。
- resume 是带明确安全前置条件的底层接口,尚不替代执行许可、包/入口句柄、在线信任、Vault、broker 和完整资源策略核验。上层未满足全部条件时仍必须拒绝运行。未新增 renderer 启动命令,也未开启 extensions capability。
- 原生参数/环境探针、IPv4/IPv6 环回探针已切换到此正式进程模块执行,相关行为回归通过。新增实际 Windows 测试验证不匹配 SID 拒绝、丢弃未恢复进程后句柄进入终止状态、入口不存在与损坏终止符失败不消耗 Profile。运行中的等待探针验证零时限返回未完成、超过 60 秒的等待请求拒绝、主动终止后五秒内观察到退出。
- 47 项扩展回归通过,3 项 ignored 为由父测试驱动的 Job 辅助入口;全目标 Clippy -D warnings 通过。日志 `.build/extension-process-regression-tests.log``.build/extension-process-clippy.log`
- 该模块只收拢已验证的原生生命周期,不构成完整生产扩展启动器。许可和包句柄原子绑定、撤销停止、生产 broker、scratch 配额、工具总期限及崩溃后的配置清理仍未完成,整体生产化继续实施。
## 增量:独立于调用方轮询的单工具期限守卫
- 新增 ToolDeadline,生产预算固定 60 秒,按单次工具调用启动,不限制常驻 MCP 服务总寿命。Running::start_tool_call 绑定该实例的 Job,创建独立计时线程;线程创建或句柄复制失败返回明确错误,调用方必须在派发工具请求前成功启动守卫。
- 期限使用单调时钟和条件变量。超时独立终止整个实例 Job,不依赖调用方继续轮询;完成只能在期限到达前撤销计时,完成操作不能在期限已过、计时线程尚未调度时绕过超时。终止失败、计时线程异常与普通超时分别返回稳定错误码。
- finish 正常完成后保留常驻进程;cancel 主动终止实例;守卫未 finish 就被释放也终止实例,覆盖调用 future 取消或异常退出,避免留下无期限工具调用。释放会唤醒并回收计时线程,正常完成无需等待满 60 秒。
- 真实 AppContainer 等待探针验证:正常完成守卫后进程仍活着;使用测试内部 100 ms 期限时,在没有 check/finish 轮询驱动的情况下进程退出,随后 finish 明确返回超时;显式取消和未完成释放均在 5 秒内观察到进程退出。生产公开 API 不接受延长期限参数。本轮没有执行完整 60 秒墙钟超限、计时线程故障注入或高并发调用压力测试,不能据此独立通过 C-04。
- 48 项扩展回归通过、3 项 Job 辅助入口 ignored(由父测试执行),全目标 Clippy -D warnings 通过。日志 `.build/extension-deadline-tests.log``.build/extension-deadline-clippy.log`
- 守卫仍需接到实际 MCP/扩展调用派发与结束路径;正式许可/包句柄绑定、broker、scratch 配额及完整验收尚未完成,整体生产化目标继续进行。
## 验收增量:完整 60 秒工具预算、进程树清理与 Host 保存
- 新增长时显式验收测试 real_sixty_second_tool_deadline_kills_tree_and_host_can_save。测试探针在真实 AppContainer 内创建一个同受 Job 管理的子进程,两个进程自然等待均为 120 秒,避免与 60 秒预算自然退出混淆;先核对活动进程数为 2,再等待生产 start_tool_call 固定 60 秒预算。
- 本次实际执行通过:计时开始 60.0048499 秒后 Job 活动进程数为 0,探针没有以自然结束码退出,finish 返回 EXTENSION_TOOL_DEADLINE_EXCEEDED。等待期间不通过 deadline.check/finish 驱动超时,终止由独立守卫完成。
- 同一 Host 测试进程在工具运行期间使用正式 Workspace.write 保存笔记,清理后以 expected_hash 再次写入,关闭后重开验证内容一致。此证据覆盖 Host 库保存路径,尚不等于打包桌面 UI 端到端保存验收。
- 长时测试以 --ignored --exact 显式执行,1 项通过;常规 AppContainer 5 项回归通过,长时条目在常规运行中保留 ignored 标记避免每次都额外等待一分钟。全目标 Clippy -D warnings 通过。日志 `.build/extension-deadline-sixty-seconds.log``.build/extension-deadline-container-regression.log``.build/extension-deadline-acceptance-clippy.log`。这补足上一条记录中未执行完整 60 秒和容器子树验证的缺口,不覆盖计时线程故障注入或高并发压力。
- 远端只读复查:HTTP /health 200、/ready 503SSH 22 连接仍在认证前返回空 banner;未修改远端配置,仍需要恢复就绪依赖与 SSH 可用入口。
- C-04 的 CPU 持续超限、scratch 配额、broker 限流及完整桌面证据仍未齐备,不能将本测试扩大为 C-04 全项通过。整体生产化目标继续进行。
## 增量:校验后持续持有 Windows 包对象句柄
- 新增 PinnedPackage,从 Host 已验证的目录 capability 和 Inventory 出发,逐级以 nofollow、FILE_SHARE_READ 和读取/ACL 权限打开根目录、全部父目录及包文件,保留这些句柄到实例结束。先持有全部现有对象,再复用完整树校验核对文件集合、摘要、总大小、硬链接与重解析限制,并匹配预期展开树摘要;任一步失败释放整组句柄。
- 该对象提供按持有句柄授予实例只读执行权限;不接受 renderer 任意路径,不在授权时重新通过字符串查找文件。数量、路径长度、目录数和展开体积继续有界。实际容器探针已通过该对象持有包后启动,参数/环境、网络行为、取消及短期限回归通过。
- 两项实际 Windows 句柄测试验证持有期间写入、删除、文件重命名和子目录重命名被拒绝;已存在写入句柄时锁定失败;错误树摘要和指向包外的硬链接拒绝;失败或释放对象后不残留写入锁。授权后文件内容保持一致。
- 50 项扩展回归通过,4 项 ignored 中三个是父测试实际调用的 Job 辅助入口,另一个是上一轮已显式通过的 60 秒长时验收,本轮未重跑该长时项。全目标 Clippy -D warnings 通过。日志 `.build/extension-pinned-regression-tests.log``.build/extension-pinned-clippy.log`
- 此原语固定已有包对象,不是只读文件系统挂载:包根目录上层路径绑定、并发新增未知文件、已有可写映射等场景仍未形成完整证明;不据此通过整个 C-02。正式启动器还需将许可、精确入口、完整包句柄和策略检查连接起来,extensions capability 继续关闭,整体生产化继续实施。
## 增量:原生入口卷路径、祖先句柄与进程生命周期绑定
- PinnedPackage 新增 bind_entry,仅允许已验证清单中的入口。通过 GetFinalPathNameByHandleW 从持有文件句柄取得卷 GUID 路径,逐级持有卷根至入口的对象句柄,拒绝重解析对象并阻止祖先目录删除共享;最后用卷序列号和文件索引核对重新打开的入口与原持有文件身份一致。
- BoundEntry 保留全部祖先句柄并借用完整 PinnedPackage。Suspended::create_bound 将此守卫借用延续到进程结束,使该创建路径不能在进程仍存活时释放入口或包句柄。挂起创建失败仍按既有所有权规则清理,不产生可恢复进程。
- 无法取得卷 GUID、不是本地卷格式、路径过长或超过 256 个路径分量时明确拒绝,不退回 UNC、驱动器字母搜索或普通子进程。原有低层 create 仍供受控探针等调用使用,正式包运行编排应使用 create_bound 并完成其余许可与策略检查。
- 实际 Windows 测试确认绑定路径为卷 GUID 路径、内容对应已持有文件、缺失/越界入口拒绝、父目录重命名失败;全部所有者释放后重命名成功。真实 AppContainer 原生参数/环境探针通过 create_bound 启动成功,网络/取消/短期限探针也使用持续持有的绑定路径运行。
- 51 项扩展回归通过,4 项 ignored 为三个由父测试实际驱动的 Job 辅助入口及需显式执行的 60 秒验收,本轮未重跑长时项。Clippy 首次指出冗余 Ok/?,修正后全目标 -D warnings 通过。日志 `.build/extension-entry-binding-tests.log``.build/extension-entry-binding-clippy.log`。API 依据 [Microsoft GetFinalPathNameByHandleW](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew)。
- 这补上了普通祖先路径替换的绑定原语与实测,仍未完成并发新增未知文件、已有可写映射、完整攻击矩阵、许可原子核验或所有目标系统验证,不能据此认定 C-02 或整体生产化完成。
## 增量:从执行许可构造参数、环境及包域凭据
- Claims 增加 Plugin/MCP 执行类型并纳入 HMAC 摘要,防止类型切换后沿用原许可。现有逐字段篡改测试覆盖该字段;许可仍为 Host 内存态能力,未增加旧许可兼容或 renderer 签发入口。
- 新增 extension_launch_authorization::Context::build,先核验许可有效期/HMAC、Host 当前 Vault/策略/平台,以及 BoundEntry 相对入口与展开树摘要,再从已签发声明构造参数和环境,不接受独立的替换参数或环境值。
- CredentialScope 的值解释为包域内不透明凭据引用。凭据归属由 HTTPS 来源、命名空间、包 ID 的带长度摘要派生,再按已绑定执行类型进入 Plugin 或 MCP 域;不接受调用者另报凭据域,也不回退 Provider。版本未加入凭据归属摘要,保留同包升级后的引用稳定性;新执行仍须独立完成信任和权限确认。
- 环境秘密通过现有 Stronghold broker 解密,拒绝缺失、锁定、无效引用和非 UTF-8 值;解析前后核对锁定代次。临时环境值由清理所有者清零,原始解密字节及最终 UTF-16 启动缓冲继续使用各自清理机制;错误只返回稳定代码,不包含值。
- 实际 Stronghold 测试验证 Provider 同名凭据不可见、正确 MCP 包域可用、重新签发后改变类型/来源/命名空间/包 ID 仍不能读取原凭据,以及入口/树/Vault/策略不匹配、参数篡改、过期、锁定和编码错误拒绝。真实 AppContainer 原生探针通过该准备链取得虚构测试凭据后启动,完整 argv/环境核对通过,未使用任何用户真实秘密。
- 52 项扩展回归通过,4 项 ignored 为三个由父测试驱动的 Job 辅助入口和单独执行的 60 秒验收;全目标 Clippy -D warnings 通过。日志 `.build/extension-launch-authorization-tests.log``.build/extension-launch-authorization-clippy.log`
- 该组件只完成准备阶段,不是可直接恢复执行的授权租约;调用方仍须在 resume 前复核在线信任、活动安装身份、许可、Vault 和锁定代次,并完成运行中撤销/停止、broker 和完整资源限制。目前未开放第三方执行,整体生产化继续进行。