Files
Agent-System-Documents/docs/proposals/2026-10-14-iam-u3-delegated-projection-actor-amendment.md

7.8 KiB
Raw Permalink Blame History

IAM U3 委任项目改名真实操作者围栏修订与实施计划 r1

状态:待阶段 4–5 人工重审;日期:2026-10-14。本文是已批准 U3 r1 及其 A1–A4 增量修订 的单点补充。仅涉及 I1 已交付的委任项目改名投影在 U3 账号停用围栏下的真实操作者传递;不改变 RDM 项目职责规则,不启动 U4–U9,不授权 PR、合入、生产迁移、部署或真实账号操作。

1. 问题、对象与边界

独立只读复核在 Backend 4053c4d038b1d13a356e0196db56ab11c0e4f8e1 后的 U3 未提交修复候选中发现:RDM internal/rdmapp/system_projects.go 已对请求主体 Bob 检查当前 project.settings,但委任 Bob 改创建者 Alice 的项目时,internal/rdmapp/host_projection.go 调用 extension.NewScopedHost(Alice, "rdm") 重建创建者 Host;Backend internal/app/project_lifecycle.go 的 RenameOwnedProject 将 Host owner Alice 同时作为最终 Store 事务 actor。若 Bob 通过 RDM 的最后授权检查后被停用,Backend 的 projects 表仍可在停用提交后由 Alice 身份完成改名。RDM 与 Backend 之间的授权快照窗口依旧不可原子关闭;此次可关闭的是 Backend 同一账号数据库内 Bob 有效态与项目投影写入的窗口,不能把后者归入已批准的跨库限制。

需求不变:项目创建者决定项目权限;获其委任且当前具有 project.settings 的成员可改名;系统管理员本身不因此获得项目内容或改名权。委任操作者停用后,已在途的物理投影不得在 Backend 最终事务中成功;创建者停用亦不应由旧 Host 句柄继续投影。项目 ID、创建者 owner 和委任 actor 是三个不同字段,不能互相代用。I1 的持久失败/恢复记录仍是跨库失败出口,不能假定两库提交原子性。

2. 推荐契约与备选

推荐新增由当前受信请求 Host 派生的可选项目投影能力,例如 extension.DelegatedProjectProjectionHost.ProjectProjectionForCreator(creator, projectID) (ProjectHost, error)。RDM 的 HTTP 生命周期回调和 rdm.project.rename 命令处理器都把当前认证主体绑定到各自传入的 requestHost;两条入口都必须从该次收到的 Host派生,不能另造操作者身份。派生句柄继承操作者 Bob、仅把资源 owner 收窄为 Alice。方法不接收调用方自填的 operator,也不复用按任意 owner 重建的全局 NewScopedHost 作为委任写入口。普通 NewScopedHost 继续服务既有读取/恢复能力,但不得替代新委任写入口。能力只向已注册的 RDM 项目生命周期/命令提供者开放;缺少能力、绑定不一致、项目不存在或插件来源不符时拒绝,不回退为创建者身份执行。

Backend 派生时核对原 Host 的操作者、插件来源、目标项目 ID 与持久创建者;RDM 仍按现有顺序检查 Bob 的当前 project.settings、项目 HostBinding 和改名意图。RenameOwnedProject 将真实 actor Bob、创建者 owner Alice、目标 ID 与名称分开送入 Store。最终 Store 事务按账号 owner 稳定排序锁定 Bob 与 Alice 并读取两者有效态,再取项目名称锁、读取持久项目 owner、校验名称并更新同一 projects 行;创建者本人改名时只锁一次。停用先提交则拒绝改名,改名先提交则停用等待;账号锁不授予 Bob 项目权限,RDM project.settings 检查继续独立存在。auth-off 缺失本地默认 owner 的例外只对该 owner 生效,明确停用记录拒绝。

未采用的方案:在全局 NewScopedHost 增加可自填 actor 参数,无法从受信请求句柄证明该 actor 是本次操作者;只在 RDM 最后授权后再查一次账号,仍有检查到 Backend SQL 之间的同库晚到窗口;把委任投影从 A1 承诺中豁免,则保留已知的 Backend 同库晚到写,与获批的 A1 契约不符。

3. 数据流、失败恢复与兼容

  1. HTTP 认证主体 Bob → Backend 生命周期回调或命令分发的 requestHost(Bob)→ RDM 当前 project.settings 判定与 HostBinding/意图校验。
  2. RDM 从同一个 requestHost 派生 Alice 项目的投影能力;能力内部固定 actor=Bob, owner=Alice, projectID=既定项目,RDM 不提交自选 actor。
  3. Backend Store 在最终事务中锁定并复核两个账号、项目 owner 与名称后提交物理改名;RDM 随后按 I1 原流程完成自己的数据库投影和意图记录。
  4. 派生能力在改名意图建立前不可用时直接拒绝,RDM 数据保持原状;意图建立后的账号停用、权限撤回、超时或 Backend 写入失败按 I1 规则标记失败并保留恢复信息。重试需新的受信请求 Host 和原意图 actor,重新检查当前权限/账号;不可把旧创建者 ScopedHost 当作跳过 Bob 的恢复捷径。

这个修订增加一个可选公开 Go 能力,不改 HTTP 请求/响应、迁移表或现有 ProjectHost 方法集合;RDM 的测试替身需要显式实现派生能力。若正式 Backend 尚未发布该能力,RDM 委任改名须返回能力不可用,不能默默回退。Frontend 无需新控件;已有项目改名错误提示可显示拒绝。两个数据库之间以及 RDM 权限撤回后的瞬时窗口仍不能声称零窗口,按 I1 持久意图和人工核对规则处理。

4. 实施计划与可判定验证

  1. 固定 Backend、RDM 和 Documents 候选 SHA;在 Backend pkg/extension 定义可选受信派生接口,在 internal/app 实现请求绑定、来源/项目核对。逐一追踪 HTTP 生命周期与 rdm.project.rename 命令两条入口;旧全局 ScopedHost 的委任写用法在两条改名路径全部替换,其它读取调用保持原状。
  2. Backend Store 增加两账号稳定排序的最终事务围栏,仅在项目投影入口使用;检查 Bob 与 Alice 有效态、持久项目 owner、全局名称唯一性和 rows affected。保持单账号项目创建路径与 U7 bootstrap 锁序;不得在 RDM 回调或模型/网络调用期间持有 Backend DB 事务。
  3. RDM 改名与失败重试从当前回调 Host 派生投影句柄,继续执行现有 project.settings 和 HostBinding/意图检查。缺少新能力时明确失败;已建立的意图按原规则保留,未建立意图的请求不凭空新增。补创建者本人、委任成员、停用创建者、错误绑定和权限撤回场景。
  4. 用可控屏障在 Backend 最终投影 SQL 前暂停,分别在隔离 SQLite 双 Store、PG 双连接/两进程停用 Bob,再继续,断言 Backend 项目名不变、无创建者身份回退;反向顺序验证先改名后停用。并发 Alice/Bob 锁顺序测试不得死锁。RDM 组合测试同时覆盖无会话 rdm.project.rename 命令和 HTTP PATCH:委任成员仅有 project.settings、无 doc.read 时均可改名;两入口的停用围栏、授权撤回与失败意图恢复均成立,不宣称跨库原子性。
  5. 重跑 Backend 全包/构建、隔离 PG、RDM 源码外 Go overlay、相关 Frontend 构建与浏览器路径;固定 SHA、命令和完整脱敏输出进入 Dev 任务卡 SELF 收据。随后重新提交阶段 6 人工评审;正式 pin、阶段 7、独立 Review/GATE、PR 与合入按既有前置分别处理。

停止条件:不能从受信请求 Host 得到真实操作者、测试发现 RDM 的回调来源并非可信身份、两账号锁序与 U7 冲突、或必须更改现有 ProjectHost 公开方法/持久数据设计时,先修订本文并重审,不以创建者代替 actor 继续交付。

5. 本次评审请求

请仅裁定本文件的阶段 4–5 契约与计划。批准后才实施上述新增接口与委任投影修复,并重跑受影响验证,再提交阶段 6 人工评审。本次不请求阶段 6 结论、阶段 7 验收、PR/合入、受信 tag、生产迁移或部署。