<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.32 (Ruby 3.3.0) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

]>


<rfc ipr="trust200902" docName="draft-ietf-jmap-conditional-01" category="std" consensus="true" submissionType="IETF" updates="8620" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="JMAP Conditional">JMAP Conditional Set</title>

    <author initials="B." surname="Gondwana" fullname="Bron Gondwana">
      <organization>Fastmail</organization>
      <address>
        <email>brong@fastmailteam.com</email>
      </address>
    </author>

    <date year="2026" month="October" day="15"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 31?>

<t>The JMAP base protocol (<xref target="JMAP-CORE"/>) provides the Foo/set method for
creating, updating, and destroying objects.  It offers a single concurrency
control, the "ifInState" argument, which guards an entire object type: if any
object of that type has changed, the whole method is rejected.</t>

<t>This extension adds a finer, per-object conditional mechanism.  A client may
require that an individual update or destroy proceed only if the target object
still matches a set of expected property values, expressed using the JMAP
PatchObject already defined for updates.  This provides optimistic concurrency
control scoped to a single object — the equivalent of an HTTP "If-Match"
precondition — for any JMAP data type.</t>

<t>This extension also defines an optional "atomic" argument that applies an
entire Foo/set as a single unit: either every change it requests takes effect,
or none does.  Combined with the per-object precondition, this lets a client
express a multi-object change that is safe only when applied together — such as
an atomic rename that exchanges two names.</t>



    </abstract>



  </front>

  <middle>


<?line 51?>

<section anchor="introduction"><name>Introduction</name>

<t>The Foo/set method defined in <xref target="JMAP-CORE"/> is the mechanism by which clients
create, update, and destroy objects.  It provides one form of concurrency
control: the optional "ifInState" argument, which aborts the entire method if
the account's state string for that data type does not match the value the
client supplies.</t>

<t>This guard is coarse.  The state string changes whenever <em>any</em> object of that
type changes, by any client.  In a busy account — or one that receives
server-initiated changes, such as the arrival of new mail — the state can
change between a client's read and its write for reasons entirely unrelated to
the object the client is modifying.  Using "ifInState" to protect a single
update therefore leads to frequent spurious rejections and retries.</t>

<t>Clients commonly need a narrower guarantee: "apply this change only if the
specific object I read still holds the values I depend on".  This is the same
need met by the HTTP "If-Match" precondition (<xref target="HTTP-SEMANTICS"/>) and the
entity-tag model of WebDAV (<xref target="WEBDAV"/>): a conditional write scoped to a single
resource.</t>

<t>This document defines a generic, per-object conditional mechanism for Foo/set.
It introduces no new properties and no new version tokens.  Instead it reuses
the PatchObject already defined by <xref target="JMAP-CORE"/> for updates: a client states
its precondition as a PatchObject describing the values it expects the object
to currently hold, and the server performs the change only if applying that
patch would change nothing.</t>

<t>Because the mechanism is defined entirely in terms of an object's properties
and the existing PatchObject semantics, it applies uniformly to every data
type that implements Foo/set, with no per-type additions.</t>

<t>A second, related need is atomicity.  <xref target="JMAP-CORE"/> processes the creations,
updates, and destroys within a Foo/set independently: some may succeed while
others fail, and the method gives no guarantee that a set of related changes
takes effect together.  The only all-or-nothing control Core offers is
"ifInState", which — like the concurrency problem above — is scoped to the
entire object type rather than to the changes the client actually requested.
This document therefore also defines an optional "atomic" argument that commits
a Foo/set as a single unit, evaluated against the state that results from
applying all of its changes together (see <xref target="atomic"/>).</t>

<section anchor="conventions-used-in-this-document"><name>Conventions Used in This Document</name>

<t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>

<?line -18?>

<t>The terms "Id", "PatchObject", "SetError", and "Foo/set" are defined in
<xref target="JMAP-CORE"/>.  A "pointer" is a JSON Pointer as used within a PatchObject
(see <xref target="JMAP-CORE"/>, Section 5.3).</t>

</section>
</section>
<section anchor="addition-to-the-capabilities-object"><name>Addition to the Capabilities Object</name>

<section anchor="urnietfparamsjmapconditional"><name>urn:ietf:params:jmap:conditional</name>

<t>The presence of the "urn:ietf:params:jmap:conditional" property in the
"capabilities" object of the JMAP Session resource indicates support for the
conditional Foo/set behaviour defined in this document.  The value of this
property <bcp14>MUST</bcp14> be an empty object.</t>

<t>A client indicates that it wishes to use this extension by including the
capability URI in the "using" array of a request.  When a server that
advertises this capability receives a request whose "using" array includes
this URI, it <bcp14>MUST</bcp14> honour the "ifUnchangedBy" argument (<xref target="conditional-set"/>) on
every Foo/set method it implements.  It <bcp14>MUST</bcp14> also honour the "atomic" argument
(<xref target="atomic"/>): either applying the method atomically, or, if it cannot, rejecting
it with a "cannotApplyAtomically" error (<xref target="atomic"/>).  A server <bcp14>MUST NOT</bcp14> apply
the changes of a method requested with "atomic" only in part.</t>

<t>The capability is generic: it does not depend on any particular data type, and
its presence applies to all types for which the server implements Foo/set.</t>

<section anchor="capability-example"><name>Capability Example</name>

<figure><artwork><![CDATA[
"urn:ietf:params:jmap:conditional": {}
]]></artwork></figure>

</section>
</section>
</section>
<section anchor="conditional-set"><name>Conditional Foo/set</name>

<t>This document adds the following arguments to the standard Foo/set method
(<xref target="JMAP-CORE"/>, Section 5.3):</t>

<t><list style="symbols">
  <t>ifUnchangedBy: "Id[PatchObject]" (default: an empty object)  <vspace blankLines='1'/>
A map of object id to a PatchObject expressing a precondition on that
object.  For each entry, the precondition is satisfied if and only if
applying the given PatchObject to the current server-side object would
leave the object unchanged.  <vspace blankLines='1'/>
Equivalently: for every pointer in the PatchObject, the object's current
value at that pointer <bcp14>MUST</bcp14> equal the value given in the PatchObject.  A
JSON "null" value matches a property that is not present (it asserts that
removing the property would be a no-op).  Comparison uses the same
representation the server would return for that property from Foo/get.</t>
  <t>atomic: "Boolean" (default: false)  <vspace blankLines='1'/>
If true, the Foo/set is applied as a single unit: the server <bcp14>MUST</bcp14> either
commit every creation, update, and destroy the method requests, or make no
change at all.  See <xref target="atomic"/>.</t>
</list></t>

<section anchor="evaluation-rules"><name>Evaluation Rules</name>

<t><list style="numbers" type="1">
  <t>Preconditions are evaluated against the state of each object as it exists
at the start of the method, before any create, update, or destroy in the
same method is applied.</t>
  <t>Each key in "ifUnchangedBy" is the id of an object of the same type as the
method (the "Foo" of "Foo/set").  The object need not be one the method
changes.  A client <bcp14>MAY</bcp14> set a precondition on an object the method does not
change, for example its parent.  A precondition is not satisfied if its
object does not exist, or is not visible to the client.  The server then
handles it as in <xref target="effect"/>.  A creation id (an id prefixed with "#") <bcp14>MAY</bcp14>
be a key.  It references an object created by an earlier method call in the
same request (<xref target="JMAP-CORE"/>, Section 5.3).  If the creation id resolves to
an object of a different type, the server <bcp14>MUST</bcp14> reject the whole method with
an "invalidArguments" error.  This lets a client require that an object it
created earlier in the request has not changed since then.</t>
  <t>Unlike the PatchObject supplied in the "update" argument, which may only
reference properties the client is permitted to set, the PatchObject in
"ifUnchangedBy" <bcp14>MAY</bcp14> reference any property of the object, including
server-set and otherwise read-only properties (for example a content
identifier, a size, or a server-maintained change timestamp).  This allows
a client to condition a change on properties it cannot itself modify.</t>
  <t>If a pointer in an "ifUnchangedBy" PatchObject is not a valid pointer for
the object's type, or the PatchObject is otherwise malformed, the server
<bcp14>MUST</bcp14> reject the whole method with an "invalidArguments" error.</t>
  <t>The "ifUnchangedBy" and "ifInState" arguments are both method-level guards
and compose.  If both are supplied, the server checks "ifInState" first and
then the "ifUnchangedBy" preconditions; if either does not hold, the method
is rejected with a "stateMismatch" error and no change is made.</t>
</list></t>

</section>
<section anchor="effect"><name>Effect</name>

<t>If every precondition in "ifUnchangedBy" is satisfied, the method proceeds
exactly as it would without this extension.</t>

<t>If any precondition is not satisfied, the server <bcp14>MUST</bcp14> make no change — no
creation, update, or destroy in the method takes effect — and <bcp14>MUST</bcp14> reject the
whole method with a method-level "stateMismatch" error (<xref target="statemismatch"/>).
The state string for the type <bcp14>MUST</bcp14> be unchanged.</t>

<t>This is all-or-nothing at the method level, by design: a single Foo/set is
the unit of conditional application.  A client that wants changes to succeed or
fail independently of one another places them in separate method calls within
the same request, each with its own "ifUnchangedBy".</t>

</section>
<section anchor="statemismatch"><name>The "stateMismatch" error</name>

<t>A failed "ifUnchangedBy" precondition is reported using the method-level
"stateMismatch" error already defined by <xref target="JMAP-CORE"/> for a failed "ifInState"
guard.  It is returned as an "error" response in place of the Foo/set response,
so no create, update, or destroy result is returned and the client knows the
method made no change.</t>

<t>The error discloses no object data: a client that needs the current values
fetches them with Foo/get or Foo/changes before deciding how to proceed.  A
server <bcp14>MAY</bcp14> include a "description" for debugging, and <bcp14>MAY</bcp14> include:</t>

<t><list style="symbols">
  <t>failed: "Id[]"  <vspace blankLines='1'/>
The ids of the objects whose preconditions were not satisfied.  This lets a
client re-fetch only what it needs, without disclosing any values.  A server
that does not wish to distinguish which precondition failed <bcp14>MAY</bcp14> omit this
property.</t>
</list></t>

</section>
</section>
<section anchor="atomic"><name>Atomic Foo/set</name>

<t>When the "atomic" argument is true, the server <bcp14>MUST</bcp14> apply the Foo/set as a
single unit: either every creation, update, and destroy the method requests
takes effect, or none of them does.</t>

<section anchor="evaluation"><name>Evaluation</name>

<t>The server evaluates the method as though all of its changes were applied
together.  Any constraint that <xref target="JMAP-CORE"/> or a data-type extension evaluates
on the resulting object set — for example a uniqueness constraint on a name
within a parent — is checked once, against the state produced by applying all
the changes, not against any intermediate state.</t>

<t>This guarantees that a set of changes that is valid only as a whole can
succeed.  For example, exchanging two names — renaming object A to the name
currently held by B and B to the name currently held by A — collides if applied
one change at a time, but the combined result is conflict-free.  <xref target="JMAP-CORE"/>,
Section 5.3 already permits a server to accept such a change when the final
state is valid, but also permits it to process the changes sequentially and
reject one of them, possibly after committing the other.  With "atomic", the
client can rely on the server evaluating the final state, and on the changes
succeeding or failing together (see <xref target="exchange"/>).</t>

</section>
<section anchor="failure"><name>Failure</name>

<t>If any part of an atomic method fails — an invalid patch, a name collision, a
permission error, a violated constraint, or any other SetError that would place
an id in "notCreated", "notUpdated", or "notDestroyed" — the server <bcp14>MUST</bcp14> make
no change and <bcp14>MUST</bcp14> reject the whole method with a method-level "atomicFailure"
error.  The state string for the type <bcp14>MUST</bcp14> be unchanged.</t>

<t>A failed "ifUnchangedBy" precondition is reported as a "stateMismatch" error
(<xref target="statemismatch"/>) whether or not "atomic" is set; preconditions are already
all-or-nothing at the method level.  The "atomicFailure" error is specific to
the method's own creations, updates, and destroys not being committable
together.</t>

<t>The "atomicFailure" error object <bcp14>MAY</bcp14> carry "notCreated", "notUpdated", and
"notDestroyed" maps — of the same form as a Foo/set response — identifying the
ids whose processing failed and the SetError for each.  Ids that would have
succeeded are omitted; they were not committed, because the method as a whole
was rejected.  A server <bcp14>MAY</bcp14> report only the first failure it encounters.</t>

</section>
<section anchor="cannotapply"><name>Servers That Cannot Apply Atomically</name>

<t>A server that advertises this capability but cannot apply a given method
atomically — either at all, or because this particular method is beyond what it
can commit as a unit — <bcp14>MUST</bcp14> reject the method with a method-level
"cannotApplyAtomically" error and make no change.  It <bcp14>MUST NOT</bcp14> fall back to
applying the changes non-atomically.</t>

<t>A client that receives "cannotApplyAtomically" <bcp14>MAY</bcp14> retry without "atomic" if it
can tolerate partial application, or surface the failure otherwise.  A client
that does not recognise the error treats it as "serverFail" (<xref target="JMAP-CORE"/>):
since a rejected atomic method makes no change, this fallback is safe, if less
informative.</t>

</section>
</section>
<section anchor="examples"><name>Examples</name>

<section anchor="force-with-lease-on-file-content"><name>Force-with-lease on file content</name>

<t>A client last synchronised a file node "f42" with content blob "G_old".  It has
since produced new content "G_new", and wishes to replace the content only if no
other client has changed it in the meantime.  It conditions on the server-set
"blobId" (<xref target="JMAP-FILENODE"/>):</t>

<figure><artwork><![CDATA[
[[ "FileNode/set", {
  "accountId": "u1",
  "ifUnchangedBy": { "f42": { "blobId": "G_old" } },
  "update":       { "f42": { "blobId": "G_new",
                             "modified": "2026-05-01T09:30:00Z" } }
}, "0" ]]
]]></artwork></figure>

<t>If "f42" still references "G_old", the update succeeds.  If another client has
already replaced the content (so "blobId" is now, say, "G_other"), the
precondition fails and the server makes no change, returning a method-level
"stateMismatch" error:</t>

<figure><artwork><![CDATA[
[[ "error", {
  "type": "stateMismatch",
  "failed": [ "f42" ]
}, "0" ]]
]]></artwork></figure>

<t>The client fetches "f42", resolves the conflict (for instance by preserving its
own version as a separate file), and retries.</t>

</section>
<section anchor="conditional-destroy"><name>Conditional destroy</name>

<t>Destroy a message only if it has not been read on another device.  In
<xref target="JMAP-MAIL"/>, an unread message has no "$seen" keyword, so the client asserts
that "keywords/$seen" is absent:</t>

<figure><artwork><![CDATA[
[[ "Email/set", {
  "accountId": "u1",
  "ifUnchangedBy": { "M7": { "keywords/$seen": null } },
  "destroy":      [ "M7" ]
}, "0" ]]
]]></artwork></figure>

<t>If the message has since been marked "$seen", the precondition fails, the whole
method is rejected with a "stateMismatch" error, and "M7" is not deleted.</t>

</section>
<section anchor="a-condition-that-ignores-unrelated-changes"><name>A condition that ignores unrelated changes</name>

<t>Because the precondition references only the pointers the client supplies,
concurrent changes to other properties of the same object do not cause it to
fail.  Here a client removes a grantee's access, but only if that grantee
currently holds exactly the rights the client saw:</t>

<figure><artwork><![CDATA[
[[ "FileNode/set", {
  "accountId": "u1",
  "ifUnchangedBy": { "d3": { "shareWith/bob/mayRead": true } },
  "update":       { "d3": { "shareWith/bob": null } }
}, "0" ]]
]]></artwork></figure>

<t>The change applies only if Bob currently has "mayRead" of "true".  A concurrent
change to an unrelated property of "d3" (its name, or another grantee's rights)
does not trigger a "stateMismatch".</t>

</section>
<section anchor="conditioning-on-an-object-the-method-does-not-change"><name>Conditioning on an object the method does not change</name>

<t>A precondition may name an object the method is not creating, updating, or
destroying.  Here a client updates the content of file "f42", but only if it is
still in the parent directory the client last saw ("d3"), so the write does not
land in an unexpected place after a concurrent move:</t>

<figure><artwork><![CDATA[
[[ "FileNode/set", {
  "accountId": "u1",
  "ifUnchangedBy": { "f42": { "parentId": "d3" },
                     "d3":  { "name": "Reports" } },
  "update":       { "f42": { "blobId": "G_new",
                             "modified": "2026-05-01T09:30:00Z" } }
}, "0" ]]
]]></artwork></figure>

<t>If either "f42" has been reparented or "d3" has been renamed, the method is
rejected with a "stateMismatch" error and the content is not written, even
though "d3" itself is not being changed.</t>

</section>
<section anchor="whole-object-compare-and-swap"><name>Whole-object compare-and-swap</name>

<t>A data type that maintains a server-set change token can be used to require
that nothing at all has changed.  For example, a type with a server-maintained
"changed" timestamp that is updated on every modification:</t>

<figure><artwork><![CDATA[
"ifUnchangedBy": { "f42": { "changed": "2026-04-30T12:00:00Z" } }
]]></artwork></figure>

<t>Because the server updates "changed" on any modification to the object, this
asserts that the entire object is unchanged since the client last read it,
recovering the coarse "If-Match" behaviour as a special case of the general
mechanism.</t>

</section>
<section anchor="exchange"><name>Atomic exchange of two names</name>

<t>Two file nodes, "a" (named "current.txt") and "b" (named "previous.txt"), are
to swap names.  Applied one at a time, either rename collides with the name the
other still holds; applied together, the result is conflict-free.  A server
conforming only to <xref target="JMAP-CORE"/> may accept this swap, but is not required to.
With "atomic" set, the rule that sibling names are unique is evaluated only
against the resulting state:</t>

<figure><artwork><![CDATA[
[[ "FileNode/set", {
  "accountId": "u1",
  "atomic": true,
  "update": {
    "a": { "name": "previous.txt" },
    "b": { "name": "current.txt" }
  }
}, "0" ]]
]]></artwork></figure>

<t>Both renames take effect, or — if either is rejected for any reason — neither
does, and the server returns an "atomicFailure" error identifying the offending
id.</t>

</section>
<section anchor="replace"><name>Atomic replace of one file by another</name>

<t>A common pattern in POSIX applications is to write new content to a temporary
file and then rename it over the original, so that other readers see either the
complete old file or the complete new one, never a partial write.  Here "t"
(named "report.txt.tmp") holds the new content, and "r" (named "report.txt",
with content "G_old") is the file to be replaced:</t>

<figure><artwork><![CDATA[
[[ "FileNode/set", {
  "accountId": "u1",
  "atomic": true,
  "ifUnchangedBy": { "r": { "blobId": "G_old" } },
  "update":  { "t": { "name": "report.txt" } },
  "destroy": [ "r" ]
}, "0" ]]
]]></artwork></figure>

<t>Without "atomic", a server may process each change sequentially against the
current state (<xref target="JMAP-CORE"/>, Section 5.3), so the rename of "t" could be
rejected because "r" still holds the name, while the destroy of "r" succeeds,
leaving neither file named "report.txt".  With "atomic", the sibling-name
uniqueness rule is evaluated only against the resulting state, in which "r" no
longer exists, and the two changes succeed or fail together.</t>

<t>The "ifUnchangedBy" precondition additionally ensures that "r" is replaced only
if no other client has changed its content since this client read it; if it has,
the method is rejected with a "stateMismatch" error and neither file is changed.
A client that wants the unconditional behaviour of POSIX rename(2) omits the
precondition.</t>

</section>
</section>
<section anchor="implementation-considerations"><name>Implementation Considerations</name>

<section anchor="evaluating-preconditions"><name>Evaluating Preconditions</name>

<t>A server can implement "ifUnchangedBy" generically, without code specific to any
data type.  For each entry, the server reads the current object in the
representation it would return from Foo/get, applies the PatchObject to a copy
of it using the same logic it uses for the "update" argument, and compares the
result with the original.  Any difference means the precondition is not
satisfied.  Every data type that supports Foo/set already has both a Foo/get
representation and PatchObject application, so no new per-type machinery is
required.</t>

<t>A server <bcp14>MAY</bcp14> instead compare the referenced values directly, or use any cheaper
method, provided the outcome is the same.</t>

<t>The precondition check is only meaningful if no other change to the referenced
objects can occur between evaluating the preconditions and applying the
method's changes.  A server therefore evaluates the preconditions and applies
the changes within the same lock or transaction.</t>

</section>
<section anchor="applying-methods-atomically"><name>Applying Methods Atomically</name>

<t>A server backed by a transactional store can implement "atomic" by performing
the whole Foo/set within a single transaction, deferring constraint checks such
as name uniqueness until all of the changes have been applied, and rolling the
transaction back if any part fails.  A server that cannot do this for some or
all of its data types still supports this extension by returning
"cannotApplyAtomically" (<xref target="cannotapply"/>) for those methods.</t>

</section>
</section>
<section anchor="implementation-status"><name>Implementation Status</name>

<t>EDITOR: please remove this section before publication.</t>

<t>This section records the status of known implementations of the protocol
defined by this specification at the time of posting of this Internet-Draft,
and is based on a proposal described in <xref target="IMPL-STATUS"/>.  The description of
implementations in this section is intended to assist the IETF in its
decision processes in progressing drafts to RFCs.  Please note that the listing
of any individual implementation here does not imply endorsement by the IETF.
Furthermore, no effort has been spent to verify the information presented here
that was supplied by IETF contributors.  This is not intended as, and must not
be construed to be, a catalog of available implementations or their features.
Readers are advised to note that other implementations may exist.</t>

<section anchor="cyrus-imap"><name>Cyrus IMAP</name>

<t><list style="symbols">
  <t>Organization: Cyrus IMAP project</t>
  <t>Description: "ifUnchangedBy" for all JMAP data types implemented by Cyrus</t>
  <t>Level of maturity: in development
(https://github.com/cyrusimap/cyrus-imapd/pull/6104)</t>
  <t>Licensing: BSD-style</t>
  <t>Contact: Bron Gondwana <eref target="mailto:brong@fastmailteam.com">brong@fastmailteam.com</eref></t>
</list></t>

</section>
<section anchor="fastmail"><name>Fastmail</name>

<t><list style="symbols">
  <t>Organization: Fastmail</t>
  <t>Description: "ifUnchangedBy" in Fastmail's internal JMAP server</t>
  <t>Level of maturity: in development</t>
  <t>Licensing: proprietary</t>
  <t>Contact: Bron Gondwana <eref target="mailto:brong@fastmailteam.com">brong@fastmailteam.com</eref></t>
</list></t>

</section>
</section>
<section anchor="iana-considerations"><name>IANA Considerations</name>

<section anchor="jmap-capability-registration-for-conditional"><name>JMAP Capability Registration for "conditional"</name>

<t>IANA is requested to register the "conditional" JMAP Capability as follows, in
the "JMAP Capabilities" registry established by <xref target="JMAP-CORE"/>:</t>

<dl>
  <dt>Capability Name:</dt>
  <dd>
    <t>urn:ietf:params:jmap:conditional</t>
  </dd>
  <dt>Specification document:</dt>
  <dd>
    <t>this document</t>
  </dd>
  <dt>Intended use:</dt>
  <dd>
    <t>common</t>
  </dd>
  <dt>Change Controller:</dt>
  <dd>
    <t>IETF</t>
  </dd>
  <dt>Security and privacy considerations:</dt>
  <dd>
    <t>this document, <xref target="security"/></t>
  </dd>
</dl>

</section>
<section anchor="jmap-error-code-registration-for-atomicfailure"><name>JMAP Error Code Registration for "atomicFailure"</name>

<t>IANA is requested to register the "atomicFailure" JMAP Error Code in the "JMAP
Error Codes" registry established by <xref target="JMAP-CORE"/>:</t>

<dl>
  <dt>JMAP Error Code:</dt>
  <dd>
    <t>atomicFailure</t>
  </dd>
  <dt>Intended use:</dt>
  <dd>
    <t>common</t>
  </dd>
  <dt>Change Controller:</dt>
  <dd>
    <t>IETF</t>
  </dd>
  <dt>Description:</dt>
  <dd>
    <t>A Foo/set requested with "atomic" set to true could not commit all of its
changes together; no change was made.  Returned as a method-level error.</t>
  </dd>
  <dt>Reference:</dt>
  <dd>
    <t>this document</t>
  </dd>
</dl>

</section>
<section anchor="jmap-error-code-registration-for-cannotapplyatomically"><name>JMAP Error Code Registration for "cannotApplyAtomically"</name>

<t>IANA is requested to register the "cannotApplyAtomically" JMAP Error Code in
the "JMAP Error Codes" registry established by <xref target="JMAP-CORE"/>:</t>

<dl>
  <dt>JMAP Error Code:</dt>
  <dd>
    <t>cannotApplyAtomically</t>
  </dd>
  <dt>Intended use:</dt>
  <dd>
    <t>common</t>
  </dd>
  <dt>Change Controller:</dt>
  <dd>
    <t>IETF</t>
  </dd>
  <dt>Description:</dt>
  <dd>
    <t>A Foo/set was requested with "atomic" set to true, but the server cannot
apply this method atomically; no change was made.  Returned as a method-level
error.</t>
  </dd>
  <dt>Reference:</dt>
  <dd>
    <t>this document</t>
  </dd>
</dl>

</section>
</section>
<section anchor="security"><name>Security Considerations</name>

<section anchor="information-disclosure"><name>Information Disclosure</name>

<t>The conditional mechanism returns no object data.  A failed precondition yields
only a "stateMismatch" error, optionally naming the ids whose preconditions did
not hold, but never their values — nothing beyond what the client could already
obtain by reading the objects with Foo/get.</t>

<t>A precondition does not bypass access control.  A server <bcp14>MUST</bcp14> require the same
permissions to read the properties referenced in an "ifUnchangedBy" PatchObject
as it would to return them from Foo/get.  In particular, a server <bcp14>MUST NOT</bcp14>
evaluate a precondition on a property the requesting client is not permitted to
read; such a condition <bcp14>MUST</bcp14> cause the method to fail with a "forbidden" error,
so that the mechanism cannot be used as an oracle to probe the values of
properties the client cannot otherwise see.</t>

<t>This differs deliberately from a precondition on an object that does not exist
or is not visible to the client, which is reported as "stateMismatch"
(<xref target="effect"/>).  For a client, an invisible object is indistinguishable from one
that does not exist, and reporting it differently would disclose its existence.
A property the client may not read, by contrast, belongs to an object the client
can see; the restriction depends only on the client's rights, not on the
property's value, so "forbidden" discloses nothing about the value and tells the
client that the request cannot succeed however it is retried.</t>

</section>
<section anchor="atomic-methods-and-resource-consumption"><name>Atomic Methods and Resource Consumption</name>

<t>Applying a method atomically may require the server to hold a transaction, or
equivalent locks, across all of its changes, and so a very large atomic Foo/set
can hold resources longer than the same changes made independently.  The limits
a server already applies to the number of objects in a single Foo/set
(<xref target="JMAP-CORE"/>) continue to apply, and a server <bcp14>MAY</bcp14> reject an atomic method it
considers too large rather than attempt it.</t>

</section>
<section anchor="resource-consumption"><name>Resource Consumption</name>

<t>Evaluating a precondition is comparable in cost to validating an update
PatchObject and imposes no significant additional load.</t>

</section>
</section>
<section anchor="changes"><name>Changes</name>

<t>EDITOR: please remove this section before publication.</t>

<t>The source of this document exists on github at:
https://github.com/brong/draft-gondwana-jmap-conditional/</t>

<t><strong>draft-ietf-jmap-conditional-01</strong></t>

<t><list style="symbols">
  <t>Moved the examples into their own section; they were previously nested under
the "Atomic Foo/set" section.</t>
  <t>Added an example of atomically replacing one file with another (the POSIX
write-then-rename pattern).</t>
  <t>Added Implementation Considerations, describing a generic way to evaluate
preconditions and to apply methods atomically.</t>
  <t>Added an Implementation Status section.</t>
  <t>Explained why a precondition on an unreadable property yields "forbidden"
while a precondition on an invisible object yields "stateMismatch".</t>
  <t>Clarified that <xref target="JMAP-CORE"/> already permits, but does not require, a server
to accept changes such as a name exchange whose final state is valid;
"atomic" makes this a guarantee.</t>
</list></t>

<t><strong>draft-ietf-jmap-conditional-00</strong></t>

<t><list style="symbols">
  <t>Upload with working-group adopted name.</t>
</list></t>

<t><strong>draft-gondwana-jmap-conditional-01</strong></t>

<t><list style="symbols">
  <t>Added the "atomic" argument to Foo/set: a method requested with "atomic" is
applied as a single unit, with constraints evaluated against the resulting
state (enabling changes valid only as a whole, such as an atomic name
exchange).</t>
  <t>Added the "atomicFailure" method-level error (the method's changes could not
be committed together) and the "cannotApplyAtomically" method-level error
(the server cannot apply the method atomically), both registered with IANA.
A server <bcp14>MUST NOT</bcp14> apply an atomic method's changes only in part.</t>
  <t>Generalised "ifUnchangedBy" to allow a precondition on any object of the
method's type, including objects the method does not itself create, update,
or destroy (for example a parent or container).</t>
  <t>Changed the effect of a failed precondition from a per-object "stateMismatch"
SetError to a method-level "stateMismatch" error that rejects the whole
method and makes no change; a client wanting independent application uses
separate method calls.  Removed the bespoke per-object SetError definition in
favour of Core's method-level "stateMismatch", optionally carrying the
"failed" ids.</t>
</list></t>

<t><strong>draft-gondwana-jmap-conditional-00</strong></t>

<t><list style="symbols">
  <t>Initial proposal.</t>
</list></t>

</section>


  </middle>

  <back>


<references title='References' anchor="sec-combined-references">

    <references title='Normative References' anchor="sec-normative-references">



<reference anchor="JMAP-CORE">
  <front>
    <title>The JSON Meta Application Protocol (JMAP)</title>
    <author fullname="N. Jenkins" initials="N." surname="Jenkins"/>
    <author fullname="C. Newman" initials="C." surname="Newman"/>
    <date month="July" year="2019"/>
    <abstract>
      <t>This document specifies a protocol for clients to efficiently query, fetch, and modify JSON-based data objects, with support for push notification of changes and fast resynchronisation and for out-of- band binary data upload/download.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="8620"/>
  <seriesInfo name="DOI" value="10.17487/RFC8620"/>
</reference>

<reference anchor="RFC2119">
  <front>
    <title>Key words for use in RFCs to Indicate Requirement Levels</title>
    <author fullname="S. Bradner" initials="S." surname="Bradner"/>
    <date month="March" year="1997"/>
    <abstract>
      <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="2119"/>
  <seriesInfo name="DOI" value="10.17487/RFC2119"/>
</reference>

<reference anchor="RFC8174">
  <front>
    <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
    <author fullname="B. Leiba" initials="B." surname="Leiba"/>
    <date month="May" year="2017"/>
    <abstract>
      <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="8174"/>
  <seriesInfo name="DOI" value="10.17487/RFC8174"/>
</reference>




    </references>

    <references title='Informative References' anchor="sec-informative-references">



<reference anchor="JMAP-MAIL">
  <front>
    <title>The JSON Meta Application Protocol (JMAP) for Mail</title>
    <author fullname="N. Jenkins" initials="N." surname="Jenkins"/>
    <author fullname="C. Newman" initials="C." surname="Newman"/>
    <date month="August" year="2019"/>
    <abstract>
      <t>This document specifies a data model for synchronising email data with a server using the JSON Meta Application Protocol (JMAP). Clients can use this to efficiently search, access, organise, and send messages, and to get push notifications for fast resynchronisation when new messages are delivered or a change is made in another client.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="8621"/>
  <seriesInfo name="DOI" value="10.17487/RFC8621"/>
</reference>

<reference anchor="HTTP-SEMANTICS">
  <front>
    <title>HTTP Semantics</title>
    <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
    <author fullname="M. Nottingham" initials="M." role="editor" surname="Nottingham"/>
    <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
    <date month="June" year="2022"/>
    <abstract>
      <t>The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document describes the overall architecture of HTTP, establishes common terminology, and defines aspects of the protocol that are shared by all versions. In this definition are core protocol elements, extensibility mechanisms, and the "http" and "https" Uniform Resource Identifier (URI) schemes.</t>
      <t>This document updates RFC 3864 and obsoletes RFCs 2818, 7231, 7232, 7233, 7235, 7538, 7615, 7694, and portions of 7230.</t>
    </abstract>
  </front>
  <seriesInfo name="STD" value="97"/>
  <seriesInfo name="RFC" value="9110"/>
  <seriesInfo name="DOI" value="10.17487/RFC9110"/>
</reference>

<reference anchor="WEBDAV">
  <front>
    <title>HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)</title>
    <author fullname="L. Dusseault" initials="L." role="editor" surname="Dusseault"/>
    <date month="June" year="2007"/>
    <abstract>
      <t>Web Distributed Authoring and Versioning (WebDAV) consists of a set of methods, headers, and content-types ancillary to HTTP/1.1 for the management of resource properties, creation and management of resource collections, URL namespace manipulation, and resource locking (collision avoidance).</t>
      <t>RFC 2518 was published in February 1999, and this specification obsoletes RFC 2518 with minor revisions mostly due to interoperability experience. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="4918"/>
  <seriesInfo name="DOI" value="10.17487/RFC4918"/>
</reference>


<reference anchor="JMAP-FILENODE">
   <front>
      <title>JMAP File Storage extension</title>
      <author fullname="Bron Gondwana" initials="B." surname="Gondwana">
         <organization>Fastmail</organization>
      </author>
      <date day="15" month="May" year="2026"/>
      <abstract>
	 <t>   The JMAP base protocol (RFC8620) provides the ability to upload and
   download arbitrary binary data.  This binary data is called a &quot;blob&quot;,
   and can be used in all other JMAP extensions.

   This extension adds a method to expose blobs as a filesystem along
   with the types of metadata that are provided by other remote
   filesystem protocols.

	 </t>
      </abstract>
   </front>
   <seriesInfo name="Internet-Draft" value="draft-ietf-jmap-filenode-14"/>
   
</reference>

<reference anchor="IMPL-STATUS">
  <front>
    <title>Improving Awareness of Running Code: The Implementation Status Section</title>
    <author fullname="Y. Sheffer" initials="Y." surname="Sheffer"/>
    <author fullname="A. Farrel" initials="A." surname="Farrel"/>
    <date month="July" year="2016"/>
    <abstract>
      <t>This document describes a simple process that allows authors of Internet-Drafts to record the status of known implementations by including an Implementation Status section. This will allow reviewers and working groups to assign due consideration to documents that have the benefit of running code, which may serve as evidence of valuable experimentation and feedback that have made the implemented protocols more mature.</t>
      <t>This process is not mandatory. Authors of Internet-Drafts are encouraged to consider using the process for their documents, and working groups are invited to think about applying the process to all of their protocol specifications. This document obsoletes RFC 6982, advancing it to a Best Current Practice.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="205"/>
  <seriesInfo name="RFC" value="7942"/>
  <seriesInfo name="DOI" value="10.17487/RFC7942"/>
</reference>




    </references>

</references>



  </back>

<!-- ##markdown-source:
H4sIAAAAAAAAA81963IbR5bm/3yKHGgiLCoAipLVF0MdPUNRVDcnrMtK1Hpn
3Y6JBKpA1qhQhakskMYo1LEPsQ+wz7KPsk+y5zvn5KUKECU7/GP8wyKBqryc
+52z2cz0VV+Xc/svL0/f2LO2Kaq+ahtX23dlb9xi0ZU3+1+aol02bk2vFZ1b
9bOq7Fezf1+7zWyZHpqdPDJ+u1hX3tPvl7sNPX5xfvnCLF1fXrXdbm59X5jt
pqDf/dz+8fePT0y78G1d4ndTbbq57but7x+fnHx38th8KHe3bVfQKk1fdk3Z
z55jd+N71xT/5uq2oR12pTebam5/7Nvl1Pq267ty5emn3Ro//GSM2/bXbTc3
dmYs/Vc1tPezY/sXOvmtaxx/KJd71rXN8PO2u5rbF873a1fV/EmJn+Z2QY9e
/fNKv+lLtz5etmtjmrZbu766Kef8NAA5O3v99nxu37444xubqlkdeOjl6cX3
4aFH/PFfLy/fzN6dvzx9dXlx9o6/++7RoxP+7ofzZ89P/zt/9uS7R39My7y4
+P781evntN/F7PlxwtOqqsumLUp+8uLlm+9n7y5PL9/Lsn/47sljY2azmXUL
33du2RtzeV0KGSycL+2mawm+bW3vf/wY7/Tp0xG+uKmK0tuenn/Rtg992dt1
SRAvLF3TLLuSbtpcTS3jnX8i7Fl6pe/aHf1u28W/l8veH9O5etuuVmXnrbOe
vqpLS/S13HZd2Sx3hn6md+op7zWpVhfNu55IaWJdd7Vdl00/tbfX1fLaXm1d
V9AijaUPq67ULWzPNFmt6Jud0c/aFS3n5Dt77bxdXrvmqixkl9tros5wn8rb
rsRLZXEMANHv5c992YDcrSuwo11VTdlN7absZrpBxiG0EFav/Joue2qXdUXn
s2u3M135H1sclI9C567oHYLrlt4RfiFKDDADzJdlWdi2qXe4DQ7aEwwI8rIn
cUhV026uX16XDMySL1r+vOHTYwU6Yb+zN67elsQt9E1Xek9fbQF4XhJ4Nm+w
xmu5iasJmcWOzoFbMn71dEAewyOSQ7vpK5IEfbU8hELrl3SAwvZtwrSC6//9
r//NuwMgdDoAqAXCmB3s5GI1e4kjTQwdOIKW38JxCLFCtXQqxzg9gKnat3oH
phEclbEzcX27rpaJnhQdmw0hCo8aJadA5y4j1G1T9XNbVnT2zpY3ZbdTSrJV
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

-->

</rfc>

