<?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-object-history-02" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="JMAP Object History">JMAP Object History</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="16"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 35?>

<t>The JMAP base protocol (RFC8620) provides methods for synchronizing
the current state of data objects between client and server.  This
extension adds the ability to retrieve historical versions of objects,
including objects that have been destroyed, by extending the standard
Foo/get method.</t>



    </abstract>



  </front>

  <middle>


<?line 43?>

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

<t>JMAP (<xref target="JMAP-CORE"/> — JSON Meta Application Protocol) provides a
standard set of methods for each data type: Foo/get, Foo/changes,
Foo/set, Foo/query, and Foo/queryChanges.  These methods operate
on the current state of objects.  The Foo/changes method tells a
client which objects have changed, but does not provide the
previous values.</t>

<t>In many applications it is useful to access historical versions
of objects.  For example, a user may want to see previous versions
of a contact record (<xref target="JMAP-CONTACTS"/>) or recover a deleted
email (<xref target="JMAP-MAIL"/>).</t>

<t>This extension adds history support to the standard Foo/get
method.  When the <spanx style="verb">urn:ietf:params:jmap:object-history</spanx> capability
is included in the request's <spanx style="verb">using</spanx> array, Foo/get gains
additional parameters that allow the client to request previous
versions of objects, including objects that have been destroyed.</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?>

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

<t>The capabilities object is returned as part of the JMAP Session
object; see <xref target="JMAP-CORE"/>, Section 2.</t>

<t>This document defines an additional capability URI.</t>

<section anchor="urnietfparamsjmapobject-history"><name>urn:ietf:params:jmap:object-history</name>

<t>The capability <spanx style="verb">urn:ietf:params:jmap:object-history</spanx> being present
in the "accountCapabilities" property of an account represents
support for retrieving historical object versions in that account.
Servers that include the capability in one or more
"accountCapabilities" properties <bcp14>MUST</bcp14> also include the property in
the "capabilities" property.</t>

<t>The value of this property in the JMAP session "capabilities"
property <bcp14>MUST</bcp14> be an empty object.</t>

<t>The value of this property in an account's "accountCapabilities"
property is an object that <bcp14>MUST</bcp14> contain the following information
on server capabilities for that account:</t>

<t><list style="symbols">
  <t>maxHistoryDuration: "UnsignedInt|null"  <vspace blankLines='1'/>
The number of seconds after replacement for which the server
  intends to retain old versions, or null if the server does
  not have a time-based retention policy.  This is a statement
  of server policy, not a guarantee: retention is best effort,
  and the server <bcp14>MAY</bcp14> discard versions sooner (for example, due
  to storage limits).  A version whose <spanx style="verb">replaced</spanx> timestamp is
  more than this many seconds ago has probably been discarded.
  Clients that need to be certain an object remains available
  should not destroy it.</t>
  <t>supportedTypes: "String[]"  <vspace blankLines='1'/>
The names of the data types, from the "JMAP Data Types"
  registry <xref target="IANA-JMAP"/> or private types, for which the server
  supports the history extensions in this account.  A server
  <bcp14>MAY</bcp14> support history for only a subset of the types it
  supports, and <bcp14>MAY</bcp14> retain history for only some objects of
  a supported type (for example, only for some folders).
  Clients <bcp14>MUST</bcp14> ignore type names they do not recognise.</t>
</list></t>

</section>
</section>
<section anchor="extensions-to-fooget"><name>Extensions to Foo/get</name>

<t>When this capability is included in the request's <spanx style="verb">using</spanx> array,
the standard Foo/get method (<xref target="JMAP-CORE"/>, Section 5.1) accepts
the following additional request arguments:</t>

<t><list style="symbols">
  <t>includeReplaced: "Boolean" (default: false)  <vspace blankLines='1'/>
If true, the server returns previous versions of the
  requested objects in addition to the current version.
  Each previous version appears as a separate entry in the
  <spanx style="verb">list</spanx> array, with the same <spanx style="verb">id</spanx> as the current version.
  Every entry includes an <spanx style="verb">objectHistory</spanx> property (see
  below).  Entries with the same <spanx style="verb">id</spanx> <bcp14>MUST</bcp14> be ordered by
  <spanx style="verb">objectHistory.version</spanx> (ascending).  Entries for
  different objects <bcp14>MAY</bcp14> be interleaved.</t>
  <t>includeDestroyed: "Boolean" (default: false)  <vspace blankLines='1'/>
If true, the server also returns objects that have been
  destroyed.  If <spanx style="verb">includeReplaced</spanx> is false, only the final
  version before destruction is returned.  If <spanx style="verb">includeReplaced</spanx>
  is true, all retained historical versions of destroyed
  objects are returned.  For destroyed objects, every entry
  has a non-null <spanx style="verb">objectHistory.replaced</spanx> value, since every
  version has been superseded (the final version was replaced
  by destruction).</t>
  <t>historyAfter: "UTCDate|null" (default: null)  <vspace blankLines='1'/>
If supplied, only versions with an <spanx style="verb">objectHistory.replaced</spanx>
  value strictly after this date are returned, plus the
  current (live) version which has a null <spanx style="verb">replaced</spanx> value.
  If null, no time-based filter is applied.</t>
  <t>historyBefore: "UTCDate|null" (default: null)  <vspace blankLines='1'/>
If supplied, only versions with an <spanx style="verb">objectHistory.replaced</spanx>
  value strictly before this date are returned.  The current
  (live) version, which has a null <spanx style="verb">replaced</spanx> value, is not
  returned.  If null, no time-based filter is applied.  <vspace blankLines='1'/>
A client can use this to page backwards through history: it
  passes the oldest <spanx style="verb">replaced</spanx> value from the previous response
  as <spanx style="verb">historyBefore</spanx> in the next request.  When several ids are
  requested, the client passes the oldest <spanx style="verb">replaced</spanx> value from
  the whole response; any id with no remaining versions is
  returned in <spanx style="verb">notFound</spanx>.  Clients <bcp14>SHOULD</bcp14> pass the <spanx style="verb">replaced</spanx>
  value exactly as received, rather than parsing and
  re-serialising it, since re-serialising at a lower precision
  could cause versions to be skipped.</t>
  <t>historySkip: "UnsignedInt" (default: 0)  <vspace blankLines='1'/>
The number of entries to skip for each id, counting from the
  most recent (the highest version number), before any entries
  are returned.  The current version, if it would otherwise be
  returned, counts as one entry.  For example, a client that
  wants only versions older than the 20 most recent passes
  <spanx style="verb">historySkip: 20</spanx>; any id with 20 or fewer matching entries
  is returned in <spanx style="verb">notFound</spanx>.  <vspace blankLines='1'/>
A client can also use this to page backwards through history,
  by adding the number of entries returned for an id to
  <spanx style="verb">historySkip</spanx> in the next request.  This is less robust than
  <spanx style="verb">historyBefore</spanx>: if a new version is recorded between
  requests, the window shifts and one entry is returned again.</t>
  <t>historyLimit: "UnsignedInt|null" (default: null)  <vspace blankLines='1'/>
If supplied, the maximum number of entries to return in the
  <spanx style="verb">list</spanx> array for each id, including the current version if
  any.  For each id, the server <bcp14>MUST</bcp14> return the most recent
  entries (those with the highest version numbers) remaining
  after <spanx style="verb">historySkip</spanx> is applied, not the oldest.  If null, the
  server returns all remaining retained versions, subject to
  its own limits.</t>
</list></t>

<t>The server applies <spanx style="verb">includeReplaced</spanx>, <spanx style="verb">includeDestroyed</spanx>,
<spanx style="verb">historyAfter</spanx>, and <spanx style="verb">historyBefore</spanx> to select the matching
versions of each id, then skips <spanx style="verb">historySkip</spanx> entries, then
returns at most <spanx style="verb">historyLimit</spanx> of the remaining entries.</t>

<t>If the <spanx style="verb">ids</spanx> argument is null, the server returns all objects of
the type as per <xref target="JMAP-CORE"/>, Section 5.1.  If <spanx style="verb">includeDestroyed</spanx>
is true, this includes every destroyed object for which the server
still retains any version.</t>

<t>The "maxObjectsInGet" limit and the "requestTooLarge" error
(<xref target="JMAP-CORE"/>, Section 5.1) apply to the number of distinct ids,
not to the number of entries in the <spanx style="verb">list</spanx> array.  Each id can
have up to <spanx style="verb">historyLimit</spanx> entries.</t>

<t>If, after applying <spanx style="verb">includeReplaced</spanx>, <spanx style="verb">includeDestroyed</spanx>,
<spanx style="verb">historyAfter</spanx>, <spanx style="verb">historyBefore</spanx>, and <spanx style="verb">historySkip</spanx>, no versions of a
requested id remain to be returned, that id is included in the
<spanx style="verb">notFound</spanx> array.</t>

<section anchor="the-objecthistory-property"><name>The objectHistory property</name>

<t>When <spanx style="verb">includeReplaced</spanx> or <spanx style="verb">includeDestroyed</spanx> is true, each object
in the <spanx style="verb">list</spanx> array includes an additional property:</t>

<t><list style="symbols">
  <t>objectHistory: "ObjectHistoryInfo"  <vspace blankLines='1'/>
An ObjectHistoryInfo object with the following properties:  <list style="symbols">
      <t>version: "UnsignedInt"
A per-object monotonically increasing number that
provides ordering among the versions of a single object
within a response.  Version numbers <bcp14>MAY</bcp14> have gaps (e.g.,
a server may use internal sequence numbers such as modseq
values).  The current (live) version of an object always
has the highest version number.  Servers <bcp14>SHOULD</bcp14> return
consistent version numbers across requests, but clients
<bcp14>MUST NOT</bcp14> rely on this — version numbers exist primarily
to provide ordering within a single response.</t>
      <t>replaced: "UTCDate|null"
The date and time at which this version was superseded,
either by a subsequent update or by destruction.  If null,
this is the current live version of the object.  For
destroyed objects, every version has a non-null <spanx style="verb">replaced</spanx>
value — the final version's <spanx style="verb">replaced</spanx> is the time of
destruction.  The <spanx style="verb">replaced</spanx> values of different versions
of the same object <bcp14>MUST</bcp14> be distinct, so that <spanx style="verb">historyBefore</spanx>
and <spanx style="verb">historyAfter</spanx> partition the history without ambiguity;
a server that records two versions with the same timestamp
can collapse them into a single version.  The value <bcp14>MAY</bcp14>
include fractional seconds (<xref target="JMAP-CORE"/>, Section 1.4),
but servers <bcp14>SHOULD NOT</bcp14> use more than millisecond precision,
as many client date libraries cannot represent more.</t>
      <t>hasOlder: "Boolean"
If true, the server retains at least one older version of
this object than this one, whether or not that version was
returned in this response.  A client can check <spanx style="verb">hasOlder</spanx>
on the oldest entry returned for an id to learn whether
more history is available, and retrieve it using
<spanx style="verb">historyBefore</spanx> or <spanx style="verb">historySkip</spanx>.  The server <bcp14>MAY</bcp14> return
false even if older versions exist (e.g., if it cannot
efficiently determine whether older versions remain).  If
the server returns true, the client <bcp14>MUST NOT</bcp14> assume the
older versions will still be available in a subsequent
request, as the server may purge history at any time.</t>
    </list></t>
</list></t>

<t>When <spanx style="verb">includeReplaced</spanx> and <spanx style="verb">includeDestroyed</spanx> are both false
(the default), the <spanx style="verb">objectHistory</spanx> property is not included in
the response, and the behaviour is identical to standard Foo/get.</t>

<t>The client <bcp14>MAY</bcp14> include "objectHistory" in the <spanx style="verb">properties</spanx> argument.
It is returned if and only if <spanx style="verb">includeReplaced</spanx> or <spanx style="verb">includeDestroyed</spanx>
is true, regardless of whether it is listed in <spanx style="verb">properties</spanx>.</t>

<t>Which changes produce a version is server dependent: a version is
a snapshot of the object that the server recorded at some point.
The server is not required to create a new version for every
individual change to an object.  For example, rapid successive
updates may be collapsed into a single version, and a server may
choose not to record a version for changes that only affect
server-computed properties.  The server <bcp14>MAY</bcp14> also prune old versions
in any order, so there can be gaps in the version history available
to the client.  Clients <bcp14>MUST NOT</bcp14> assume that the version history is
complete or contiguous.</t>

<t>The values of server-computed properties (for example, the counts
on a Mailbox) in a historical version are also server dependent.
The server <bcp14>SHOULD</bcp14> return the value the property had at the time of
that version if it has that information.</t>

<t>If a historical version contains a reference to a blob (for
example, the <spanx style="verb">blobId</spanx> of an Email), that blob <bcp14>MUST</bcp14> be downloadable
for as long as the server returns that version.  A server that has
discarded a blob referenced by a version <bcp14>MUST NOT</bcp14> return that
version.</t>

<t>If <spanx style="verb">includeReplaced</spanx> or <spanx style="verb">includeDestroyed</spanx> is true and the data type
is not listed in the <spanx style="verb">supportedTypes</spanx> capability property, the
server <bcp14>MUST</bcp14> reject the call with an "invalidArguments" error.</t>

<t>If the data type is supported but the server does not retain
history for a particular object, it <bcp14>MUST</bcp14> still return the current
version with an <spanx style="verb">objectHistory</spanx> property when requested.  In this
case, the server returns only the current version, with a <spanx style="verb">replaced</spanx>
of null.</t>

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

<section anchor="contact-history"><name>Contact history</name>

<t>Requesting the history of a contact, including all versions:</t>

<figure><sourcecode type="json"><![CDATA[
[["ContactCard/get", {
  "accountId": "abc",
  "ids": ["contact1"],
  "properties": ["name", "emails"],
  "includeReplaced": true,
  "historyLimit": 10
}, "0"]]
]]></sourcecode></figure>

<t>The response includes three versions: the original creation,
a name update, and the current version with an additional email
address:</t>

<figure><sourcecode type="json"><![CDATA[
[["ContactCard/get", {
  "accountId": "abc",
  "state": "abc123",
  "list": [
    {
      "id": "contact1",
      "name": {"full": "Robert Smith"},
      "emails": {
        "e1": {"address": "bob@example.com"}
      },
      "objectHistory": {
        "version": 1,
        "replaced": "2026-02-20T14:15:00Z",
        "hasOlder": false
      }
    },
    {
      "id": "contact1",
      "name": {"full": "Bob Smith"},
      "emails": {
        "e1": {"address": "bob@example.com"}
      },
      "objectHistory": {
        "version": 2,
        "replaced": "2026-03-01T09:00:00Z",
        "hasOlder": true
      }
    },
    {
      "id": "contact1",
      "name": {"full": "Bob Smith"},
      "emails": {
        "e1": {"address": "bob@example.com"},
        "e2": {"address": "bob@personal.example"}
      },
      "objectHistory": {
        "version": 3,
        "replaced": null,
        "hasOlder": true
      }
    }
  ],
  "notFound": []
}, "0"]]
]]></sourcecode></figure>

</section>
<section anchor="recovering-destroyed-emails"><name>Recovering destroyed emails</name>

<t>A client can use Email/changes to discover which emails have been
destroyed, then use a backreference to fetch their final state.
This is useful for displaying a "recently deleted" view:</t>

<figure><sourcecode type="json"><![CDATA[
[
  ["Email/changes", {
    "accountId": "abc",
    "sinceState": "state42"
  }, "0"],
  ["Email/get", {
    "accountId": "abc",
    "#ids": {
      "resultOf": "0",
      "name": "Email/changes",
      "path": "/destroyed"
    },
    "properties": ["subject", "from", "receivedAt"],
    "includeDestroyed": true
  }, "1"]
]
]]></sourcecode></figure>

<t>The Email/get response returns the final state of each
destroyed email.  The <spanx style="verb">objectHistory.replaced</spanx> value is the
time of destruction:</t>

<figure><sourcecode type="json"><![CDATA[
[["Email/get", {
  "accountId": "abc",
  "state": "state43",
  "list": [
    {
      "id": "email42",
      "subject": "Meeting notes",
      "from": [{"name": "Alice",
        "email": "alice@example.com"}],
      "receivedAt": "2026-03-10T09:00:00Z",
      "objectHistory": {
        "version": 1,
        "replaced": "2026-03-15T16:30:00Z",
        "hasOlder": false
      }
    },
    {
      "id": "email57",
      "subject": "Project update",
      "from": [{"name": "Bob",
        "email": "bob@example.com"}],
      "receivedAt": "2026-03-12T14:00:00Z",
      "objectHistory": {
        "version": 1,
        "replaced": "2026-03-15T16:31:00Z",
        "hasOlder": false
      }
    }
  ],
  "notFound": []
}, "1"]]
]]></sourcecode></figure>

<t>Since <spanx style="verb">includeReplaced</spanx> was not set, only the final version of
each destroyed email is returned.  The non-null <spanx style="verb">replaced</spanx>
value indicates when each email was destroyed.</t>

</section>
</section>
</section>
<section anchor="restoring-objects"><name>Restoring Objects</name>

<t>To restore an earlier version of an existing object, the client
uses a normal Foo/set update with the values from that version.</t>

<t>To restore a destroyed object, the client uses Foo/set to create a
new object with the values from the version to be restored.  When
this capability is included in the request's <spanx style="verb">using</spanx> array, the
client <bcp14>MAY</bcp14> include the <spanx style="verb">id</spanx> of the destroyed object in the create
request.  The server <bcp14>MAY</bcp14> honour this, in which case the created
object has that id and its history continues from the destroyed
object's history, so the destroyed versions become previous
versions of the restored object.  If the server does not wish to
reuse the id, it <bcp14>MUST</bcp14> reject the creation with an
"invalidProperties" SetError listing the <spanx style="verb">id</spanx> property; the client
can then retry without an <spanx style="verb">id</spanx> to create the object with a new id.</t>

<t>The server <bcp14>MUST</bcp14> reject a create with an <spanx style="verb">id</spanx> that is not the id of
a destroyed object of the same type in the same account.  Apart
from restoring a destroyed object in this way, the server <bcp14>MUST NOT</bcp14>
reuse the id of a destroyed object for which it retains any
history.</t>

</section>
<section anchor="design-rationale"><name>Design Rationale</name>

<t>This section is not normative.</t>

<t>History is returned through the existing Foo/get method rather than
a new method.  The entries in the <spanx style="verb">list</spanx> array are ordinary objects
of the data type, so a client can feed them to the same parser it
uses for current objects, and the existing <spanx style="verb">properties</spanx> argument
works unchanged.  It also allows a client to fetch the final state
of many destroyed objects in a single call, using a backreference
to the <spanx style="verb">destroyed</spanx> list from Foo/changes, as shown in the examples
above.</t>

<t>The history metadata is embedded in each object as the
<spanx style="verb">objectHistory</spanx> property, rather than wrapping each object in a
separate container, for the same reason: the entries remain
ordinary objects.  This follows the existing pattern of JMAP-specific
properties such as <spanx style="verb">id</spanx> being added to objects whose format is
defined elsewhere; the <spanx style="verb">objectHistory</spanx> name is reserved in the
relevant property registries (see <xref target="iana-considerations"/>).</t>

<t>Each entry is a full copy of the object rather than a patch
against the previous version.  Patches would save space, but the
client would need every intermediate version to reconstruct any
one of them, which conflicts with the server's freedom to prune
versions, and the final version of a destroyed object would need
to be returned in full anyway.</t>

<t>Every superseded version carries a <spanx style="verb">replaced</spanx> timestamp.  The
server always knows, at least approximately, when it replaced a
snapshot it was keeping, and the timestamp is what a client needs
to present history to a user and to filter it with <spanx style="verb">historyAfter</spanx>.</t>

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

<section anchor="jmap-capability-registration-for-urnietfparamsjmapobject-history"><name>JMAP Capability Registration for urn:ietf:params:jmap:object-history</name>

<t>IANA is requested to register the "Object History" Capability
as follows:</t>

<t>Capability Name: urn:ietf:params:jmap:object-history</t>

<t>Intended use: common</t>

<t>Change Controller: IETF</t>

<t>Specification document: this document</t>

<t>Security and privacy considerations: this document,
Security Considerations</t>

</section>
<section anchor="update-to-the-jmap-data-types-registry"><name>Update to the JMAP Data Types Registry</name>

<t>This document adds a "Supports History" column to the "JMAP Data
Types" registry <xref target="IANA-JMAP"/>.  The value
is "Yes" or "No", indicating whether the data type supports the
history extensions defined in this document.</t>

<t>The initial values for existing registrations are:</t>

<texttable>
      <ttcol align='left'>Type Name</ttcol>
      <ttcol align='left'>Supports History</ttcol>
      <c>Core</c>
      <c>No</c>
      <c>PushSubscription</c>
      <c>No</c>
      <c>Mailbox</c>
      <c>Yes</c>
      <c>Thread</c>
      <c>No</c>
      <c>Email</c>
      <c>Yes</c>
      <c>EmailDelivery</c>
      <c>No</c>
      <c>SearchSnippet</c>
      <c>No</c>
      <c>Identity</c>
      <c>Yes</c>
      <c>EmailSubmission</c>
      <c>No</c>
      <c>VacationResponse</c>
      <c>Yes</c>
      <c>MDN</c>
      <c>No</c>
      <c>Quota</c>
      <c>No</c>
      <c>SieveScript</c>
      <c>Yes</c>
      <c>Principal</c>
      <c>No</c>
      <c>ShareNotification</c>
      <c>No</c>
      <c>AddressBook</c>
      <c>Yes</c>
      <c>ContactCard</c>
      <c>Yes</c>
      <c>Calendar</c>
      <c>Yes</c>
      <c>CalendarEvent</c>
      <c>Yes</c>
      <c>CalendarEventNotification</c>
      <c>No</c>
      <c>ParticipantIdentity</c>
      <c>Yes</c>
</texttable>

<t>The default value for this column is "No".  New registrations
that do not explicitly include a value are assumed not to
support history.</t>

<t>This column records whether history is meaningful for a data type.
Whether a particular server supports history for a type is
advertised in the <spanx style="verb">supportedTypes</spanx> capability property.</t>

</section>
<section anchor="jscontact-property-registration"><name>JSContact Property Registration</name>

<t>IANA is requested to register the following property in the
"JSContact Properties" registry defined in <xref target="JSCONTACT"/>,
Section 3, so that the name cannot be used for a property of a
JSContact Card.</t>

<t>Property Name:  objectHistory</t>

<t>Property Type:  not applicable</t>

<t>Property Context:  Card</t>

<t>Intended Usage:  reserved</t>

<t>Since Version:  1.0</t>

<t>Change Controller:  IETF</t>

<t>Reference:  this document</t>

</section>
<section anchor="jscalendar-property-registration"><name>JSCalendar Property Registration</name>

<t>IANA is requested to register the following property in the
"JSCalendar Properties" registry defined in <xref target="JSCALENDAR"/>,
Section 8.2, so that the name cannot be used for a property of a
JSCalendar object.</t>

<t>Property Name:  objectHistory</t>

<t>Property Type:  not applicable</t>

<t>Property Context:  Event, Task, Group</t>

<t>Intended Usage:  reserved</t>

<t>Change Controller:  IETF</t>

<t>Reference:  this document</t>

<t>Specifications that define a JMAP data type whose object format is
also governed by a separate property registry <bcp14>SHOULD</bcp14> reserve the
<spanx style="verb">objectHistory</spanx> property name in that registry.</t>

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

<t>All security considerations from <xref target="JMAP-CORE"/> apply to this
document.</t>

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

<t>Retaining historical versions of objects can consume significant
server storage.  Servers <bcp14>SHOULD</bcp14> impose reasonable limits on
history retention, either by duration (advertised via
<spanx style="verb">maxHistoryDuration</spanx>) or by total storage.  Servers <bcp14>MAY</bcp14>
silently discard history entries when storage limits are
reached.</t>

</section>
<section anchor="access-control"><name>Access Control</name>

<t>Historical versions of an object <bcp14>MUST</bcp14> respect the same access
controls as the current version.  A user who does not have
permission to read an object <bcp14>MUST NOT</bcp14> be able to read its
history.</t>

<t>Access rights can change over time, for example when an object is
shared with a new user, or moved into a shared container.  The
server <bcp14>MUST NOT</bcp14> return a historical version to a user who could not
have read that version at the time it was current.  This requires
the server to track changes to access rights.  A server that does
not keep a full history of access rights can take a conservative
approach: record the point at which the access rights affecting an
object (or its containing object, such as a Mailbox or AddressBook)
last changed, for example as a modseq, and not return any version
that was replaced before that point.</t>

<t>Similarly, for destroyed objects, the server <bcp14>MUST NOT</bcp14> reveal the
existence or content of a destroyed object to a user who could not
read it at the time it was destroyed.</t>

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

<t>Object history may reveal information that the user or an
administrator intended to remove.  For example, a contact
record that was updated to remove a phone number will still
have that phone number visible in its history.  Servers
<bcp14>SHOULD</bcp14> provide administrators with the ability to purge
history for specific objects when required for privacy or
compliance reasons.</t>

</section>
<section anchor="privacy-considerations"><name>Privacy Considerations</name>

<t>When a server supports this extension, updating or destroying an
object does not immediately remove the previous content from the
server; it remains retrievable by anyone with read access to the
object until the server discards it under its retention policy.
Users may not expect this.  This is not new in kind (servers
commonly retain deleted data in backups, and many mail systems
offer a "recently deleted" view), but this extension makes such
data retrievable through the protocol.</t>

<t>Servers <bcp14>SHOULD</bcp14> make their retention policy visible to users, for
example through the <spanx style="verb">maxHistoryDuration</spanx> capability property and
the server's user interface.  Clients that present a "destroy"
operation to users <bcp14>SHOULD NOT</bcp14> describe it as irreversible or
permanent when the server advertises this capability for that data
type.  Whether, and how, a user can request that history be purged
before the end of the retention period is a matter of server
policy and is outside the scope of this document.</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-object-history/</t>

<t><strong>draft-ietf-jmap-object-history-02</strong></t>

<t><list style="symbols">
  <t>Replaced the top-level <spanx style="verb">hasMoreHistory</spanx> response property with a
per-entry <spanx style="verb">objectHistory.hasOlder</spanx> property, so the client can
tell which ids have more history.</t>
  <t>Added <spanx style="verb">historySkip</spanx>, to skip the N most recent versions of each
id; ids with N or fewer versions are returned in <spanx style="verb">notFound</spanx>.</t>
</list></t>

<t><strong>draft-ietf-jmap-object-history-01</strong></t>

<t><list style="symbols">
  <t>Removed "Updates: 8620"; the JMAP Data Types registry is not
defined by RFC 8620.  The registry is now referenced by name
rather than by its defining document.</t>
  <t>Corrected the registry table to match the current registry.</t>
  <t><spanx style="verb">historyLimit</spanx> is now per id.</t>
  <t>Defined behaviour for <spanx style="verb">ids: null</spanx> with <spanx style="verb">includeDestroyed</spanx>, and
clarified that "maxObjectsInGet" counts ids, not entries.</t>
  <t>Ids with no matching versions are returned in <spanx style="verb">notFound</spanx>.</t>
  <t>Which changes create a version, and the values of server-computed
properties, are server dependent.</t>
  <t>Blobs referenced by returned versions must be downloadable.</t>
  <t>Expanded access control considerations for changing access rights.</t>
  <t>Added <spanx style="verb">supportedTypes</spanx> to the account capability; requesting
history for an unsupported type is an error.</t>
  <t>Reserved the <spanx style="verb">objectHistory</spanx> property name in the JSContact and
JSCalendar property registries.</t>
  <t>Added acknowledgements.</t>
  <t>Added a Design Rationale section (Foo/get rather than a new method,
embedded metadata, full objects rather than patches, timestamps).</t>
  <t>Added a Restoring Objects section: a client may ask to recreate a
destroyed object with its old id, and the server may accept or
reject; ids of destroyed objects are otherwise not reused.</t>
  <t><spanx style="verb">maxHistoryDuration</spanx> is now a best-effort statement of server policy.</t>
  <t>Clarified that "objectHistory" may appear in <spanx style="verb">properties</spanx>.</t>
  <t>Added Privacy Considerations.</t>
  <t>Added <spanx style="verb">historyBefore</spanx> for paging backwards through history;
versions of the same object have distinct <spanx style="verb">replaced</spanx> values, with
at most millisecond precision.</t>
  <t>Removed the audit use case from the introduction.</t>
</list></t>

<t><strong>draft-ietf-jmap-object-history-00</strong></t>

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

<t><strong>draft-gondwana-jmap-object-history-00</strong></t>

<t><list style="symbols">
  <t>initial proposal</t>
</list></t>

</section>
<section anchor="acknowledgements"><name>Acknowledgements</name>

<t>The author would like to thank Ben Bucksch, Mauro De Gennaro,
Arnt Gulbrandsen, Neil Jenkins, and Robert Stepanek for their
feedback on this document.</t>

<t>{backmatter}</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="JMAP-CONTACTS">
  <front>
    <title>JSON Meta Application Protocol (JMAP) for Contacts</title>
    <author fullname="N. Jenkins" initials="N." role="editor" surname="Jenkins"/>
    <date month="December" year="2024"/>
    <abstract>
      <t>This document specifies a data model for synchronising contact data with a server using the JSON Meta Application Protocol (JMAP).</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="9610"/>
  <seriesInfo name="DOI" value="10.17487/RFC9610"/>
</reference>

<reference anchor="JSCONTACT">
  <front>
    <title>JSContact: A JSON Representation of Contact Data</title>
    <author fullname="R. Stepanek" initials="R." surname="Stepanek"/>
    <author fullname="M. Loffredo" initials="M." surname="Loffredo"/>
    <date month="May" year="2024"/>
    <abstract>
      <t>This specification defines a data model and JavaScript Object Notation (JSON) representation of contact card information that can be used for data storage and exchange in address book or directory applications. It aims to be an alternative to the vCard data format and to be unambiguous, extendable, and simple to process. In contrast to the JSON-based jCard format, it is not a direct mapping from the vCard data model and expands semantics where appropriate. Two additional specifications define new vCard elements and how to convert between JSContact and vCard.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="9553"/>
  <seriesInfo name="DOI" value="10.17487/RFC9553"/>
</reference>

<reference anchor="JSCALENDAR">
  <front>
    <title>JSCalendar: A JSON Representation of Calendar Data</title>
    <author fullname="N. Jenkins" initials="N." surname="Jenkins"/>
    <author fullname="R. Stepanek" initials="R." surname="Stepanek"/>
    <date month="July" year="2021"/>
    <abstract>
      <t>This specification defines a data model and JSON representation of calendar data that can be used for storage and data exchange in a calendaring and scheduling environment. It aims to be an alternative and, over time, successor to the widely deployed iCalendar data format. It also aims to be unambiguous, extendable, and simple to process. In contrast to the jCal format, which is also based on JSON, JSCalendar is not a direct mapping from iCalendar but defines the data model independently and expands semantics where appropriate.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="8984"/>
  <seriesInfo name="DOI" value="10.17487/RFC8984"/>
</reference>


<reference anchor="IANA-JMAP" target="https://www.iana.org/assignments/jmap/">
  <front>
    <title>JSON Meta Application Protocol (JMAP)</title>
    <author >
      <organization>IANA</organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>


    </references>

</references>



  </back>

<!-- ##markdown-source:
H4sIAAAAAAAAA81d23Ibx5m+76fohS8iqkCKpGXHhlJJqJPNlEQpJJWtrFe1
HMw0gDEHM9jpASGsrNQ+xD7APss+yj7J/qc+DYYU7SSV1YVNAtM93f/x+w/d
3N/fV13ZVWai//D65K1+M/3R5J3+vrRd025VNp225mb4u6LJ62wJA4s2m3X7
pelm+z8us9V+Q8/tL/i5/cNjZdfTZWlt2dSX2xWMOH1x+VLlWWfm8MBE265Q
zdQ2lemMnahy1U50165td3x4+C0MvzbbTdMWMK7uTFubbv85vlLZLquLf8uq
poY5t8aqVTnRP3RNPta2abvWzCz8tF3iD++VytbdomknSu8rDf/K2k700wP9
XVMXm6zO6EPe0dO2qdPPm3Y+0S8z2y2zsqJPDP400VN4dP77mXzTmWx5kDdL
peqmXWZdeWMm9DQScP/Zm/MXE33+8tk3Xx8fKlXWs4GHXp+cvnIPHcVjzy5P
nl1e0Ffffn10yF9dyOf88Vdffek+Pnn14uz5yTnP9O03j+nz05Ozk32cjt+H
/7qsnZtuohddt7KTR482m81BCbs+gB0/yoBn83pp6s4+QtY+CsNEZi7enOnX
psv0yWpVlcBS4LF+2zbAhKbSD/Bde36QZ4D7tx9+dDTGJSq1v7+vs6nt2izv
lLpcGJbAaWaNXvnZhZJ7+NFNWRirlwbeUFgNhAXG1/kCuFP+R1nPVQdz5Ou2
hb2AvIHo6WamiwxWzuJq9dR0G2NqnVclPgSipa1pb0x7oPUlCLMyHzpToxDr
rIB34IzZtKzKbqu7Rrema0tzYzTLPdCi0jAYn7f4LnnNGNieV+sC1uTf3C2y
Ti8yGDvFBcBGurbZmmKsp1tNb6XH8YUk8llbqJdN8wgYJzs+YJIty6KojFJf
oKa0TbHOkR9KEfEefPzopfDTJ/2///lfn2FfRNdMuRcDTTrcTkxpk+ULpmVH
6i1rG9MP+SKr5wb2jb9Y9+m/r027HROR/a/P+EkitwFGu1c0K9MCwxQsbZCL
QkYeF79TZtCdqSrcg3B2syhhvY74RHcegARfd7poYGjddG77+Fa1AjtYNmur
b7JqDYtU6rTWy6ze6iyQzuqy06XVa2tm6wqlIstzY+2QTKhk5S+RjB+y5aoy
QBWcoIXZtxoMUIfzWIOC75YQTZHpvKk7UBMQwByMZMRmNhifPu2BZtG3MA6e
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
jPuIXzAe/KT+Dw2uGiL/agAA

-->

</rfc>

