Skip to content

feat(runtime)!: 退役 ctx.user 的 roles 别名,positions 成为唯一拼法 (#6011) - #6048

Merged
qq9340100 merged 1 commit into
mainfrom
claude/issue-6011-actor-user-roles-retire
Aug 7, 2026
Merged

feat(runtime)!: 退役 ctx.user 的 roles 别名,positions 成为唯一拼法 (#6011)#6048
qq9340100 merged 1 commit into
mainfrom
claude/issue-6011-actor-user-roles-retire

Conversation

@qq9340100

Copy link
Copy Markdown
Collaborator

Fixes #6011

按维护者 2026-08-06 14:49Z 的就地裁决执行:方向 2「直接退役」—— 立即删除 ctx.user 上的 roles 别名,不设弃用窗口、不双发。

改了什么

ActorUser(action body 的 ctx.user / AI 路由处理器的 req.user)此前同时声明并发出两个键,值由同一次赋值产生、逐字相同:

  • 声明:packages/runtime/src/security/actor-user.tsroles: string[]
  • 构造:同文件 buildActorUser() 里的 roles: core.positions

两处一并删除,positions 成为该面唯一的位置拼法。原注释声称该别名 "kept for the REST/AI shapes" —— 这一说法在删除前被核实并证伪(见下)。

消费方核实(删除的硬前置)

一律以 origin/main(>= 739f496,即 #5991 合并后)为准做 git grep,不读工作树;零命中结果都用已知存在的邻近词 positions 做了反证,确认 grep 本身有效。

消费面 结果
本仓全仓 user.roles / req.user.roles(所有文件类型) 仅 4 处,全部在测试里,即本 PR 翻转的那几个钉子
ActorUser 的四个生产点 action-execution.ts / dispatcher-plugin.ts / domains/actions.ts / domains/ai.ts —— 构造的都是服务端 body / 路由处理器信封,不进入任何 HTTP 响应体
REST / AI 路由 未见任何处理器读 .roles
examples/(showcase / CRM 的 action body) 零命中
objectui(/home/user/objectui,origin/main) .roles 命中全部落在另外两个独立生产者上:better-auth 会话的 user.roles / user.role(AuthGuard / useIsWorkspaceAdmin),以及 /api/v1/auth/me/permissions 响应体(由 plugin-hono-server/src/current-user-endpoints.ts 自行构造)。没有一处消费 ActorUser
文档 / skills 没有任何手写文档教 ctx.user.roles;唯一相关的一处 (content/docs/permissions/permission-metadata.mdx:201) 恰恰在申明「不存在 current_user.roles

⚠️ cloud 仓在本会话不可达,因此它是未经核实的消费面。changeset 里的迁移处方(rolespositions,值不变)即为该面的处置说明。

钉子:翻转而非删除

三个文件里的断言都同批翻转并继续承载,既断言新语义的实质,又钉住方向:

  • action-ctx-user-shape.test.ts —— 原「aliases stay in lockstep」整条替换(它钉的正是被删的那条肢,留着会因「什么都没产生」而空绿):现在断言 positions 逐字承载调用者位置, 'roles' in ctx.user === false
  • http-dispatcher.test.ts —— 两处 user.roles 断言改为其反面(键不存在),而非删掉。
  • ai-request-user-capability-channel.test.ts —— user.roles 改读 user.positions(该用例的实质是「位置是与两条权限通道互不合并的第三条通道」,实质保留),并补键不存在断言。

断言用 'roles' in user 而不是 toBeUndefined():后者无法区分「键已删除」与「键还在、值为空」的半吊子退役。

反向验证(方向预先判定为「红」,结果一致):把删掉的 roles: core.positions 恢复回去后,7 条断言转红 —— 2 条键集断言(8 键 vs 7 键)、1 条 value-for-value toEqual、4 条 expected true to be false(新的键不存在钉子)。恢复后即刻回退。

⛔ 范围外(已刻意不动)

测试证据

pnpm --filter @objectstack/runtime typecheck   → 干净通过(tsc --noEmit,无输出)
pnpm --filter @objectstack/runtime test        → Test Files 102 passed (102)
                                                 Tests 1476 passed (1476)
pnpm check:role-word                           → OK (43 baselined, no new occurrences)
node scripts/check-nul-bytes.mjs               → OK (5779 files, no raw control bytes)
eslint(4 个改动文件)                          → exit 0

关于待定的 spec 半边(回答派发时的必答问题)

本改动使 spec 半边的 ADR-0087 台账条目更简单,并不使其变得不必要。

理由:台账条目要记录的「FROM → TO」事实已经在本 PR 里被确定并固定了 —— 退役已发生、迁移映射是纯改键(值不变)、消费面已扫清且证据在案、positions 唯一拼法已有钉子守住。因此 spec 座位写条目时不必再自行判定退役范围或复核消费方,只需把既成事实登记入册。它仍然必要:没有条目,这次退役在台账上不可见,与同族 session 侧已有的三条(data.hookContext.session.rolesui.actionSession.rolesCEL/formula: current_user.roles)不对称,而这种不对称正是本 issue 立单的原因。

需要提醒 spec 座位的一点:ctx.user至今没有 spec schema,只有 runtime 的 TS interface —— 所以该条目登记的是一个 spec 从未声明过的键的退役,这与 session 侧「schema 里有声明可改」的情形不同,条目的 surface 写法需要相应处理。


🤖 Generated with Claude Code

https://claude.ai/code/session_01Wbxm29qPKnLf44AbSxizqW


Generated by Claude Code

ActorUser 同时声明并发出 `positions` 与 `roles`,两者由同一次赋值产生、值
逐字相同。`roles` 是 ADR-0090 D3 保留并禁用的词,且从未有关闭日期 —— 与
#5613 给 ctx.session 装上迁移窗口的同族面相比,这一面既无 spec 契约、也无
ADR-0087 台账条目、也无移除路径。维护者 2026-08-06 就地裁决:立即退役,
不设弃用窗口、不双发。

消费方核实(删除的前置条件,因为旧注释声称该别名 "kept for the REST/AI
shapes"):全仓 + objectui 扫描未见任何活体读取 `ActorUser.roles` 的代码。
四个生产点(action-execution / dispatcher-plugin / domains.actions /
domains.ai)构造的都是服务端 body / 路由处理器信封,不进入任何响应体;
objectui 的 `.roles` 读取全部落在 better-auth 会话与
`/api/v1/auth/me/permissions` 两个独立生产者上。

钉子同批翻转而非删除:三处断言改为既断言新语义的实质(`positions` 逐字
承载),又钉住方向(`roles` 键不存在)。反向验证已做:恢复被删的构造分支
后 7 条断言转红,方向与预期一致。

⛔ 不含 ctx.session:该面按 #5613 保留其弃用窗口,双发不动。
⛔ 不含 packages/spec:ADR-0087 台账条目另行落地。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wbxm29qPKnLf44AbSxizqW
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 6, 2026 3:41pm

Request Review

@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Aug 6, 2026
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/runtime.

21 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/api/client-sdk.mdx (via packages/runtime)
  • content/docs/api/index.mdx (via @objectstack/runtime)
  • content/docs/api/wire-format.mdx (via @objectstack/runtime)
  • content/docs/automation/hook-bodies.mdx (via @objectstack/runtime)
  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/runtime)
  • content/docs/concepts/north-star.mdx (via packages/runtime)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/runtime)
  • content/docs/deployment/index.mdx (via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/deployment/vercel.mdx (via @objectstack/runtime)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/runtime)
  • content/docs/kernel/cluster.mdx (via @objectstack/runtime)
  • content/docs/permissions/authentication.mdx (via @objectstack/runtime)
  • content/docs/permissions/authorization.mdx (via packages/runtime)
  • content/docs/plugins/packages.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/runtime)
  • content/docs/releases/implementation-status.mdx (via @objectstack/runtime)
  • content/docs/releases/v17.mdx (via @objectstack/runtime)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@qq9340100 qq9340100 closed this Aug 7, 2026
@qq9340100 qq9340100 reopened this Aug 7, 2026
@qq9340100
qq9340100 marked this pull request as ready for review August 7, 2026 01:06
@qq9340100
qq9340100 added this pull request to the merge queue Aug 7, 2026
Merged via the queue into main with commit dca5bd3 Aug 7, 2026
53 of 97 checks passed
@qq9340100
qq9340100 deleted the claude/issue-6011-actor-user-roles-retire branch August 7, 2026 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants