ADR-0118 D4 fixes batchData's atomic flag (it opened no transaction — it only broke the loop, stranding every prior write as committed). Its two siblings in the same file have the same class of defect and were out of that PR's confirmed scope.
1. deleteManyData — fake-atomic (packages/metadata-protocol/src/protocol.ts:5543)
Same break-without-rollback shape as pre-fix batchData; the comment there even says "Same stop semantics as batchData". Deletes performed before the failure stay deleted while the response is titled atomic — worse than the batchData case, because a partial delete has no natural undo.
2. updateManyData — ignores atomic entirely (protocol.ts:5405-5444)
The option is accepted and never read. A caller passing atomic: true gets best-effort with no signal.
Work
Reuse the two pieces ADR-0118 D4 introduces rather than re-deriving them: the extracted per-record loop helper, and the fail-closed capability gate (engine exposes transaction and, where the driver registry is inspectable, the default driver has beginTransaction; otherwise 501 NOT_IMPLEMENTED rather than a silent best-effort run). Apply the same response contract: a rolled-back batch reports zero successes, with rows marked ROLLED_BACK: / NOT_ATTEMPTED: so a client can tell which is which.
3. Second finding — per-row result shape diverges from its own schema
The implementation pushes { id, success, error: string, record } while BatchOperationResultSchema declares { errors: ApiError[], data }. ADR-0118 D4 deliberately kept the implementation shape (changing it there would have been a silent wire-compat break riding on a bug fix). Decide the direction on purpose: widen the schema to match reality, or migrate the implementation and version the response. Whichever way, the two should stop disagreeing.
Refs: ADR-0118 D4, #4612, ADR-0049.
ADR-0118 D4 fixes
batchData'satomicflag (it opened no transaction — it only broke the loop, stranding every prior write as committed). Its two siblings in the same file have the same class of defect and were out of that PR's confirmed scope.1.
deleteManyData— fake-atomic (packages/metadata-protocol/src/protocol.ts:5543)Same break-without-rollback shape as pre-fix
batchData; the comment there even says "Same stop semantics as batchData". Deletes performed before the failure stay deleted while the response is titled atomic — worse than thebatchDatacase, because a partial delete has no natural undo.2.
updateManyData— ignoresatomicentirely (protocol.ts:5405-5444)The option is accepted and never read. A caller passing
atomic: truegets best-effort with no signal.Work
Reuse the two pieces ADR-0118 D4 introduces rather than re-deriving them: the extracted per-record loop helper, and the fail-closed capability gate (engine exposes
transactionand, where the driver registry is inspectable, the default driver hasbeginTransaction; otherwise501 NOT_IMPLEMENTEDrather than a silent best-effort run). Apply the same response contract: a rolled-back batch reports zero successes, with rows markedROLLED_BACK:/NOT_ATTEMPTED:so a client can tell which is which.3. Second finding — per-row result shape diverges from its own schema
The implementation pushes
{ id, success, error: string, record }whileBatchOperationResultSchemadeclares{ errors: ApiError[], data }. ADR-0118 D4 deliberately kept the implementation shape (changing it there would have been a silent wire-compat break riding on a bug fix). Decide the direction on purpose: widen the schema to match reality, or migrate the implementation and version the response. Whichever way, the two should stop disagreeing.Refs: ADR-0118 D4, #4612, ADR-0049.