Skip to content

[观察] autonumber builder 不注入 readonly: true —— readonly 契约的「表单不可编辑」那一半对单号字段不成立 #5628

Description

@os-zhuang

性质

观察类(finding),不是今天用户会踩到的数据缺陷#5503 / PR #5627 已在引擎侧把
type: 'autonumber' 视为隐含 readonly,非 system 调用者提交的单号在派发给任何驱动之前
就被剥离,因此数据不会再被伪造。这里记录的是同一契约的另一半没有对齐。

事实

packages/spec/src/data/field.zod.ts:779FieldSchema.readonly.describe()
这个键定义为两件事

Read-only — never editable in forms, AND server-enforced on BOTH write paths…

packages/spec/src/data/field.zod.ts:898 的 builder:

autonumber: (config: FieldInput = {}) => ({ type: 'autonumber', ...config } as const),

不注入 readonly: true。于是任何按 field.readonly 决定是否渲染成可编辑输入的
authoring / 渲染层,都会把 autonumber 字段当作可编辑字段对待 —— 而它的值现在必然被
服务端丢弃。

反查过的对照:仓内确实存在若干"计算字段"集合,但没有一个被表单层消费成 readonly ——
packages/verify/src/derive.ts:23COMPUTED
packages/plugins/plugin-audit/src/audit-writers.ts:188COMPUTED_FIELD_TYPES
(审计跳过计算列)、packages/metadata-protocol/src/protocol.ts 的 clone 剔除。
packages/spec/src/data/object.form.ts 里 autonumber 只出现在类型下拉与
autonumberFormatvisibleWhen 上,没有可编辑性的分支。

后果(低)

一个用户在表单里看到可以输入的"单号"框,填了值、提交成功,回包里的单号却是序列发的另一个
号。写入路径会在 droppedFields 里如实上报、服务端也会留下一条带补救办法的 warn
(PR #5627),但渲染器未必把 droppedFields 呈现给用户。属于 #4632 那类"第二等公民"的
交互,不是数据正确性问题。

可能的方向(未决,交由 spec 座位判断)

  1. builder 直接注入 readonly: true(issue [17.0-rc2验收] autonumber 字段可被普通调用者改写:POST 提交显式值绕过序列、PATCH 直接改号落库 —— readonly 剥离不保护 type:'autonumber' #5503 建议方向的后一种)。需要确认注入后
    stripReadonlyForInsert 入口剥离、isPreservableUnderAuditsystem !== true 分支)
    与既有的 authorable-surface / 表单基线不会被动出别的语义。
  2. 不动 builder,改为在表单/渲染契约侧把"运行时拥有的字段类型"与 readonly 并列处理,
    与 PR fix(objectql): autonumber 是运行时拥有的字段,写路径不再接受调用者提交的单号 (#5503) #5627 在引擎侧引入的 isRuntimeOwnedField 判定同源。

无论走哪条,都不替代引擎侧防线:入口剥离对 sys_ / managedBy 平台对象是豁免的,
而且绕过 DataProtocol 直接调用 engine.insert 的路径不经过入口。

发现于 #5503 的实现过程(PR #5627),按 Prime Directive #10 单独记录,未在该 PR 内扩大范围。

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions