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
Honor atomic: true on batch requests when not rejected.
"when not rejected" qualifies a MUST against a rejection the spec never defines. There is no way for a conforming server to decline atomicity:
The registered error-code table in S7 has no not_supported (or equivalent). The set is bad_request, sql_error, not_allowed, auth_error, permission_error, payload_too_large, rate_limited, internal_error. not_allowed is scoped to statement shape rejected by server policy, which does not cover refusing the atomic field.
S4.2's only rejection clause is statement-count overflow to 413 / payload_too_large.
Nothing in S6 echoes back whether the server actually ran the batch in a transaction, so a client has no positive signal either.
So a server that cannot do transactions has exactly two options, and both are non-conforming: silently lie (accept atomic: true and not honor it), or misuse an error code. A client cannot distinguish either case from an unrelated failure, and S7's "treat unknown error.code values as the closest registered code by HTTP status family" guarantees a vendor: code cannot carry the signal interoperably.
This is issue #3's exact shape -- a normative keyword gated on a condition the spec leaves undefined -- reproduced in the conformance section rather than in a field definition.
Why it is being filed now
rafters-studio/smugglr PR #308 makes this gap load-bearing. Its migrate design decision 6 ("design as if no transaction exists") now rests on the reasoning above: the spec gives a server no conforming way to decline atomicity, so atomic honoring is unobservable to a client and correctness must not depend on it. That reasoning is correct against v0.1 on both main and #9's head -- I verified it. It is also reasoning about an absence, which means closing this gap rots a downstream repo's prose. Reviewed and flagged there; the fix requested downstream is to pin v0.1 into those sentences.
The design conclusion survives either resolution below, because absence of a rejection is still an unverifiable claim of support. Only the "lie or misuse a code" sentence depends on the gap.
The two candidate resolutions
A. Drop the qualifier. Item 5 becomes "Honor atomic: true on batch requests." Unconditional, matches what S4.2:64 already says (the MUST has no escape hatch there), and matches both reference servers. A server that cannot do transactions is simply non-conforming for batch -- which is arguably already the truth S4.2 states, with item 5 accidentally weakening it.
B. Define the decline path. Register a code (not_supported, 400) and state in S4.2 that a server unable to execute a batch atomically MUST reject a request carrying atomic: true with it, rather than executing non-atomically. This makes the rejection real, makes item 5's qualifier meaningful, and gives a client a distinguishable signal -- but it is a new registered code, so per S11 it is a v0.2 additive change, not a v0.1 clarification.
Preference: A, and it is the smaller claim. v0.1's S4.2 already puts an unqualified MUST on the server; item 5's "when not rejected" is the only text in the spec that implies a negotiation exists, and no other section supports it. Removing it makes the conformance section agree with the field definition instead of quietly contradicting it. B can be considered on its own merits for v0.2 -- a real decline signal has value -- but it should not be motivated as a fix for this, because the fix for a dangling qualifier is to delete the qualifier.
Whichever lands, the check-before-writing rule from #9 applies: verify both reference servers first. Both currently honor atomic (examples/cloudflare-worker-to-d1/src/index.ts:92 via db.batch(), examples/cloudflare-durable-object/src/index.ts:124 via ctx.storage.transactionSync), so A codifies shipped behavior and neither server becomes non-conforming.
Acceptance criteria
S10.1 item 5 no longer gates a normative obligation on an undefined condition.
S4.2's atomic obligation and S10.1's conformance item state the same rule -- no reader can find a negotiation in one and not the other.
Both reference servers are checked against the resulting text before it is written, and remain conforming.
The defect
SPEC.mdS10.1 item 5 reads:"when not rejected" qualifies a
MUSTagainst a rejection the spec never defines. There is no way for a conforming server to decline atomicity:not_supported(or equivalent). The set isbad_request,sql_error,not_allowed,auth_error,permission_error,payload_too_large,rate_limited,internal_error.not_allowedis scoped to statement shape rejected by server policy, which does not cover refusing theatomicfield.413/payload_too_large.So a server that cannot do transactions has exactly two options, and both are non-conforming: silently lie (accept
atomic: trueand not honor it), or misuse an error code. A client cannot distinguish either case from an unrelated failure, and S7's "treat unknownerror.codevalues as the closest registered code by HTTP status family" guarantees avendor:code cannot carry the signal interoperably.This is issue #3's exact shape -- a normative keyword gated on a condition the spec leaves undefined -- reproduced in the conformance section rather than in a field definition.
Why it is being filed now
rafters-studio/smugglrPR #308 makes this gap load-bearing. Its migrate design decision 6 ("design as if no transaction exists") now rests on the reasoning above: the spec gives a server no conforming way to decline atomicity, soatomichonoring is unobservable to a client and correctness must not depend on it. That reasoning is correct against v0.1 on bothmainand #9's head -- I verified it. It is also reasoning about an absence, which means closing this gap rots a downstream repo's prose. Reviewed and flagged there; the fix requested downstream is to pinv0.1into those sentences.The design conclusion survives either resolution below, because absence of a rejection is still an unverifiable claim of support. Only the "lie or misuse a code" sentence depends on the gap.
The two candidate resolutions
A. Drop the qualifier. Item 5 becomes "Honor
atomic: trueon batch requests." Unconditional, matches what S4.2:64 already says (theMUSThas no escape hatch there), and matches both reference servers. A server that cannot do transactions is simply non-conforming for batch -- which is arguably already the truth S4.2 states, with item 5 accidentally weakening it.B. Define the decline path. Register a code (
not_supported,400) and state in S4.2 that a server unable to execute a batch atomically MUST reject a request carryingatomic: truewith it, rather than executing non-atomically. This makes the rejection real, makes item 5's qualifier meaningful, and gives a client a distinguishable signal -- but it is a new registered code, so per S11 it is a v0.2 additive change, not a v0.1 clarification.Preference: A, and it is the smaller claim. v0.1's S4.2 already puts an unqualified
MUSTon the server; item 5's "when not rejected" is the only text in the spec that implies a negotiation exists, and no other section supports it. Removing it makes the conformance section agree with the field definition instead of quietly contradicting it. B can be considered on its own merits for v0.2 -- a real decline signal has value -- but it should not be motivated as a fix for this, because the fix for a dangling qualifier is to delete the qualifier.Whichever lands, the check-before-writing rule from #9 applies: verify both reference servers first. Both currently honor
atomic(examples/cloudflare-worker-to-d1/src/index.ts:92viadb.batch(),examples/cloudflare-durable-object/src/index.ts:124viactx.storage.transactionSync), so A codifies shipped behavior and neither server becomes non-conforming.Acceptance criteria
atomicobligation and S10.1's conformance item state the same rule -- no reader can find a negotiation in one and not the other.conformance/README.mddoes not grant or imply a permission the spec does not issue (the P0: non-atomic batch failure has no normative behavior (forbid partial success + REQUIRE statementIndex on non-atomic + state that preceding statements persist) #1 failure mode).