Skip to content

E5b(#5040 执行器):接线收拢 —— 派发步 501 分支替换为「策略链 → 执行委派」+ 真实 boot 集成测试 #5129

Closed

Description

@os-zhuang

Part of #5040(E 系列 R3 收拢单,小型)。Blocked-by: #5091(E4)+ #5092(E5) —— R3 为避免两单同改 api-endpoint-step.ts 的必然冲突,按模块切面解耦(E4 独占派发步接线、E5 只出纯执行模块),本单在两者落 main 后做最后接线。

范围(小)

  1. api-endpoint-step.ts:命中分支的 501 兜底替换为完整链 —— 匹配 → 策略链(E4,401/429/头已接)→ executeEndpointTarget(E5 模块)→ 响应映射;cacheTtl 计算头应用到真实执行结果上(E4 落地时如何暴露以其模块文档为准);
  2. per-environment metadata/services 解析:按 E5 落地报告的 followup 与 E3 注释(需要 dispatch() 的 resolver;单租户直取本 kernel 服务,多租户路径如超出小单范围,如实报告并留给 E8 前置);
  3. 真实 boot 集成测试(扩展 dispatcher-plugin.endpoint-fallback.integration.test.ts):命中执行(object_operation + flow 各一)、策略拒绝(401/429)短路不执行、未命中/前缀外仍逐字节不变;
  4. 台账 * /apps/** 行注记更新:「EXECUTION IS NOT WIRED」改为如实描述已接线状态(仍注明 publish 门未翻转,结构性不可达);
  5. changeset(@objectstack/runtime minor,仍零现网行为变更)。

约束

执行器车道程序卡(session_01EYGdmvWP1ieZSLqvAW6uyd 按序派发),其它车道请勿认领;词表与 spec 零触碰;E6(#5093)与 E7(#5111)的 Blocked-by 链随本单顺移(E6 实际前置 = 本单)。

关联:#5091、#5092、#5090(seam)、#5040 设计 §3/§5。

Activity

  1. added
    enhancementNew feature or request
    domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they land
    on Aug 4, 2026
  2. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    ContributorAuthor

    E4(#5091 / PR #5135)交接契约 —— 本单要接的那几根线

    E4 已把策略链落在 packages/runtime/src/endpoint-policy.ts,并在 api-endpoint-step.ts 的命中分支里调用。按 R3 文件面切分,E4 不碰 dispatcher-plugin.ts,所以下面这两根线留给本单接:

    1. 兜底器要把策略上下文喂给派发步。 AppEndpointStepInput.policy 目前是可选的,兜底器没传 —— 没传时终态答复仍是 501,因此今天不存在「未经策略就被服务」的请求;但本单把 501 换成执行的同一次改动必须同时传它,否则执行会落在一个策略没跑过的分支上。上下文形状(EndpointPolicyContext):

    • headers / remoteAddress:直接取兜底器的 req(E3 已备好 remoteAddress);
    • resolvePrincipalId:用 security/resolve-session-principal.ts 的 resolveSessionPrincipalId(authService, headers) —— 与 server 级限流器、dispatcher 具体路由挂载同一个查询,别新起一个;
    • limiters:createEndpointRateLimiterRegistry({ resolveCache: () => safeGetService('cache'), logger }) —— 在 start() 里建一次,不要每请求新建(每请求新建会让每端点桶的降级 warn 重复刷屏,且限流器缓存失效);
    • trustProxy:透传 config.rateLimit?.trustProxy === true,与 server 级读同一份声明,不造第二个信任开关。

    2. 兜底器要写出 answer.headers。 AppEndpointStepAnswer 新增了 headers?(429 的 Retry-After 走这里);现在的兜底器只写 status + securityHeaders + json,会把它丢掉。一个丢了 Retry-After 的 429 对客户端等于没说话。

    3. cacheTtl 的头怎么用。 卡面问「E4 落地时如何暴露以其模块文档为准」——答案:不在 501 上应用,挂在裁决对象上。applyEndpointPolicies 返回 { verdict: 'pass', principalId?, responseHeaders },responseHeaders 即 {'Cache-Control': 'private, max-age={秒数}'}(或 no-store,或空对象)。理由:Cache-Control 描述的是尚不存在的成功响应体,让客户端缓存一个 501 比什么都不说更糟。本单把执行结果的成功答复合成时,把 responseHeaders 并进去即可;verdict.principalId 也顺带给了执行委派,不必再查一次会话。

    4. 落点位置是结构性的。 E4 把执行落点安排在策略链之后的分支里,而该分支在没有策略上下文时不可达 —— 本单加执行调用时没有别的地方可放,这正是「接了执行、忘了策略」不可能发生的原因。请保持这个形状,别把执行提到 applyEndpointPolicies 之前或与之并列。

    5. 集成测试。 dispatcher-plugin.endpoint-fallback.integration.test.ts 目前只有 E3 的否定断言(E4 未扩它 —— 兜底器没喂上下文,策略用例在真实 boot 里还构造不出来)。本单接上线后,401 / 429 短路两条真实 boot 用例是本单卡面第 3 条的应有之义。


    Generated by Claude Code

  3. self-assigned this
    on Aug 4, 2026
  4. os-zhuang commented on Aug 4, 2026

    @os-zhuang
    ContributorAuthor

    认领 —— PM 会话 session_01EYGdmvWP1ieZSLqvAW6uyd(执行器车道),分支 claude/issue-5129-wire-endpoint-chain,即刻派发。前置齐备:E4(a70cd0a)/ E5(277eb36)均落 main,复核毕。

    文件面声明(#4604):packages/runtime/src/dispatcher-plugin.ts(兜底器喂 EndpointPolicyContext + 写出 answer.headers + limiter registry 构建)、api-endpoint-step.ts(策略通过分支的 501 → executeEndpointTarget)、dispatcher-plugin.endpoint-fallback.integration.test.ts 扩展、route-ledger.ts 注记更新、changeset。移交契约以本单此前 E4 评论 + PR #5136 正文「接线单」段为准。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landenhancementNew feature or requestpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions