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:779,FieldSchema.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:23 的 COMPUTED、
packages/plugins/plugin-audit/src/audit-writers.ts:188 的 COMPUTED_FIELD_TYPES
(审计跳过计算列)、packages/metadata-protocol/src/protocol.ts 的 clone 剔除。
packages/spec/src/data/object.form.ts 里 autonumber 只出现在类型下拉与
autonumberFormat 的 visibleWhen 上,没有可编辑性的分支。

后果(低)

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

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

  1. builder 直接注入 readonly: true(issue [17.0-rc2验收] autonumber 字段可被普通调用者改写:POST 提交显式值绕过序列、PATCH 直接改号落库 —— readonly 剥离不保护 type:'autonumber' #5503 建议方向的后一种)。需要确认注入后
    stripReadonlyForInsert 入口剥离、isPreservableUnderAudit(system !== 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 内扩大范围。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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