越范围发现,记录于 #5111 (E7 翻转)实现期,不在该 PR 内修 (#5111 的文件面声明为 packages/spec)。
事实
#5111 把 apis: 的逐端点门挂在 ObjectStackDefinitionSchema 上,覆盖五条 stack 级 parse 路径(defineStack / os validate / lint 评分 / metadata 插件 artifact 摄入 / EnvironmentArtifactSchema.metadata)。
但逐条 metadata 条目的发布路径不经过 stack schema :MetadataManager.publishPackage(packages/metadata/src/metadata-manager.ts:~840)的校验环节是逐条 this.validate(item.type, item.data),即针对该类型自身的 schema(api 条目 → ApiEndpointSchema),而不是 stack 级 parse。因此一个经 metadata.register() / metadata 写接口(Studio「全部发布」)创建的 api 条目,发布时不受 E7 任何一道门约束 。
影响(按门分)
不支持子集(script/proxy/transform/缺 objectParams)、映射路径与互撞:有运行时兜底 —— 执行链答结构化 501 并点名条目,是响亮的,不是静默的;
命名空间门(D1/D2):路径落在 apps/{ns}/ 之外的条目永远匹配不上 (isAppEndpointPath 只把该挂载下的请求交给端点步),后果是死元数据,不是安全洞;
⚠️ D6(authRequired: false 必须伴随已装配限流)没有运行时对偶 :运行时忠实执行 authRequired: false(匿名放行),rateLimit 未装配则 deriveBucketConfig 返回 null、不计量(E4 已有测试钉住这是声明即执行 的正确读法)。也就是说,经该路径发布的一条 authRequired: false 且无限流的端点,会得到一个匿名可达、零配额的执行入口 ,而 ADR-0121 D6 的原文是「publish 拒绝」。
建议(不预判,交 PM/维护者定)
packages/spec/src/api/endpoint-publish-gate.ts 里的门是纯函数(validateApiEndpointDeclarations(endpoints, { namespace })),按 stack 身份取命名空间。可选路线:
A —— publishPackage 在 api 条目上调用同一函数,命名空间取该 package 的 manifest;门的判据只此一处,不产生第二套;需要把该模块从 packages/spec/src/api/index.ts 导出(现为包内私有,E7(#5040 执行器):翻转 —— publish 硬拒收窄为「不支持子集 + 命名空间门」,声明式端点随 v17 放行执行 #5111 刻意未进公共面);
B —— 只把 D6 一条(唯一没有运行时对偶的)接进 publishPackage;面小,但「哪些门在哪条路径上成立」变成需要维护的知识,正是本程序在消灭的形状;
C —— 把 D6 也做成运行时对偶(匹配器装载期拒绝「匿名 + 未装配限流」的条目并 error 点名),与其它门同姿态:publish 是第一道门,装载是兜底。
倾向 A + C (判据单一 + 两端都不静默),但这是发布面/契约面的取舍,留给裁决。
前置
packages/spec/src/api/endpoint-publish-gate.ts 随 #5111 (PR #5188 )落地后本单才有可复用的门函数。
越范围发现,记录于 #5111(E7 翻转)实现期,不在该 PR 内修(#5111 的文件面声明为
packages/spec)。事实
#5111 把
apis:的逐端点门挂在ObjectStackDefinitionSchema上,覆盖五条 stack 级 parse 路径(defineStack/os validate/ lint 评分 / metadata 插件 artifact 摄入 /EnvironmentArtifactSchema.metadata)。但逐条 metadata 条目的发布路径不经过 stack schema:
MetadataManager.publishPackage(packages/metadata/src/metadata-manager.ts:~840)的校验环节是逐条this.validate(item.type, item.data),即针对该类型自身的 schema(api条目 →ApiEndpointSchema),而不是 stack 级 parse。因此一个经metadata.register()/ metadata 写接口(Studio「全部发布」)创建的api条目,发布时不受 E7 任何一道门约束。影响(按门分)
script/proxy/transform/缺objectParams)、映射路径与互撞:有运行时兜底 —— 执行链答结构化 501 并点名条目,是响亮的,不是静默的;apps/{ns}/之外的条目永远匹配不上(isAppEndpointPath只把该挂载下的请求交给端点步),后果是死元数据,不是安全洞;authRequired: false必须伴随已装配限流)没有运行时对偶:运行时忠实执行authRequired: false(匿名放行),rateLimit未装配则deriveBucketConfig返回null、不计量(E4 已有测试钉住这是声明即执行的正确读法)。也就是说,经该路径发布的一条authRequired: false且无限流的端点,会得到一个匿名可达、零配额的执行入口,而 ADR-0121 D6 的原文是「publish 拒绝」。建议(不预判,交 PM/维护者定)
packages/spec/src/api/endpoint-publish-gate.ts里的门是纯函数(validateApiEndpointDeclarations(endpoints, { namespace })),按 stack 身份取命名空间。可选路线:publishPackage在api条目上调用同一函数,命名空间取该 package 的 manifest;门的判据只此一处,不产生第二套;需要把该模块从packages/spec/src/api/index.ts导出(现为包内私有,E7(#5040 执行器):翻转 —— publish 硬拒收窄为「不支持子集 + 命名空间门」,声明式端点随 v17 放行执行 #5111 刻意未进公共面);publishPackage;面小,但「哪些门在哪条路径上成立」变成需要维护的知识,正是本程序在消灭的形状;倾向 A + C(判据单一 + 两端都不静默),但这是发布面/契约面的取舍,留给裁决。
前置
packages/spec/src/api/endpoint-publish-gate.ts随 #5111(PR #5188)落地后本单才有可复用的门函数。