Surfaced while reviewing smugglr PR #308, which reasons about atomic from the
consumer side and got two related things almost right. Recording the asymmetry
here; NOT proposing a v0.1 change.
The two halves
Atomicity is unobservable on success. S6.2's batch success envelope carries no
atomicity field, and S9 defines no atomicity header. A 200 is shape-identical
whether or not the server executed the batch in a transaction. A client that sent
atomic: true can never confirm the MUST at S4.2 was honored.
Declining is not portable. S10.1 item 5 qualifies the obligation with "when not
rejected," but the only rejection clause in S4.2 is statement-count overflow to
413, and the S7 table has no code meaning "atomicity unavailable." A server that
cannot transact may reject with a vendor code (vendor:atomic_not_supported),
which is conforming -- but S7 tells clients to treat unknown codes as the nearest
registered code by HTTP status family, so the signal collapses to
bad_request/sql_error semantics at the client. There is a conforming way to
decline and no portable way to be understood doing it.
Why v0.1 changes nothing
Consumer count for this friction is one (smugglr's migrate), and that consumer's
correct design does not need either capability: it designs as if no transaction
exists, precisely because presence is unobservable. Adding a registered code or a
response field to serve a consumer that does not need it grows permanent surface
for no behavior change. The spec is a future-compat anchor; every registered code
is forever.
The honest statement of the current contract is: atomic: true is a request the
server MUST honor and the client MUST NOT verify. That is a coherent contract
for a v0.1 transport. It is only a defect if a consumer's correctness comes to
depend on confirmation.
What would reopen it
- A second independent consumer needing to branch on whether atomicity held.
- A server implementation that wants to advertise non-support rather than
fail requests opaquely.
Candidate shapes for that day, recorded so the design is not re-derived:
- A registered
not_supported code (400 or 501) with error.message naming the
unsupported feature. Cheapest; declines loudly, still says nothing on success.
- An
atomic echo field in the S6.2 batch envelope ({"results": [...], "atomic": true}) -- a positive success-path signal, additive, minor-version
bump per S11.
- Capability advertisement (a
GET/OPTIONS capabilities document). Largest
surface, and it invites the negotiation S9 deliberately does not have.
Preference if forced today: (2), because the missing half is the success path, and
an echo is checkable by a client that cares and ignorable by one that does not.
Filed by the platform seat. Deliberately open and deliberately unscheduled.
Surfaced while reviewing smugglr PR #308, which reasons about
atomicfrom theconsumer side and got two related things almost right. Recording the asymmetry
here; NOT proposing a v0.1 change.
The two halves
Atomicity is unobservable on success. S6.2's batch success envelope carries no
atomicity field, and S9 defines no atomicity header. A
200is shape-identicalwhether or not the server executed the batch in a transaction. A client that sent
atomic: truecan never confirm theMUSTat S4.2 was honored.Declining is not portable. S10.1 item 5 qualifies the obligation with "when not
rejected," but the only rejection clause in S4.2 is statement-count overflow to
413, and the S7 table has no code meaning "atomicity unavailable." A server thatcannot transact may reject with a vendor code (
vendor:atomic_not_supported),which is conforming -- but S7 tells clients to treat unknown codes as the nearest
registered code by HTTP status family, so the signal collapses to
bad_request/sql_errorsemantics at the client. There is a conforming way todecline and no portable way to be understood doing it.
Why v0.1 changes nothing
Consumer count for this friction is one (smugglr's migrate), and that consumer's
correct design does not need either capability: it designs as if no transaction
exists, precisely because presence is unobservable. Adding a registered code or a
response field to serve a consumer that does not need it grows permanent surface
for no behavior change. The spec is a future-compat anchor; every registered code
is forever.
The honest statement of the current contract is:
atomic: trueis a request theserver MUST honor and the client MUST NOT verify. That is a coherent contract
for a v0.1 transport. It is only a defect if a consumer's correctness comes to
depend on confirmation.
What would reopen it
fail requests opaquely.
Candidate shapes for that day, recorded so the design is not re-derived:
not_supportedcode (400 or 501) witherror.messagenaming theunsupported feature. Cheapest; declines loudly, still says nothing on success.
atomicecho field in the S6.2 batch envelope ({"results": [...], "atomic": true}) -- a positive success-path signal, additive, minor-versionbump per S11.
GET/OPTIONScapabilities document). Largestsurface, and it invites the negotiation S9 deliberately does not have.
Preference if forced today: (2), because the missing half is the success path, and
an echo is checkable by a client that cares and ignorable by one that does not.
Filed by the platform seat. Deliberately open and deliberately unscheduled.