feat(runtime): 端点执行目标委派 —— endpoint-executor 纯模块(#5040 E5) - #5136
Merged
Conversation
命中的声明式 `apis:` 端点按 `type` 委派到既有执行管线,零新执行语义 (#5040 §4 裁决:声明式端点是既有管线的稳定 URL 别名 + 策略层,不是第二 套执行方言)。 - `object_operation` → `action-execution.callData`,五个操作的参数形状逐条 对齐 `/data`(注释里逐行标注对照的 `domains/data.ts` 行号);记录 id 取 `query.id`(词表未定义路径模板,不发明);`object` 只来自声明;身份信封 在五个操作上一律透传(#4936 摘除的死代码正是丢了这个参数)。 - `flow` → `IAutomationService.execute(target, buildAutomationContext(...))`, 复用 `/automation` 触发路由同一个上下文构造函数(该函数因此导出), 身份信封与 `{recordId, objectName, params}` 翻译一并继承(#3760/#1888); 槽空或自称非 handler → 501 + discovery 同款处方句(ADR-0076 D12)。 - `script` / `proxy` 与缺 `objectParams` 的 `object_operation` → 结构化 501 NOT_IMPLEMENTED(带处方),不支持子集只列一处供 E7 publish 门照读。 - 失败走既有错误包络:状态优先级与 details 组装照抄 `errorFromThrown`, 5xx 过 `looksLikeInternalErrorLeak` 消毒;新模块入 error-envelope 源码 扫描名单。 模块为 (request, match, deps) 的纯函数,内部零查找;调度步接线是随后的小型 单(与 E4 #5091 一并落地后),叠加 publish 硬拒 → 结构性不可达,现网零变更。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYGdmvWP1ieZSLqvAW6uyd
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 21 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
August 4, 2026 06:00
os-zhuang
enabled auto-merge
August 4, 2026 06:00
This was referenced Aug 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5092
Part of #5040(E 系列第 5 单);Blocked-by 已满足:E2
ecc61ab、E32649ccb均在 main。调度步(
api-endpoint-step.ts)命中后仍然答 501,本 PR 一行都没碰它。把 501 分支换成「策略 → 执行」链是随后的小型接线单,在本单与 #5091(E4,策略键)两条 R3 PR 都合入 main 之后落地 —— 两单按 #4604 声明了互斥文件面并行开发,接线做成一次小改动比让两个 PR 争同几行更好审。叠加 publish 对非空
apis:的硬拒(E7 前不撤),本模块结构性不可达:没有任何部署能触达它,现网行为零变更。测试按 #5040 §5 的规定用 stub 直接驱动模块。做了什么
新增纯模块
packages/runtime/src/endpoint-executor.ts。它遵守 #5040 §4 的唯一裁决:声明式端点 = 既有管线的「稳定 URL 别名 + 策略层」,零新执行语义;同一操作经声明端点与经内建路由必须给同样的答案。1.
buildEndpointExecutionContext(...)—— 请求上下文构造从兜底请求形状(
method/path/query/headers/body/remoteAddress,E3 的 seam 已填 body 与 remoteAddress)+ApiEndpointMatch+ 显式传入的服务依赖,投影出一个执行上下文。query/headers/body原样直通(规整化会在管线自己的入参处理前面再放一份更弱的拷贝);顺带构造HttpProtocolContext({ request, environmentId, dataDriver, executionContext }),因为buildAutomationContext本来就吃这个对象 —— 喂它同一个形状,而不是一个长得像的副本。match.params恒{}(词表无路径模板语法),携带但不用于取记录 id。2.
executeEndpointTarget(...)—— 按 type 委派object_operation→callData,五个操作的参数形状逐条对齐/data(注释里标了对照行号,可逐条核):find('query', { object, query: {…query} })domains/data.ts:119get('get', { object, id, select?, expand? })domains/data.ts:87(只放行 select/expand,防参数污染)create('create', { object, data: body })domains/data.ts:126(答 201,同 POST /data/:object)update('update', { object, id, data: body })domains/data.ts:95delete('delete', { object, id })domains/data.ts:103query.id(17.x 立项:建设声明式 ApiEndpoint 执行器(挂载 + matchEndpoint + authRequired/cacheTtl/inputMapping/outputMapping 逐键接线) #5040 §2)——/data从路径段取,而声明式端点没有表达路径段的词表,执行器不发明一套。缺?id=→ 400VALIDATION_FAILED+fields[](复用validationFailure),不是 500;?id=重复出现直接拒,不静默挑一个。object只来自objectParams.object,请求改不动它(/data的镜像缺陷见 全仓扫查"body 展开在受信任值之后":runtime 的 /data/:object/query 也中了,其余 8 处已核实无问题 #3946)。executionContext/dataDriver/environmentId在五个操作上一律透传,五个操作各有一条测试钉住 —— 声明式apis:(ApiEndpoint)入站面全链路零执行:元数据装载成功、路由从未挂载、matchEndpoint全仓无实现 #4936 摘除的死代码正是丢了这个参数,真跑起来会以 system 身份绕过 RLS。flow→automationService.execute(target, buildAutomationContext(body, ctx))。buildAutomationContext从domains/automation.ts导出复用(设计 §4 明确要求;E5 文件面本就含这一处):{recordId, objectName, params}翻译 + 完整身份信封转发一并继承,runAs:'user'的流程不会 fail-closed 被拒(#3760)或以他人身份运行(#1888)。槽为空 / 自称非 handler(handlerReady:false)/ 无execute→ 501,携带 discovery 同款处方句(ADR-0076 D12、domains/unavailable.ts);degraded占位者照常服务。3. 不支持子集 —— 结构化 501,不猜语义
script/proxy,以及缺objectParams.object|operation的object_operation、target为空的flow:一律 501 NOT_IMPLEMENTED + 处方。理由按 #5040 §7-3:automation 契约的execute注释虽提「flow or script」,但仓内没有任何证据表明 script 目标经它可达;proxy是全新出网面(SSRF / 出口策略),必须单独安全裁决。这个「不支持子集」在
planEndpointTarget里只列一处,E7 的 publish 门可以直接照着这份清单写,不必另行复述。4. 错误映射 —— 全走既有包络
endpointErrorAnswer是HttpDispatcher.errorFromThrown(http-dispatcher.ts:530)在本模块答案类型上的重述:同样的状态优先级(.status→.statusCode→ 校验失败 400 → 兜底 500)、同样的details组装(code/issues/fields[]最后放,让VALIDATION_FAILED对仅凭name匹配的错误也生效)、同样的 5xxlooksLikeInternalErrorLeak消毒(#3867/#3918)。零新包络形状、零新错误码词表。新模块已加入error-envelope.conformance.test.ts的源码扫描名单(与 #5091 加的endpoint-policy.ts是不同行,git 可无冲突合并)。需要复核者留意的两处「设计文档内部打架」
设计 §4 同时写了两句相互冲突的话,我按更强、带测试的那句(「与
/data同请求同身份逐字节同结果」)取舍,并在此显式标出,请维护者在 E7/E8 验收时确认:success(result.records, {total})」,但同段红线要求与/data逐字节一致,而/data是success(result)(整个FindDataResponse)。本 PR 取success(result)—— 重塑一遍会造出第二种方言,正是同段裁决要避免的。get未命中:/data对callData('get')返回null的情况答 200 +data: null。本 PR 照抄,没有发明一个 404 —— 在消费者侧发明语义正是 contract-first 禁止的。若产品要求集成面上 404,那是/data与端点面一起改的决定,应单独立卡。另:
create答 201(同/dataPOST),其余 200。范围外(留给后续单)
inputMapping/outputMapping(设计 §3.4 的api-mapping.ts):设计总表把它列在 E5 行,但本单派发的文件面只含endpoint-executor.ts。本 PR 未实现映射;E7 翻转前必须补一单,否则两个键会处于「声明合法、执行忽略」的中间态。已在报告中标出。验证
新增
endpoint-executor.test.ts49 例:每个 target 的委派调用形状(逐个参数断言)、成功映射、各失败类映射(404 / 403 statusCode / ValidationError→400+fields / 500 兜底 / 5xx 消毒 / 4xx 不消毒 / 生产者自带 code)、不支持类型判定、上下文构造(headers/query/body 直通、params{}、匿名不伪造身份)。Changeset:
.changeset/endpoint-execution-targets.md(@objectstack/runtimeminor)。未触碰content/docs/releases/。🤖 Generated with Claude Code
https://claude.ai/code/session_01EYGdmvWP1ieZSLqvAW6uyd
Generated by Claude Code