<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
  <!ENTITY stanza-id "&lt;stanza-id/&gt;">
  <!ENTITY origin-id "&lt;origin-id/&gt;">
  <!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
  <title>Unique and Stable Stanza IDs</title>
  <abstract>This specification describes unique and stable IDs for messages.</abstract>
  &LEGALNOTICE;
  <number>0359</number>
  <status>Experimental</status>
  <type>Standards Track</type>
  <sig>Standards</sig>
  <approver>Council</approver>
  <dependencies>
    <spec>XMPP Core</spec>
  </dependencies>
  <supersedes/>
  <supersededby/>
  <shortname>stanza-id</shortname>
  &flow;
  <revision>
	  <version>0.5.0</version>
	  <date>2017-08-23</date>
	  <initials>dg</initials>
	  <remark>
		  <ul>
			  <li>Business rules clarifications</li>
			  <li>Define stanza-ids for messages only</li>
		  </ul>
	  </remark>
  </revision>
  <revision>
    <version>0.4.1</version>
    <date>2017-05-20</date>
    <initials>egp</initials>
    <remark><ul>
      <li>Added an XML schema.</li>
      <li>Fixed a typo.</li>
    </ul></remark>
  </revision>
  <revision>
    <version>0.4</version>
    <date>2016-10-30</date>
    <initials>dg</initials>
    <remark>
      <p>Add ability to discover support</p>
    </remark>
  </revision>
  <revision>
    <version>0.3.0</version>
    <date>2016-10-29</date>
    <initials>fs</initials>
    <remark>
      <p>Rename client-id element to origin-id.</p>
	  <p>Minor improvements.</p>
    </remark>
  </revision>
  <revision>
    <version>0.2.1</version>
    <date>2015-09-22</date>
    <initials>fs</initials>
    <remark>
      <p>Minor fixes (typos, s/JID/XMPP Address, etc.)</p>
    </remark>
  </revision>
  <revision>
    <version>0.2</version>
    <date>2015-09-18</date>
    <initials>fs</initials>
    <remark>
	  <ul>
		<li>Refactored client-id from attribute to element.</li>
		<li>Set short name to 'stanza-id'.</li>
		<li>Clarified that SID elements must not have additional content.</li>
	  </ul>
    </remark>
  </revision>
  <revision>
    <version>0.1</version>
    <date>2015-07-14</date>
    <initials>XEP Editor (mam)</initials>
    <remark><p>Initial published version approved by the XMPP Council.</p></remark>
  </revision>
  <revision>
    <version>0.0.2</version>
    <date>2015-06-22</date>
    <initials>fs</initials>
    <remark>
	  <ul>
		<li>Rename the XEP from "Message IDs" to "Stanza IDs"</li>
		<li>Add 'by' attribute</li>
	  </ul>
	</remark>
  </revision>
  <revision>
    <version>0.0.1</version>
    <date>2015-06-01</date>
    <initials>fs</initials>
    <remark><p>First draft.</p></remark>
  </revision>
</header>
<section1 topic='Introduction' anchor='intro'>
  <p>This XEP introduces unique and stable IDs for messages, which are beneficial in various ways. For example, they can be used together with &xep0313; to uniquely identify a message within an archive. They are also useful in the context of &xep0045; conferences, as they allow to identify a message reflected by a MUC service back to the originating entity.</p>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
  <section2 topic='Unique stanza IDs' anchor='stanza-id'>
  <example caption='The stanza ID extension.'><![CDATA[
<stanza-id xmlns='urn:xmpp:sid:0'
           id='de305d54-75b4-431b-adb2-eb6b9e546013'
           by='room@muc.example.com'/>
]]></example>
  <p>In order to create a &stanza-id; extension element, the creating XMPP entity generates and sets the value of the 'id' attribute, and puts its own XMPP address as value of the 'by' attribute. The value of the 'id' attribute must be unique and stable, i.e. it MUST NOT change later for some reason within the scope of the 'by' value. Thus the IDs defined in this extension MUST be unique and stable within the scope of the generating XMPP entity. It is RECOMMENDED that the ID generating service uses UUID and the algorithm defined in &rfc4122; to generate the IDs.</p>
  </section2>
  <section2 topic='Origin generated stanza IDs' anchor='origin-id'>
	<p>
	  Some use cases require the originating entity, e.g. a client, to generate the stanza ID. In this case, the client MUST use the &origin-id; element extension element qualified by the 'urn:xmpp:sid:0' namespace. Note that originating entities often want to conceal their XMPP address and therefore the &origin-id; element has no 'by' attribute.
	</p>
	<example caption='A message stanza with the stanza ID extension.'><![CDATA[
<message xmlns='jabber:client'
         to='room@muc.example.com'
         type='groupchat'>
  <body>Typical body text</body>
  <origin-id xmlns='urn:xmpp:sid:0' id='de305d54-75b4-431b-adb2-eb6b9e546013'/>
</message>]]></example>
	<p>
	  The server or component MAY add a &stanza-id; element. In that case, it MUST preserve the content of the &origin-id; element.
	</p>
	<example caption='A message stanza with the stanza ID extension.'><![CDATA[
<message xmlns='jabber:client'
         to='room@muc.example.com'
         type='groupchat'>
  <body>Typical body text</body>
  <stanza-id xmlns='urn:xmpp:sid:0'
             id='5f3dbc5e-e1d3-4077-a492-693f3769c7ad'
             by='room@muc.example.com'/>
  <origin-id xmlns='urn:xmpp:sid:0' id='de305d54-75b4-431b-adb2-eb6b9e546013'/>
</message>]]></example>
  </section2>
</section1>
<section1 topic='Business Rules' anchor='rules'>
  <ol>
	<li>The values of the 'id' attribute SHOULD be unpredictable.</li>
	<li>Stanza ID generating entities, which encounter a &stanza-id; element where the 'by' attribute matches the 'by' attribute they would otherwise set, MUST delete that element even if they are not adding their own stanza ID.</li>
	<li>Entities, which are routing stanzas, SHOULD NOT strip any elements qualified by the 'urn:xmpp:sid:0' namespace from message stanzas unless the preceding rule applied to those elements.</li>
	<li>Stanzas MUST possess, in the direct child level of the stanza, at most one &stanza-id; extension element with the same XMPP address as value of the 'by' attribute.</li>
	<li>Every &stanza-id; extension element MUST have the 'id' attribute and the 'by' attribute set.</li>
	<li>Every &stanza-id; and &origin-id; extension element MUST always possess an 'id' attribute and MUST NOT have any child elements or text content.</li>
	<li>The value of the 'by' attribute MUST be the XMPP address of the entity assigning the unique and stable stanza ID. For one-on-one messages the assigning entity is the account. In groupchats the assigning entity is the room. Note that XMPP addresses are normalized as defined in &rfc6122;.</li>
  </ol>
</section1>
<section1 topic='Discovering Support' anchor='disco'>
  <p>An entity that follows the business rules, especially the rule on overriding the ID in elements where the by atttribute matches the 'by' attribute they would otherwise set, SHOULD announce the 'urn:xmpp:sid:0' namespace in its disco features allowing other entities to verify that those business rules are properly enforced.</p>
  <example caption='Client sends service discovery request to the room'><![CDATA[
<iq from='romeo@montague.tld/garden'
    id='somethingrandom'
    to='room@muc.example.com'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#info' />
</iq>
]]></example>
  <example caption='Servers includes the stanza ID namespace in its features'><![CDATA[
<iq from='room@muc.example.com'
    to='romeo@montague.tld/garden'
    id='somethingrandom'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    …
    <feature var='urn:xmpp:sid:0'/>
    …
  </query>
</iq>
]]></example>
</section1>
<section1 topic='Security Considerations' anchor='security'>
  <p>The value of the 'id' attribute should not provide any further information besides the opaque ID itself. Entities observing the value MUST NOT be able to infer any information from it, e.g. the size of the message archive. The value of 'id' MUST be considered a non-secret value.</p>
  <p>Before processing the stanza ID of a message and using it for deduplication purposes or for MAM catchup, the receiving entity SHOULD ensure that the stanza ID could not have been faked, by verifying that the entity referenced in the by attribute does annouce the 'urn:xmpp:sid:0' namespace in its disco features.</p>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
  <p>This document requires no interaction with &IANA;.</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
  <section2 topic='Protocol Namespaces' anchor='ns'>
    <p>This specification defines the following XML namespaces:</p>
    <ul>
      <li>urn:xmpp:sid:0</li>
    </ul>
    <p>The &REGISTRAR; shall include the foregoing namespaces in its registry of protocol namespaces (see &NAMESPACES;) and in its disco features registry (&DISCOFEATURES;) as defined in &xep0030;.</p>
<code caption='Registration'><![CDATA[
<var>
  <name>urn:xmpp:sid:0</name>
  <desc>Indicates that an entity adds stanza-ids and follows the business rules described in the XEP</desc>
  <doc>XEP-0359</doc>
</var>
]]></code>
  </section2>
</section1>
<section1 topic='XML Schema' anchor='schema'>
  <code><![CDATA[
<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='urn:xmpp:sid:0'
    elementFormDefault='qualified'>

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      XEP-0359: https://www.xmpp.org/extensions/xep-0359.html
    </xs:documentation>
  </xs:annotation>

  <xs:element name='stanza-id'>
    <xs:complexType>
      <xs:attribute name='id' type='xs:string' use='required'/>
      <xs:attribute name='by' type='xs:string' use='required'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='origin-id'>
    <xs:complexType>
      <xs:attribute name='id' type='xs:string' use='required'/>
    </xs:complexType>
  </xs:element>

</xs:schema>]]></code>
</section1>
<section1 topic='Acknowledgements' anchor='ack'>
  <p>Thanks to Thijs Alkemade and Georg Lukas for providing feedback.</p>
</section1>
</xep>
