You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
tracking: droppedFields write-observability is asymmetric across the Virtual Data Engine RPC boundary (update best-effort, create surfaces) #3476
droppedFields (write-observability for LEGALLY-stripped fields — readonly#2948 / readonlyWhen#3042 / #3043 create ingress) reaches the caller via two different mechanisms with different reach:
create side — the 安全/设计:静态 readonly 的 INSERT 豁免让审批/状态字段可在创建时被直接播种(比 #3003 少一步) #3043 static-readonly strip is computed at the protocol layer (stripReadonlyForInsert + a before/after payload diff in metadata-protocol), so it surfaces even when the data engine is remote (Virtual Data Engine / RPC). Applies to createData, createManyData, insertManyData, and batch create rows.
update side — the readonly/readonlyWhen strips happen inside the engine, reported via the in-process onFieldsDropped listener (feat(automation): update_record/create_record 步骤对被静默剥离的写入字段挂 warning(#3407) #3413). That callback does not cross the RPC boundary, so for a remote engine the update-side droppedFields is best-effort / absent. Applies to updateData, updateManyData, and batch update/upsert rows.
#3468 extended both channels to the bulk paths, so bulk now inherits the exact same asymmetry the single-write path already had (acknowledged in #3413).
Why it matters
A cross-process deployment (Virtual Data Engine) gets reliable drop reporting on creates but silent success on updates — the very silent-success class #3407 set out to remove, re-appearing only at the process seam.
Options to consider
Carry onFieldsDropped events across the RPC envelope (add a droppedFields field to the engine's remote write-response contract) so the remote engine reports its own strips.
Recompute the update strip at the protocol layer via a before/after diff (as the create side does) — costs an extra read to know the pre-write values.
Document the boundary as a known limitation and leave update-side remote reporting best-effort.
No runtime bug today (single-process/ObjectQL deployments are fully covered); this tracks closing the remote gap.
Closing after verification (2026-07-25): the boundary this issue guards does not exist at runtime.
`DataEngineRequestSchema` ("Virtual ObjectQL", `packages/spec/src/data/data-engine.zod.ts` §9) defines request schemas only — there is no response schema at all.
Zero runtime consumers repo-wide (cloud included): no HTTP endpoint accepts these requests, and no remote proxy implements `IDataEngine`. The only implementation is the in-process ObjectQL engine (`packages/objectql/src/engine.ts`).
Design constraint to carry forward if/when a VDE is actually implemented — treat this issue as an acceptance criterion for that work:
The write-path RPC response contract MUST carry `droppedFields` (option 1 here), so the remote engine reports its own strips.
Option 2 (recomputing update strips at the protocol layer via a pre/post diff) should not be built even then: it costs a pre-read per update and duplicates `readonlyWhen` predicate evaluation outside the engine — a permanent two-implementation drift tax.
Option 3 (document the limitation) is already done: the schema comment on `DroppedFieldsEventSchema` states the listener cannot cross the RPC boundary.
Split out from #3455 / #3468 (design note #3413).
The asymmetry
droppedFields(write-observability for LEGALLY-stripped fields —readonly#2948 /readonlyWhen#3042 / #3043 create ingress) reaches the caller via two different mechanisms with different reach:readonlystrip is computed at the protocol layer (stripReadonlyForInsert+ a before/after payload diff inmetadata-protocol), so it surfaces even when the data engine is remote (Virtual Data Engine / RPC). Applies tocreateData,createManyData,insertManyData, and batchcreaterows.readonly/readonlyWhenstrips happen inside the engine, reported via the in-processonFieldsDroppedlistener (feat(automation): update_record/create_record 步骤对被静默剥离的写入字段挂 warning(#3407) #3413). That callback does not cross the RPC boundary, so for a remote engine the update-sidedroppedFieldsis best-effort / absent. Applies toupdateData,updateManyData, and batchupdate/upsertrows.#3468 extended both channels to the bulk paths, so bulk now inherits the exact same asymmetry the single-write path already had (acknowledged in #3413).
Why it matters
A cross-process deployment (Virtual Data Engine) gets reliable drop reporting on creates but silent success on updates — the very silent-success class #3407 set out to remove, re-appearing only at the process seam.
Options to consider
onFieldsDroppedevents across the RPC envelope (add adroppedFieldsfield to the engine's remote write-response contract) so the remote engine reports its own strips.No runtime bug today (single-process/ObjectQL deployments are fully covered); this tracks closing the remote gap.
Refs: #3455, #3468, #3413, #3407.