Files
ycode/docs/沙盒原生写回事务-2026-10-18.md

83 lines
8.2 KiB
Markdown
Raw Permalink 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.
# 沙盒原生写回事务(2026-10-18)
> 后续增量:0.6.0 已接入[长期会话草稿](沙盒长期工作区接入-2026-10-18.md),提交继续复用本文 v3 原生宿主事务。下方 0.5.0 测试和“下一阶段”保留为当时记录;长期草稿的已实现子集及剩余限制见新文档。
## 交付范围
组件升级为 0.5.0 / protocol 1。默认 `write_file` / `edit_file`、命令产物提交、失败补偿和显式事务恢复均使用自有原生文件事务后端。支持范围是 Windows x64、本地固定 NTFS 卷;后端不可用时拒绝写入,不退回普通宿主文件写入。
本批没有新增 WorkBuddy 取证。它是 YCode 自有边界实现,不代表 P3 全部完成或原版等价验收。
| 文件 | 职责 |
| --- | --- |
| `native/sandbox/filesystem-write.h` | 宿主专用事务通道;固定根和目录句柄,按父目录句柄打开、创建、重命名和删除目标 |
| `native/sandbox/runner.cpp` | `--workspace-write` 宿主入口;AppContainer 内调用直接拒绝 |
| `src/main/sandbox/filesystem-writer.ts` | 私有串行通道、帧/时限限制、身份检查和生命周期 |
| `src/main/sandbox/native-component.ts` | 命令和事务共用组件摘要、普通文件身份及事务协议校验 |
| `src/main/sandbox/transactions.ts` | v3 根身份日志、独立 before/after 备份、逐操作意图、提交/补偿/恢复 |
| `service.ts` / `agent/tools/index.ts` | 执行或审批前捕获工作区身份;原有授权消费和策略撤销继续有效 |
## 实际边界与文件语义
1. 根目录从本地卷逐级打开并保留祖先句柄。后续目标由 `NtCreateFile` 的 `RootDirectory` 和单个名称解析,启用 `OBJ_DONT_REPARSE` / `FILE_OPEN_REPARSE_POINT`;重命名用 `NtSetInformationFile` 的父目录句柄。不会在检查后重新用绝对路径遍历整个祖先链。
2. 根和目录句柄不共享删除,固定名称和身份。根祖先允许写共享以兼容原生目录操作,但目标解析仍基于已持有的目录对象,校验 reparse 属性和最终名称。文件目标不共享写入/删除;多重硬链接、reparse、设备、既有可写句柄和只读目标均拒绝,失败后不放宽共享模式重试。
3. 普通命令在快照前捕获工作区卷/文件 ID,默认文件工具在审批前捕获;提交前重新核对。即使同一路径被换成内容相同的新目录,旧审批也不能向新根写入。v3 恢复同样绑定原根身份。
4. 读取备份和检查现有内容发生在原生固定句柄下。文件写入、删除和目录删除由原生句柄执行,保留摘要冲突检查;目录最终删除还会由文件系统检查是否为空,外部新文件不会被递归删除。
5. 本批不直接向沙盒进程开放写入桥。项目命令继续修改副本,由原有整批审批触发宿主事务;已有 Node 读取桥继续只读。新通道仅由宿主主进程持有,不是逐后代 PID 认证协议。
文件替换采用两步、不覆盖的名称交接:先刷新新内容的临时文件,在保持原文件句柄固定时把原文件移到预先记录的专用临时名,再把新文件移动到目标名;两次移动均不覆盖既有名称。若竞争者创建了目标,发布失败并保留竞争者内容,随后执行补偿或标记需恢复。
因此,这不是单次原子交换,两个移动之间有短暂缺名窗口。普通读取者可能观察到 ENOENT;本批不宣称无中间状态。Windows 通用绝对路径重命名和 POSIX 替换在固定句柄条件下实测发生共享冲突,最终生产实现使用上述相对句柄交接,不通过释放目标锁重试来绕过它。
## 日志和恢复
- v3 manifest 保存根身份、完整 before/after 摘要、目录增删、调用/策略/审批归属。原文件备份、目标备份和逐操作意图均在宿主变更前刷新文件缓冲。
- 每次操作意图独立保存于 `transactions/<id>/mutations/<nonce>.json`。恢复会合并独立记录和 manifest,避免主进程中断后漏掉尚未汇总的操作;正常执行不为每个文件重写整个批次 manifest。
- 默认文件工具隐式创建的父目录也进入事务,恢复时可移除其未变化的目录树。
- `.ycode-sandbox-` 是保留名称前缀,不进入正常命令快照,模型文件操作不能访问。恢复仅清理日志 nonce 对应且内容摘要一致的临时文件;外部新增或变更的内容继续拒绝清理。
- 后端死亡或回复丢失时不推断“未执行”,未能补偿的批次保留 `recovery-required`。新的原生会话可根据独立备份恢复;交接中断造成的缺名状态可按已记录意图恢复,不能覆盖后来的外部编辑。
- v1/v2 历史记录仍可读取,在原生边界内恢复并升级为 v3。历史记录原本没有根身份,不能追溯补上当时的身份保证。
```powershell
npm run test:sandbox:write
npm run sandbox:maintain -- restore TRANSACTION_UUID --workspace 'C:\absolute\workspace' --state-root 'C:\absolute\userData\sandbox'
```
## 验证
全部测试使用独立 `.tmp` 工作区/状态目录和隔离 Electron userData;不修改生产策略,不重启用户窗口。
| 范围 | 结果 / 最终报告 |
| --- | --- |
| 原生写入专项 | 32/32;`.tmp/sandbox-write-GuLFv7/report.json` |
| 目录事务 | 13/13;`.tmp/sandbox-directories-Y8KMq0/report.json` |
| 基础隔离/宿主工具 | 52/52;`.tmp/sandbox-regression-diTTJm/report.json` |
| 策略/授权 | 38/38;`.tmp/sandbox-policy-UMZshP/report.json` |
| Git 本地工作流 | 43/43;`.tmp/sandbox-git-5Z9639/report.json` |
| 内置 Git 分发/资源 | 20/20;`.tmp/sandbox-bundled-git-CzL0UX/report.json`;本次未额外提供离线归档重建参数 |
| 读取桥 | 21/21;`.tmp/sandbox-read-bridge-nsjAQ4/report.json` |
| 真实生产 Electron/OMP | 31/31;`.tmp/sandbox-app-RVG4C7/report.json` |
| 完整生产构建 | `npm run build` 通过,包含原生 `/W4 /WX`、主进程/渲染器类型检查与 main/preload/renderer 生产产物;本次不另作安装包验收 |
最终 8 组共 250 项通过。组件源码/二进制和构建产物身份、各报告摘要及限制汇总于 `.tmp/sandbox-native-write-validation.json`;组件 manifest 源码摘要与当前源码逐项一致,原生 `--version` 与 manifest 均为 0.5.0。
专项覆盖:固定根和祖先、junction/硬链接/ADS/敏感路径、二进制和空文件、既有可写句柄、只读文件、AppContainer 调用宿主入口拒绝、审批期间根替换、外部编辑和目录新增、默认文件工具、隐式父目录恢复、实际后端死亡后的批次恢复、回复通道失效拒绝降级、专用临时文件的冲突保护,以及实际维护 CLI 的中文/空格/`^` 路径和 v1/v2 恢复升级。
“交接中断缺名并留下 old/new 临时文件”的用例是可复现磁盘状态夹具;不能把它写成已经在每个原生指令位置强制断电/终止的验收。另有真实终止原生后端的批次恢复测试,两者证据范围分开。
## 剩余限制与下一步
尚未验收断电级目录耐久性;文件刷新不等于 NTFS 命名操作和完整事务已经断电原子化。写入中断造成未完成的临时内容、临时文件被外部修改、损坏的意图记录等情况会拒绝自动清理,需继续保留恢复状态并人工核对。
尚未完成完整描述符/追加/语言 shim、ACL/时间戳等元数据、回收站、逐程序和逐后代规则、磁盘硬配额、长期工作区、标准用户/支持 OS/特殊 NTFS 配置矩阵及独立安全审查。当前验证不能推广到其他文件系统或平台。
下一阶段优先实现长期工作区的身份、策略失效、外部编辑冲突和提交/丢弃规则,再接宿主 Git 元数据事务与受控依赖更新。
## 原生 API 依据
- [ZwCreateFile / RootDirectory 与共享规则](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-zwcreatefile)
- [NtSetInformationFile / FileRenameInformation](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntsetinformationfile)
- [FILE_RENAME_INFORMATION](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_rename_information)
以上官方接口资料用于解释执行点,支持范围以自有测试和列出的限制为准。