Observation-class finding,来自 #5372 / PR #5518 的实施。今天没有用户会撞到,不影响任何运行行为 —— 记录的是一处"声明缺席"而非缺陷。
观察到的事实
ScriptContext(packages/runtime/src/sandbox/script-runner.ts:59)把交给 body 的调用者声明为:
而 ctx.user 在两个方向上都是有契约的:
也就是说值已经统一了,但类型系统对此一无所知:unknown 之下,第四个 dispatch 面明天再手搓一个 user 字面量,编译器不会说一句话 —— 而"三个 dispatcher 手搓出三种形状"正是 #5372 的成因。#5372 之所以能存在几个版本,部分原因就是没有任何声明可以违背。
为什么按 observation 归档而不是缺陷
可能的方向(未裁决)
ScriptContext.user?: EvalUser(spec 契约,最小公分母),dispatch 面的传输键作为结构化扩展仍然合法;
- 在 runtime 侧导出
ActorUser 并声明 user?: ActorUser | EvalUser;
- 维持
unknown,改以闸门(而非类型)约束"user 形状只有一个生产者" —— 与 check:single-authz-resolver 同形。
需要先测 hook 面实际交付的形状再选。
会话:session_016FNvXhtSdnEGEfLEsMmvxh(仅记录,不认领)
Observation-class finding,来自 #5372 / PR #5518 的实施。今天没有用户会撞到,不影响任何运行行为 —— 记录的是一处"声明缺席"而非缺陷。
观察到的事实
ScriptContext(packages/runtime/src/sandbox/script-runner.ts:59)把交给 body 的调用者声明为:而
ctx.user在两个方向上都是有契约的:EvalUser(packages/spec/src/identity/eval-user.zod.ts),formula/stdlib.ts的buildScope正是把它挂在current_user/user/ctx.user三个别名上;ctx.user.name交付真实 display name —— 三条 dispatch 路径统一 user 形状 (#5372) #5518 之后由单一生产者packages/runtime/src/security/actor-user.ts构造,其身份内核就是同一个createEvalUser。也就是说值已经统一了,但类型系统对此一无所知:
unknown之下,第四个 dispatch 面明天再手搓一个 user 字面量,编译器不会说一句话 —— 而"三个 dispatcher 手搓出三种形状"正是 #5372 的成因。#5372 之所以能存在几个版本,部分原因就是没有任何声明可以违背。为什么按 observation 归档而不是缺陷
packages/runtime/src/action-ctx-user-shape.test.ts逐键、逐值断言三条路径相等);user来自引擎engineCtx.user,与 dispatch 面不是同一个生产者 —— 直接把类型收紧成ActorUser会把 hook 面一起断言进来,需要先核 hook 侧交付的到底是什么形状。这是这条 finding 里唯一真正的工作量,也是它不适合顺手做进 Action context'sctx.user.nameis hardcoded to the raw user id on the REST dispatch path — three dispatchers hand the sandbox three different user shapes #5372 的原因。可能的方向(未裁决)
ScriptContext.user?: EvalUser(spec 契约,最小公分母),dispatch 面的传输键作为结构化扩展仍然合法;ActorUser并声明user?: ActorUser | EvalUser;unknown,改以闸门(而非类型)约束"user 形状只有一个生产者" —— 与check:single-authz-resolver同形。需要先测 hook 面实际交付的形状再选。
会话:
session_016FNvXhtSdnEGEfLEsMmvxh(仅记录,不认领)