Skip to content

meta: /meta/objects reports field metadata from the build artifact, not the registry — created_at reads readonly: false while the write path enforces read-only #4513

Description

@os-zhuang

发现于修复 #4447 时(PR #4511),与该 issue 同源但是另一处缺陷,故单独记录,未认领。

摘要

GET /api/v1/meta/objects/<object> 返回的字段元数据来自应用构建产物dist/objectstack.json),而不是运行时注册表registry.getObject())。两者已经不一致:写入路径按注册表强制 created_at 为只读,而这个机器可读面仍然声称它可写。

复现

pnpm dev -- --fresh -p <port>,showcase,admin 会话,#4447 修复之后

GET /api/v1/meta/objects/showcase_task
→ "created_at": {"label":"Created At","type":"datetime", …, "readonly": false}

但同一个字段在同一次启动里确实是只读的:

PATCH /api/v1/data/showcase_task/<id>  {"progress":42,"created_at":"1999-01-01T00:00:00Z"}
→ 200
   droppedFields: [{"object":"showcase_task","fields":["created_at"],"reason":"readonly"}]
GET  …?select=created_at,progress
→ {"created_at":"2026-06-22T00:00:00.000Z","progress":42}   ← 锚点没动

即:面说可写,引擎按只读执行。

另外注意同一响应里 updated_at / created_by / updated_by 根本不出现,只有 created_at 出现——这本身就说明这份字段表不是注册表的投影(注册表四个都有),而是构建产物里恰好被物化的那一个。

#4447 的区别

影响

AGENTS.md「Route & surface ownership」第 4 条:机器可读面不许撒谎/meta/objects 会被 SDK、代码生成、Studio 表单渲染和 AI 客户端读取:

  • 表单/Studio 会把 created_at 渲染成可编辑输入框,用户改了却静默不生效(值被 droppedFields 丢弃,UI 若不读该字段就完全无提示);
  • 代码生成/AI 作者会据此认为该字段可写,产出写它的代码;
  • 更一般地:任何构建产物与注册表存在差异的字段,这个面给出的都是产物那一侧的答案,而强制的是注册表那一侧。created_at 只是第一个被抓到的样本,不一定是唯一的。

期望

/meta/objects 投影应以运行时注册表为准(registry.getObject(),即 applySystemFields / provisionPrimary 之后的规范形状),使它与实际执行的写入契约一致。若出于性能或其他原因必须读产物,则产物必须在构建时就经过同样的规范化,并有门禁保证两者不漂移。

顺带值得查清的:构建产物里那个 created_at物化进去的(showcase 源码并未声明它,task.view.ts / dashboards / datasets 只是引用了它)。如果是「把视图引用到的字段补进对象」这类构建步骤,那它用 FieldSchema 默认值补出一个系统字段本身就该修——那会是第三处,比这个面更靠上游。

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions