Repository navigation
E5b(#5040 执行器):接线收拢 —— 派发步 501 分支替换为「策略链 → 执行委派」+ 真实 boot 集成测试 #5129
Description
Activity
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
认领 —— 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
Part of #5040(E 系列 R3 收拢单,小型)。Blocked-by: #5091(E4)+ #5092(E5) —— R3 为避免两单同改
api-endpoint-step.ts的必然冲突,按模块切面解耦(E4 独占派发步接线、E5 只出纯执行模块),本单在两者落 main 后做最后接线。范围(小)
api-endpoint-step.ts:命中分支的 501 兜底替换为完整链 —— 匹配 → 策略链(E4,401/429/头已接)→executeEndpointTarget(E5 模块)→ 响应映射;cacheTtl计算头应用到真实执行结果上(E4 落地时如何暴露以其模块文档为准);dispatch()的 resolver;单租户直取本 kernel 服务,多租户路径如超出小单范围,如实报告并留给 E8 前置);dispatcher-plugin.endpoint-fallback.integration.test.ts):命中执行(object_operation + flow 各一)、策略拒绝(401/429)短路不执行、未命中/前缀外仍逐字节不变;* /apps/**行注记更新:「EXECUTION IS NOT WIRED」改为如实描述已接线状态(仍注明 publish 门未翻转,结构性不可达);@objectstack/runtimeminor,仍零现网行为变更)。约束
执行器车道程序卡(
session_01EYGdmvWP1ieZSLqvAW6uyd按序派发),其它车道请勿认领;词表与 spec 零触碰;E6(#5093)与 E7(#5111)的 Blocked-by 链随本单顺移(E6 实际前置 = 本单)。关联:#5091、#5092、#5090(seam)、#5040 设计 §3/§5。