Repository navigation
Closed
Labels
bugSomething isn't workingSomething isn't workingdomain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopReady for the PM dispatch looptarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GARelease blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA
Description
发现于 #5112(#5040 E8 收官验收)的真实 boot 探针,不在该单文件面内,按 Prime Directive #10 单独立项。
事实(showcase 真实 boot,objectstack dev --fresh,47 plugins)
通过 Studio 的元数据写入口写一条 api 条目 —— 注意这是匿名且未计量的形状(ADR-0121 D6 明令禁止的那一种):
PUT /api/v1/meta/api/e8_backdoor
{"name":"e8_backdoor","path":"/api/v1/apps/showcase/backdoor","method":"GET",
"type":"object_operation","target":"showcase_task",
"objectParams":{"object":"showcase_task","operation":"find"},"authRequired":false}
→ HTTP/1.1 200 OK
{"success":true,"version":"sha256:9ad721f4...","seq":1,"state":"active",
"message":"Saved customization overlay (env-wide, state=active) — type=api ..."}
写入成功。随后:
GET /api/v1/apps/showcase/backdoor (匿名) → 404 {"error":"Not found"}
GET /api/v1/apps/showcase/backdoor (已鉴权) → 404 {"error":"Not found"}
GET /api/v1/meta/api → 三条,含
- e8_backdoor GET /api/v1/apps/showcase/backdoor authRequired=False
GET /api/v1/openapi.json → paths 含 /api/v1/apps/showcase/backdoor:
{"get":{"operationId":"e8_backdoor","responses":{"200":{"description":"Success"}},"security":[]}}
路由 404,而两个机器可读面都在宣告它存在 —— 且 OpenAPI 用 security: [] 明确把它描述成「不需要凭据」的公开端点。
为什么会这样(不是 E7b 的门在挡)
两边读的是两个不同的库:
IMetadataService.matchEndpoint→EndpointMatcher→MetadataManager.listForIndex('api'),只读 manager 自己的registry+ 已注册 loader。dev/serve 的 manager 上 loaders 是["filesystem","memory"],sys_metadata行根本不在其中(实测:registry.get('api')为 undefined,list('api')长度 0,而同一时刻/meta/api返回 2 条)。/meta/:type与/openapi.json(17.x 立项:建设声明式 ApiEndpoint 执行器(挂载 + matchEndpoint + authRequired/cacheTtl/inputMapping/outputMapping 逐键接线) #5040 E6 的 enrichment)都走protocol.getMetaItems,读的是 ObjectQL SchemaRegistry +sys_metadata。
所以这条路由死掉不是因为 #5189/#5203 的装载期门把它拒了 —— 那道门压根没被走到(dev 日志里没有 [EndpointMatcher] ... EXCLUDED 那行)。E7b 的门依然正确且必要;这里是它下面还有一层看不见。
影响的两个方向
- 面在说谎(本条的主症):
/openapi.json是 SDK / codegen / AI 客户端直接生成代码的契约面(Route & surface ownership 第 4 条、ADR-0076 D12)。一个被宣告为匿名可达、实际 404 的端点,会传播进所有基于它构建的东西。 - 反方向同样成立:一条合法的、本应服务的端点如果是通过 Studio / 运行时写入(而非 stack artifact)落库的,匹配器同样看不见 —— 作者被告知 "Saved",面上也能看到,唯独请求 404。当前净行为是 fail-closed(安全),但「声明了却不生效」正是 声明式
apis:(ApiEndpoint)入站面全链路零执行:元数据装载成功、路由从未挂载、matchEndpoint全仓无实现 #4936 这条线一直在还的债。
建议的判断轴(不预设结论)
- 要么让
matchEndpoint的取数与getMetaItems收敛到同一个源(一条路由一个所有者的元数据版本); - 要么让两个面只宣告匹配器实际会服务的集合(enrichment 与
/meta/api走匹配器的索引); - 要么在写入口就拒绝一条永远不会被服务的
api条目(与 MetadataManager.publishPackage 不经 E7 端点门 —— ADR-0121 D6「匿名须限流」在 Studio 发布路径上不成立 #5189 的 publish 门同侧)。
三条的长期代价不同,请维护者裁决 —— 中间那条最省,但它把「面不说谎」变成了「面自己去问匹配器」,是唯一不引入第二真相源的形状。
复现
pnpm dev:showcase -- --fresh -p 39720 --seed-admin
# 登录取 token,然后照上面三条 curl
关联:#5040(执行器立项)、#5112(E8 验收,发现于此)、#5189/#5203(E7b 兜底门)、ADR-0076 §1/§4、ADR-0121 D6。
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingdomain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopReady for the PM dispatch looptarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GARelease blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA
Activity
baozhoutao commentedon Aug 5, 2026
分诊补记(cli 车道 PM,
session_01VkPSGsX9o17MsGv3Lbxu2w,PM 循环第 1 轮):本轮暂缓,挂pm:blocked。Blocked-by: #520616:04Z 登记要求的「派前与 B 包属主对表」已做,结论:
api不在 metadata 类型注册表里 —— Studio 直写路径完全不校验端点,publishPackageDrafts 也没有 E7 门 #5206(engine 车道,pm:dispatched在飞)与本单同一领地:「api不在 metadata 类型注册表 —— Studio 直写路径完全不校验端点,publishPackageDrafts 没有 E7 门」,其 spec 拆单 [spec]api补进 DEFAULT_METADATA_TYPE_REGISTRY 与 BUILTIN_METADATA_TYPE_SCHEMAS(#5206 第 1 步,拆单) #5271 的 PR 仍在落地链上。api不在 metadata 类型注册表里 —— Studio 直写路径完全不校验端点,publishPackageDrafts 也没有 E7 门 #5206 落地后,本单复现用的写入口(匿名未计量api条目 PUT 成功)大概率被 E7 门 / 注册表校验拒收 —— 本单前提的「写入成功」半边会实质改变,而「匹配器与两个面读不同库」的核心断链是否仍可达、以何种形状可达,须在其后重核。saveMetaItem的 direct-active 写入是api的第三条门外通路 —— 命名空间门(ADR-0121 D1/D2)与去重门在这条路上无人跑 #5311(saveMetaItem direct-active 第三条门外通路)与本单相邻,重核时一并对照。解锁条件:#5206 关闭(其 PR 合入 main)后,重核本单前提(重跑 body 里的三条 curl 探针),再按当时事实决定派发形状 —— 届时三个方向(收敛取数源 / 面问匹配器 / 写入口拒绝)里「写入口拒绝」可能已被 #5206 部分兑现。
另:与本单文件面相交的 #5155(dispatcher 实例字段串租户)本轮已先行派发 —— 其 dev 已被明确告知⛔不动
matchEndpoint取数逻辑,本单裁决面不受污染。Generated by Claude Code
baozhoutao commentedon Aug 5, 2026
解锁裁定 + 认领(cli 车道 PM,
session_016FNvXhtSdnEGEfLEsMmvxh,2026-08-05 13:2xZ):摘pm:blocked,与 #5206 解耦派发。解耦理由(留否决窗口):① #5206 认领已 24h 无分支无 PR,stale-claim 问询(12:0xZ)1h+ 无回应,v17 窗口不应无限等一个停滞认领;② 两单文件面不相交(#5206 落 spec kernel 注册表 + metadata-protocol,本单落 runtime/rest 的取数与宣告面),原阻塞理由是「复现面的写入半边会变」而非文件冲突 —— 该风险由派发词内的前提重核(重跑 body 三条 curl 探针)吸收:探针若显示写入口已被拒,核心断链(匹配器与两面读不同库)换合法写入路径复测即可,缺陷本体不消失。#5206 自身的认领不动,问询静默窗照走。
方向裁定(两轴,留否决窗口):取中间条 —— 两个面只宣告匹配器实际会服务的集合(
/meta/api与/openapi.json的 enrichment 改为经匹配器索引取数)。判据:issue 自述它是「唯一不引入第二真相源的形状」;恢复的是已成文不变量(Route & surface ownership §4、ADR-0076 D12:契约面不得宣告不会被服务的端点),且不封死另两条路 —— 收敛取数源(方向一)是更大的架构统一,留作 engine/维护者的 appetite 决策另行立项;写入口拒绝(方向三)是 #5206 的领地不侵入。防 AI 轴:codegen/AI 客户端直接消费/openapi.json,「security: [] 的 404 端点」会传播进所有生成物 —— 面必须说真话。维护者若属意方向一为 v17 形状,请否决,届时转 needs-user-decision。认领:PM 循环第 7 轮(cli 车道,v17 优先项)
会话:
session_016FNvXhtSdnEGEfLEsMmvxh分支:
claude/issue-5224-surfaces-match-matcherWorktree:
objectstack-issue-5224域:
domain:cli文件面:
packages/rest/src/**(/meta/:type 与 openapi enrichment 的取数)+packages/runtime/src/**(仅读取匹配器索引的接缝,⛔ 不动matchEndpoint取数逻辑本身)+ 对应测试。与在队列 #5464(rest-server 错误路径)相邻同包 —— 须待 #5464 MERGED 后切树;与 #5448/#5462 不同文件。Generated by Claude Code
baozhoutao commentedon Aug 5, 2026
验收(cli 车道 PM,
session_016FNvXhtSdnEGEfLEsMmvxh):ACCEPT → PR #5487。v17 契约窗口项闭环。api已入注册表且allowRuntimeCreate: true—— 运行时创建是被声明允许的),据此不换路径复测的判断成立。served-endpoints.ts逐条问matchEndpoint(既有契约方法,零新接缝发明),两面只宣告会被服务的集合;outage 上抛不塌空集;略去项聚合一行 error 点名;⛔ 未动 matcher 取数、未动写入口、未动 runtime —— 三条边界全部遵守。?preview=draft与单条读不过滤的理由成立(作者面 ≠ 契约面)。getService<IMetadataService>),非豁免。allowRuntimeCreate与匹配器盲区的矛盾本体已按裁定预留的方向一立项api注册表条目声明 allowRuntimeCreate: true,但运行时创建的端点匹配器永远看不见 —— 声明的能力运行时不兑现(真实 boot 实测) #5488,那才是该修的东西。B 的低成本实现路径已记录,维护者属意可另开小单,否决窗口照旧。api注册表条目声明 allowRuntimeCreate: true,但运行时创建的端点匹配器永远看不见 —— 声明的能力运行时不兑现(真实 boot 实测) #5488(方向一立项)、/meta/:type上一个未分类的服务端故障被报成 HTTP 400 —— handleRouteError 的兜底把 outage 说成客户端错误 #5489(finding,sendError 的显式状态直通覆盖 400–599,5xx 的原始驱动报错绕过全部泄漏启发式直达客户端(metadata-protocol 有活体产出方) #5437 领地的 status 侧)—— 按新协调模型交分诊座位定级,本车道不代标。Generated by Claude Code
fix(rest): 两个端点契约面只宣告匹配器实际会服务的集合 (objectstack-ai#5224) (objectstack-a…
fix(examples): the three shipped examples declare @objectstack/servic…
fix(rest, runtime): the dispatcher's /meta reads answer what RestServ…