Repository navigation
ScriptContext.user 是 unknown —— 沙箱接缝上没有任何类型把 dispatcher 的 user 形状钉住(observation) #5521
Description
Activity
发现分诊轮判级:持有(留
finding,补挂domain:cli缓存落点判断 ——packages/runtime归 cli 车道)。为什么还留着:运行时形状已统一且有逐键 pin 测试兜底,今天无任何用户可撞面;类型收紧的前置(核实 hook 面engineCtx.user实际交付形状)未做,三个方向未裁。重启条件:出现第四个 dispatch 面、或 hook 面形状核实完成时晋级。下轮分诊轮复核。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
相邻信息(不是认领):#5613 的 runtime 半边(PR #5991)把同一个接缝的姊妹字段
ScriptContext.session从unknown收窄了,给本单的user字段留下了一个可直接照抄的模子和一份实测数据。收窄成什么:不是单一类型,而是两个真实生产者形状的联合,并导出成命名类型 ——
export type ScriptSession = ActionSession | HookContext['session'](packages/runtime/src/sandbox/script-runner.ts)。理由是这个 seam 确实同时承载 hook body 与 action body,收成其中任一单型都会在另一边说谎。user面大概率是同样的结构(dispatcher 侧的ActorUservs hook 侧的 user 形状),差别在于ActorUser今天只有 runtime 的 TS interface、没有 spec 契约(这一点单独记在 #6011)。#5697 当初留
unknown的那句理由(「收窄会逼 seam 的每个消费者去判别 body 种类」)这次实测过,对session字段不成立:两个写入方(body-runner.ts的buildSandboxContext/buildActionSandboxContext)都从any引擎上下文赋值,唯一读取方(quickjs-runner.ts的installCtx→setObjectJson)收unknown,全仓(objectstack / objectui / cloud)ScriptContext没有 runtime 包外引用。全仓turbo run typecheck125/125 绿,收窄面止于 runtime 包内。同样的测法应当先对user字段跑一遍再动手 —— 结论可能不同(user的读取方比session多)。本单仍未认领,
finding不变。
Generated by Claude Code
Generated by Claude Code
发现分诊轮(#4949 纪律):持有(留
finding),域维持domain:cli。一、过时前提检查(
origin/main@9e3709a)08-05 那版的两条重启条件逐条核过 —— 一条的前置模子已落地、测量本身仍未做,另一条未成立:
- 「hook 面形状核实完成」:姊妹字段
session的收窄已随 PR feat(runtime)!: action ctx.session 双发 positions(权威)+ roles(弃用别名) (#5613) #5991 于 2026-08-06 15:06Z MERGED。origin/main上packages/runtime/src/sandbox/script-runner.ts:54现有export type ScriptSession = ActionSession | HookContext['session'],而同一个 interface 的:86仍是user?: unknown—— 模子与缺口相隔 33 行。测法也已由 14:46Z 那条相邻信息记全,但针对user面的那一遍测量至今没人跑。 - 「出现第四个 dispatch 面」:未成立。
origin/main上仍恰好两个(非测试命中即此二处):body-runner.ts:307 buildSandboxContext/:326 buildActionSandboxContext。
二、⛔ 本轮新事实 —— 一条硬串行,也是维持持有的主要理由
#6011(
priority:p0+pm:queue+pm:dispatched+domain:cli+target:v17,在飞)正在处置ActorUser的roles/positions双发别名,落点packages/runtime/src/security/actor-user.ts。而ScriptContext.user的两个写入方交付的正是这个形状:body-runner.ts:315—user: engineCtx?.user ?? engineCtx?.session?.userbody-runner.ts:340—user: actionCtx?.user ?? actionCtx?.session?.user
⇒ 本单要收窄的目标类型,此刻正由 #6011 重新定形。现在晋级等于让 dev 在一个正在变的形状上钉类型,因此持有,不晋级。
三、重启条件(重新锚定,替代 08-05 那版)
- [runtime]
ctx.user的roles别名(值是positions)没有关闭日期 —— #5613 给 ctx.session 装了迁移窗口,同名同值的 ctx.user 面仍是无限期别名(observation) #6011 落地(其 PR 合入origin/main)⇒user的生产者形状定形; - 随后按 feat(runtime)!: action ctx.session 双发 positions(权威)+ roles(弃用别名) (#5613) #5991 的同一测法跑一遍
user面:写入方两处(上列)、VM 侧唯一读取方quickjs-runner.ts:489的setObjectJson(vm, ctxObj, 'user', ctx.user)、跨仓消费方。
跨仓那一格本轮已顺带跑完:
ScriptContext在 objectui / cloud 零命中(阳性对照:两仓package.json均命中objectstack,证伪「扫描器坏了/路径错了」)⇒ 收窄面止于 runtime 包内,与session当初的结论一致,这一格晋级时不必重跑。⚠️ 晋级时须点名一处比session更复杂的差异:user的两个写入方各带?? …session?.user兜底链(session字段当初没有),即形状来源比姊妹字段多一路。若测量结论是「联合类型要含第三支」,那已越出照抄ScriptSession模子的范围,需在派发令里作为必答项。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- 「hook 面形状核实完成」:姊妹字段
Findings triage (objectstack#4949 discipline) — restart condition 1 FIRED ⇒ PROMOTE to
pm:queue. Domain unchanged:domain:cli.1. The trigger
The previous verdict held on one blocker and named its exit:
- [runtime]
ctx.user的roles别名(值是positions)没有关闭日期 —— #5613 给 ctx.session 装了迁移窗口,同名同值的 ctx.user 面仍是无限期别名(observation) #6011 落地(其 PR 合入origin/main)⇒user的生产者形状定形
#6011 closed
2026-08-07T01:25:53Z, via PR #6048 merged2026-08-07T01:25:52Z(退役 ctx.user 的 roles 别名,positions 成为唯一拼法). The type this issue wants to pin is no longer being reshaped underneath it — that was the whole reason for the hold.2. Stale-premise check (
origin/main@ede5a8e) — the gap is unchangedpackages/runtime/src/sandbox/script-runner.ts:86— stilluser?: unknown;- the sibling field in the same interface,
:119, issession?: ScriptSession, typed againstScriptSession = ActionSession | HookContext['session'](:54) — the model feat(runtime)!: action ctx.session 双发 positions(权威)+ roles(弃用别名) (#5613) #5991 landed still sits 33 lines from the gap.
3. What carries over, so the dispatch does not redo it
- Restart condition 2 is the dispatch's own first step, not a gate: run the feat(runtime)!: action ctx.session 双发 positions(权威)+ roles(弃用别名) (#5613) #5991 measurement over the
userface — the two writers (body-runner.ts:315/:340), the single VM-side reader (quickjs-runner.ts:489,setObjectJson(vm, ctxObj, 'user', ctx.user)), and cross-repo consumers. - The cross-repo cell is already done and need not be re-run:
ScriptContexthas zero hits in objectui / cloud, with a positive control (both repos'package.jsonmatchobjectstack) ruling out a broken scan. The narrowing surface stops insidepackages/runtime. - One difference from
sessionto carry into the dispatch: both writers carry a?? …session?.userfallback chain, which thesessionfield had no equivalent of — so the narrowed type has to admit whatever that chain can yield, not just the primary producer's shape. - "Fourth dispatch face" (the other half of the old condition) is still not met: exactly two on main, as before.
4. Serial constraints
No open PR touches
packages/runtime/src/sandbox/**(all 5 open PRs enumerated this round). Re-pullorigin/mainat claim time regardless.⛔ No
target:<major>: a sandbox-seam type gap, not a shipped-surface defect.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- [runtime]
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(仅记录,不认领)