Skip to content

api 不在 metadata 类型注册表里 —— Studio 直写路径完全不校验端点,publishPackageDrafts 也没有 E7 门 #5206

Description

@os-zhuang

越范围发现,记录于 #5189(E7b,PR #5203)实现期,不在该 PR 内修(#5189 的文件面声明为 packages/metadata + packages/spec/src/api/index.ts)。

事实(两条,同一处出水口)

#5189 的正文推断:Studio 写接口对 api 条目「按 ApiEndpointSchema 校验、但不过 E7 的门」。读代码后实情更弱一层:

1. api 根本不在类型注册表里,所以直写路径一道校验都不跑。

  • packages/spec/src/kernel/metadata-plugin.zod.tsDEFAULT_METADATA_TYPE_REGISTRY没有 { type: 'api', … } 条目;
  • packages/spec/src/kernel/metadata-type-schemas.tsBUILTIN_METADATA_TYPE_SCHEMAS没有 api: ApiEndpointSchema;
  • 于是 packages/metadata-protocol/src/protocol.tssaveMetaItemresolveOverlaySchema('api', …)getMetadataTypeSchema('api') 返回 undefined,落进它自己文档写明的那条分支:「未注册 schema 的类型不经校验直接落库」。

也就是说 PUT /meta/api/{name} 可以把任意 JSON 存成一条 api 条目。同时,因为类型不在注册表里,getMetaTypes() 也枚举不到它 —— Studio 的 metadata-admin 既不显示这个类型,也不为它渲染表单。这是同一个缺失的两面。

2. publishPackageDrafts(Studio「全部发布」的真实入径)没有端点门。

protocol.publishPackageDrafts(ADR-0033 / ADR-0067 D2)在提升 draft 前只跑了对象命名空间前缀检查(validateObjectNamespacePrefix,仅 d.type === 'object')。api 类型的 draft 直接提升为 active,不经 E7 的任何一道门 —— 与 #5189MetadataManager.publishPackage 上修掉的是同一形状,另一条路

影响

安全后果已被 #5189 的第二层兜住。 PR #5203 在匹配器装载期(buildEndpointIndex)对每条存量条目重跑免身份门(不支持子集 / 映射 / policy 含 D6),未过门者被排除出索引并 error 点名。所以经本路径写入的「匿名 + 零配额」端点不会被服务,它答 404 + 一条响亮日志。

因此本单剩下的是两个非安全缺口,但都是本程序在消灭的形状:

建议(不预判)

一处修,两步:

  1. api 补上 DEFAULT_METADATA_TYPE_REGISTRY 条目与 BUILTIN_METADATA_TYPE_SCHEMAS['api'] = ApiEndpointSchema,让 saveMetaItem 的既有 422 路径自动生效;
  2. publishPackageDrafts 里对 api 类型 draft 调用 validateApiEndpointDeclarations —— PR fix(metadata,spec): publish 门兜底 —— publishPackage 接门 + 匹配器装载期拒绝(#5040 E7b) #5203 已把它从 @objectstack/spec/api 导出,命名空间取该 package 已经读到的 pkgNamespace(那段代码就在同一函数里,this.engine?.registry?.getPackage?.(…)?.manifest?.namespace),所以这条路身份,可以跑全量门,不像 publishPackage 需要调用方传入。

判据仍然只有一份(E7 的门函数),不产生第二套。

注意第 1 步不是纯加性:给一个此前不校验的类型接上 schema,会让既有的越界存量行在下次写入时被 422 拒绝。是否需要一次性的存量体检 / 宽限,留给裁决。

前置

PR #5203(#5189)落 main —— 门函数的公共导出与装载期兜底都在其中。

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions