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
Two ingresses fold their authoritative id into the payload with the losing spread order — { id, ...data } lets a payload id override the id the ingress resolved #11231
Observation from the #11142 ingress survey (PR #11229). No wrong write was measured — filed as a fragile-pattern finding, unassigned.
Two ingresses spell "fold the id I resolved into the write payload" with the id before the spread, so a caller-supplied data.id would override the id the ingress just resolved:
packages/metadata/src/loaders/database-loader.ts (~line 276, _update): this.engine.update(table, { id, ...data }) — same order, same single-source consequence.
The contrast is deliberate elsewhere and documented: the REST batch update arm spells it ql.update(op.object, { ...data, id }, …) with the comment "the operation's id AFTER the spread, so it wins" (rest-server.ts), and protocol.updateData does the same ({ ...request.data, id: request.id }, the #6479 fix). The two sites above are the same fold with the losing order.
Reachability, honestly stated: both sites' current callers appear to never put id inside data (settings rows are addressed by key/namespace; the loader is internal), so this may be unreachable today — that is why this is a finding, not a defect report with a repro. The pattern is still the exact #6479 shape one refactor away: any future caller that passes a row copy (rows carry id) silently retargets the write.
Cheap hardening if triage wants it: flip both to { ...data, id } (three characters each), matching the documented convention at the other two sites.
Observation from the #11142 ingress survey (PR #11229). No wrong write was measured — filed as a fragile-pattern finding, unassigned.
Two ingresses spell "fold the id I resolved into the write payload" with the id before the spread, so a caller-supplied
data.idwould override the id the ingress just resolved:packages/services/service-settings/src/settings-service-plugin.ts(~line 469, the engine-facadeupdatewrapper):eng.update(objectName, { id, ...data }, driverOpts)—idwas read from the caller'swhere.id, thendataspreads over it. The wrapper passes nowhereto the engine, so the A scalardata.idbeside a DIFFERENT scalarwhere.idsilently drops thewhere.idpredicate — the one unhonoured-predicate shape #11009's refusal deliberately left standing #11142 conflict refusal cannot catch a divergence: the payload is the only id source the engine sees.packages/metadata/src/loaders/database-loader.ts(~line 276,_update):this.engine.update(table, { id, ...data })— same order, same single-source consequence.The contrast is deliberate elsewhere and documented: the REST batch update arm spells it
ql.update(op.object, { ...data, id }, …)with the comment "the operation's id AFTER the spread, so it wins" (rest-server.ts), andprotocol.updateDatadoes the same ({ ...request.data, id: request.id }, the #6479 fix). The two sites above are the same fold with the losing order.Reachability, honestly stated: both sites' current callers appear to never put
idinsidedata(settings rows are addressed by key/namespace; the loader is internal), so this may be unreachable today — that is why this is a finding, not a defect report with a repro. The pattern is still the exact #6479 shape one refactor away: any future caller that passes a row copy (rows carryid) silently retargets the write.Cheap hardening if triage wants it: flip both to
{ ...data, id }(three characters each), matching the documented convention at the other two sites.Refs: #6479, #11142, PR #11229 (survey section).
Generated by Claude Code