Skip to content

两处手写的 ExecutionContext 组装已漂移:REST 传输不带 principalKind / onBehalfOf,而 explain / security 会读它 #6071

Description

@baozhoutao

来源:#5859(producer 半边)实施时的越界发现,未在该 PR 修复。

事实(已核 origin/main)

resolveAuthzContext(@objectstack/core)被提取出来正是为了让两个 HTTP 入口不再漂移。
从授权信封组装成 ExecutionContext 的那一步仍是两份手写副本:

  • packages/runtime/src/security/resolve-execution-context.ts(dispatcher / MCP 入口)
  • packages/rest/src/rest-server.ts(execCtx = { … },os serve / dev 的数据与元数据路由)

两份的字段集已经不一致:runtime 那份按 ADR-0090 D9/D10 设置
ctx.principalKind(human / guest / agent)与 ctx.onBehalfOf,rest-server 那份
完全不设

消费方是存在的,且在 enforcement 面:

  • plugin-security/src/explain-engine.ts:95if (!context?.userId || context?.principalKind === 'guest') return 'EXTERNAL';
  • plugin-security/src/security-plugin.ts:2557const isAgent = context?.principalKind === 'agent';
  • observability/src/perf-timing.ts:475service / system 的披露闸门
  • explain-engine.ts:1122 — explain 输出里回显 principalKind

实测

在 dogfood showcase 全栈 boot(真实登录 + 真实 HTTP 请求)里插桩打印到达
plugin-sharing 的执行上下文,键集为:

userId, tenantId, email, positions, permissions, systemPermissions, posture,
isSystem, org_user_ids, accessible_org_ids, timezone, locale, __kernel, __readScope

__kernel 说明这是 rest-server 那条组装路径;principalKind不在键集里

影响面(未评级 — 交分诊)

同一个请求经 dispatcher 与经 REST 会在这两个字段上得到不同上下文,
所以读 principalKind 的判断在 REST 面从不成立(guest 分支、agent 分支)。
是否有用户今天就撞到,取决于这些分支在 REST 面各自还有没有别的等效前置判断
(security-plugin.ts:950 明确写了「按委托 LINK 判断而非 principalKind 标签」,
提示至少 agent 那一路可能另有兜底)—— 请分诊评级,不要按本文的语气推断严重性。

建议方向(非裁决)

把「授权信封 → ExecutionContext」的组装收成一处共享函数(与
resolveAuthzContext 同一 package),两个传输各自只做传输特有的补充
(REST 的 __kernel / authGate,dispatcher 的 OAuth scopes)。#5859 是这一族在
下一跳的活标本:producer 读的 organizationId两份组装都没写过的键,
于是整条 DEPTH 租户隔离恒不生效,而两侧看起来都合规。

Refs:#5859#5852、ADR-0090 D9/D10、ADR-0095 D2

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions