背景
#3448 (closes #3431 )已接通单条 写路径的字段剥离观测通道:updateData 转发引擎的 onFieldsDropped(readonly #2948 / readonlyWhen #3042 ),createData 通过 payload 差集 surface #3043 入口剥离;两者在协议结果上附带可选 droppedFields,REST 的 PATCH/POST 输出 X-ObjectStack-Dropped-Fields 响应头并在 body 保留结构化列表(状态码不变)。
本 issue 跟踪 #3431 「设计待拍板 D2:波及面」里有意延后 的剩余项。
待办
bulk update(updateManyData)—— 真实缺口。 它逐行 engine.update(object, record.data, { where: { id } }),未挂 onFieldsDropped ,同一批 readonly/readonlyWhen 剥离照样静默发生。接法:逐行挂 collector,把掉的字段塞进该行结果;给 BatchOperationResultSchema(packages/spec/src/api/batch.zod.ts)加可选 droppedFields。
- 顺带:updateManyData 当前也不透传 context (独立的既存小问题,可一并修)。
bulk create(createManyData / batchData / insertManyData)。 走同一个 stripReadonlyForInsert 入口(安全/设计:静态 readonly 的 INSERT 豁免让审批/状态字段可在创建时被直接播种(比 #3003 少一步) #3043 ),逐行差集即可,per-row droppedFields。
GraphQL mutation。 写 mutation 若走同一套协议 updateData/createData,运行时现在已自动带上 droppedFields ;只差在 GraphQL schema 上暴露一个 typed 的 payload 字段。
@objectstack/client typed warnings。 给 UpdateDataResult / CreateDataResult(packages/client/src/index.ts)加 droppedFields?: DroppedFieldsEvent[],让正规 body 通道有类型。
(低优先)CORS expose。 把 X-ObjectStack-Dropped-Fields 加进 Hono 的 defaultExposeHeaders(packages/adapters/hono + packages/plugins/plugin-hono-server,注意"三处 CORS 站点 lockstep"),让跨域浏览器能读header 。价值有限——body 的 droppedFields 本就是跨域安全通道。
设计注记(#3448 里得到的经验)
参考
背景
#3448(closes #3431)已接通单条写路径的字段剥离观测通道:
updateData转发引擎的onFieldsDropped(readonly#2948 /readonlyWhen#3042),createData通过 payload 差集 surface #3043 入口剥离;两者在协议结果上附带可选droppedFields,REST 的 PATCH/POST 输出X-ObjectStack-Dropped-Fields响应头并在 body 保留结构化列表(状态码不变)。本 issue 跟踪 #3431「设计待拍板 D2:波及面」里有意延后的剩余项。
待办
updateManyData)—— 真实缺口。 它逐行engine.update(object, record.data, { where: { id } }),未挂onFieldsDropped,同一批 readonly/readonlyWhen 剥离照样静默发生。接法:逐行挂 collector,把掉的字段塞进该行结果;给BatchOperationResultSchema(packages/spec/src/api/batch.zod.ts)加可选droppedFields。- 顺带:
updateManyData当前也不透传context(独立的既存小问题,可一并修)。createManyData/batchData/insertManyData)。 走同一个stripReadonlyForInsert入口(安全/设计:静态 readonly 的 INSERT 豁免让审批/状态字段可在创建时被直接播种(比 #3003 少一步) #3043),逐行差集即可,per-rowdroppedFields。updateData/createData,运行时现在已自动带上droppedFields;只差在 GraphQL schema 上暴露一个 typed 的 payload 字段。@objectstack/clienttyped warnings。 给UpdateDataResult/CreateDataResult(packages/client/src/index.ts)加droppedFields?: DroppedFieldsEvent[],让正规 body 通道有类型。X-ObjectStack-Dropped-Fields加进 Hono 的defaultExposeHeaders(packages/adapters/hono+packages/plugins/plugin-hono-server,注意"三处 CORS 站点 lockstep"),让跨域浏览器能读header。价值有限——body 的droppedFields本就是跨域安全通道。设计注记(#3448 里得到的经验)
X-ObjectStack-Dropped-Fields,无法表达逐行剥离。→ body 的逐行droppedFields才是正规通道;header 只是单条写的便利镜像。onFieldsDropped是进程内函数,跨不了 Virtual Data Engine 的 RPC 边界,所以 update 侧的droppedFields是"进程内引擎才保证"的 best-effort(feat(automation): update_record/create_record 步骤对被静默剥离的写入字段挂 warning(#3407) #3413 契约已承认)。create 侧的 安全/设计:静态 readonly 的 INSERT 豁免让审批/状态字段可在创建时被直接播种(比 #3003 少一步) #3043 差集在协议层计算,即使远程引擎也能 surface —— 两条路径在远程部署下不对称。droppedFields(复用DroppedFieldsEventSchema),还是引入通用warnings信封以容纳未来更多写路径告警类(值被截断、类型强转、字段废弃…)?两者可共存;若预计短期会出现多类告警,值得一开始就上通用信封,省一次迁移。参考
successwhen written fields are silently stripped — no observability for dropped writes (split from #3356) #3407(流程侧同类缺口)DroppedFieldsEventSchema—packages/spec/src/data/data-engine.zod.tsupdateManyData/BatchOperationResultSchema—packages/metadata-protocol/src/protocol.ts/packages/spec/src/api/batch.zod.ts