完善共享授权与本地同步闭环

实现独立 share-grants 控制面,区分产品分享授权与本机目录授权。

收紧 shared AI session 的资源范围,并补充 shared cache、pending change 与冲突报告 sidecar。

更新当前架构与执行 checklist,记录 P4 已完成项和剩余 browser smoke。
This commit is contained in:
lix-2026
2026-05-19 11:11:08 +08:00
parent fc4a47e597
commit a1b28a8e38
7 changed files with 1889 additions and 48 deletions
+1 -1
View File
@@ -135,7 +135,7 @@
2. VSCode-like 冲突处理 UI:接受磁盘版本、保留当前编辑器版本、打开 diff / 合并。
3. agent 写入审计:回收 changed files、diff summary、actor、workspace root、permission level、run id。
4. 本地索引:全文搜索、反链、页面引用、资源引用、标签,不依赖 Convex search 才能搜索本地 workspace。
5. 分享与同步闭环:share grants、shared workspace cache、shared AI session、离线权限收敛和同步冲突报告。
5. 分享与同步闭环:独立 share grants 控制面、shared workspace cache、shared AI session、离线权限收敛和同步冲突报告share grant 不等于本机 local access grant,不能自动扩大本机目录读写权限
6. 插件资源模型:simplemindmap / office 作为 Resource Tree 对象打开和保存,Markdown 只保留链接或嵌入引用。
7. 旧 Convex 数据迁移产品化:真实导出入口、迁移进度、备份、冲突报告和回滚策略。
@@ -243,29 +243,45 @@
### 5.1 分享权限
- [ ] 定义 share grant 与 local access grant 的关系:分享不自动扩大本机文件系统权限。
- [ ] share grant 支持 read / write / ai capability
- [ ] shared AI session 只能访问 share grant 允许的资源
- [ ] 管理员可查看和撤销 share grant。
- [x] 定义 share grant 与 local access grant 的关系:share grant 是产品层共享授权,local access grant 是本机文件系统目录授权;分享不自动扩大本机 root 读写权限。
- 实现:`share_grant_admin_api_creates_reads_and_revokes_without_local_access` 验证 share grant 不授予 target 用户本地 filesystem read/write access
- [x] 增加 canonical share grant 控制面:默认落在 `/mnt/Data1T/Mnote_data/control-plane/share-grants.json`,记录 `shareId`、owner、target、root、resource scope、permission、capabilities、生命周期和撤销状态
- 实现:新增 `GET/POST/DELETE /api/admin/share-grants`;支持 `MNOTE_SHARE_GRANTS_FILE` 覆盖测试路径
- [x] share grant 支持 `read` / `write` / `ai` capability,并可映射到 `AiAccessScope.permissionLevel=shared_read/shared_write`
- 实现:Hermes local ACP run 从 canonical share grant 生成 `shared_read/shared_write`
- [x] shared AI session 只能访问 share grant 允许的资源;`allowedResourceIds` / `shareContext` 必须来自 canonical share grant,不接受浏览器自报扩大范围。
- 实现:`hermes_client_run_body_shared_scope_uses_share_grant_resources``acp_runtime_env_limits_shared_scope_to_granted_files` 覆盖 `shareContext``allowedResourceIds` 和文件级 allowed roots。
- [x] 管理员可查看、创建和撤销 share grant;owner 后续可管理自己创建的 share grant。
- 实现:管理员页面新增独立“分享授权”面板,与目录授权面板分离。
### 5.2 同步缓存
- [ ] 设计 shared workspace cache 目录。
- [ ] 云端同步到本地 cache 时保留来源、版本、权限和冲突信息
- [ ] 本地修改同步回云端前进行权限和版本校验
- [ ] 离线期间记录 pending changes,恢复在线后生成同步报告
- [x] 设计 shared workspace cache 目录:默认位于 `/mnt/Data1T/Mnote_data/shared/workspaces/<share-id>/`workspace 内缓存 `.mnote/share-cache.json``.mnote/sync-state.json` 只保存授权、版本、来源和同步状态,不成为第二份正文真相
- 实现:新增 `/api/local-folder/shared-cache/record``/api/local-folder/sync/pending-change`,均只写 `.mnote` sidecar
- [x] 云端同步到本地 cache 时保留来源、版本、权限和冲突信息:至少记录 `shareId``remoteVersion``baseVersion``permission``sourceActor``syncedAt`
- 实现:`.mnote/share-cache.json` 写入 `mnote.share_cache.v1`
- [x] 本地修改同步回云端前进行权限和版本校验:`shared_read` 永远不能上传 pending write`shared_write` 必须校验 share grant 未撤销且 base version 未过期。
- 验证:`shared_cache_and_sync_state_record_permissions_and_conflict_report` 覆盖 shared_read 拒绝 pending write、shared_write 写入 pending change、remote/base version 冲突返回 409。
- [x] 离线期间记录 pending changes,恢复在线后生成同步报告;pending changes 只能来自已有授权 cache,离线不能新增或扩大授权。
- 实现:pending changes 写入 `.mnote/sync-state.json`,写入前强制校验 canonical share grant。
### 5.3 同步冲突报告
- [ ] 同步冲突复用 P1 的冲突 UI。
- [ ] 冲突报告包含本地版本、远端版本、base version、修改 actor
- [ ] 管理员或 owner 可导出冲突报告。
- [x] 同步冲突复用 P1 的冲突 UI,并把冲突来源标记为 shared sync 而不是普通外部文件变更
- 实现:`/api/local-folder/sync/conflict-report` 生成 `source=shared_sync``suggestedActions=["accept_local","accept_remote","open_diff_merge"]` 的报告 envelope,供 P1 diff / merge UI 消费
- [x] 冲突报告包含本地版本、远端版本、base version、修改 actor、shareId 和 resource id
- 验证:`shared_cache_and_sync_state_record_permissions_and_conflict_report`
- [x] 管理员或 owner 可导出冲突报告;报告写入 control-plane 或 workspace `.mnote/sync-reports/`,不写入正文目录。
- 实现:报告写入授权 workspace 的 `.mnote/sync-reports/`
建议验证:
- [ ] 单测:share read 不允许写入。
- [ ] 单测:shared AI session 不扩大 workspace root
- [x] 单测:share read 不允许写入。
- 验证:`cargo test -p mnote-web shared_cache -- --nocapture``cargo test -p mnote-web hermes_client_local_shared -- --nocapture`
- [x] 单测:shared AI session 不扩大 workspace root。
- 验证:`cargo test -p mnote-web acp_runtime_env_limits_shared_scope_to_granted_files -- --nocapture`
- [ ] browser smoke:共享页面只读用户无法通过 AI 写入正文。
- 说明:当前已有 route / runtime 单测闭环;浏览器 smoke 仍需补脚本覆盖 UI 层拒写提示。
---