<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
<!ENTITY ITEM "&lt;item/&gt;">
<!ENTITY ITEMS "&lt;items/&gt;">
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
  <header>
    <title>PubSub Collection Nodes</title>
    <abstract>This specification defines the nature and handling of collection nodes in the XMPP publish-subscribe extension.</abstract>
    &LEGALNOTICE;
    <number>0248</number>
    <status>Deferred</status>
    <type>Standards Track</type>
    <sig>Standards</sig>
    <approver>Council</approver>
    <dependencies>
      <spec>XMPP Core</spec>
      <spec>XEP-0060</spec>
    </dependencies>
    <supersedes/>
    <supersededby/>
    <shortname>NOT_YET_ASSIGNED</shortname>
    &stpeter;
    &ralphm;
    <author>
      <firstname>Brian</firstname>
      <surname>Cully</surname>
      <email>bjc@kublai.com</email>
      <jid>bjc@kublai.com</jid>
    </author>
    <revision>
      <version>0.2</version>
      <date>2010-09-28</date>
      <initials>bjc</initials>
      <remark>
        <p>Completely reworked from initial version. To wit:</p>
        <ul>
          <li>Normalized layout</li>
          <li>Added required sections</li>
          <li>Renamed "multi-collection" disco feature to "multi-collections" for consistency with "collections" feature</li>
          <li>Added associate request</li>
          <li>Added dissociate request</li>
          <li>Added ability to request items on a collection node</li>
          <li>Removed "Node Relationship Models" section</li>
        </ul>
      </remark>
    </revision>
    <revision>
      <version>0.1</version>
      <date>2008-08-11</date>
      <initials>psa</initials>
      <remark><p>Initial version, split from XEP-0060.</p></remark>
    </revision>
  </header>

  <section1 topic='Introduction' anchor='introduction'>
    <p>&xep0060; defines an XMPP protocol extension for generic publish-subscribe features. However, it only allows notifications from nodes to which an entity is directly subscribed. It is useful in some circumstances to describe a relationship between nodes so that a publish on one node may be delivered via another node. For instance, if an entity is interested in notifications from a set of nodes the entity would discover each node somehow and then subscribe to them. With collection nodes, the entity would subscribe only to the collection which links the desired nodes, simplifying the subscription process.</p>

    <p>In addition to simplifying the subscriber's usage, collection nodes also allow the owner to describe almost any type of relationship between nodes. Using various access models on different nodes the owner can also create almost any desired authorization semantics on a set of leaf nodes.</p>

    <p class='em'>Note: Any use cases not described herein are described in <cite>XEP-0060</cite>. Also, this document does not show error flows related to the generic publish-subscribe use cases referenced herein, since they are exhaustively defined in <cite>XEP-0060</cite>. The reader is referred to <cite>XEP-0060</cite> for all relevant protocol details related to the XMPP publish-subscribe extension.</p>
  </section1>

  <section1 topic='Scope' anchor='scope'>
    <p>This documents addresses the common requirements regarding configuration, publishing, subscribing, and notification semantics of collection nodes.</p>
  </section1>

  <section1 topic='Glossary' anchor='glossary'>
    <p>The following terms are used in this document to refer to collection node-specific features.</p>

    <p class='em'>Note: some of these terms are specified in greater detail within the body of this document.</p>

    <dl>
      <di>
        <dt>Collection Node</dt>
        <dd>A type of node that contains other nodes but no published items (<em>c.f.</em> Leaf Node).</dd>
      </di>

      <di>
        <dt>Leaf Node</dt>
        <dd>A type of node that contains published items but no other nodes (<em>c.f.</em> Collection Node).</dd>
      </di>

      <di>
        <dt>Node Graph</dt>
        <dd>The network of nodes emitting from a given node which contains all its descendants.</dd>
      </di>

      <di>
        <dt>Root Node</dt>
        <dd>An anonymous collection node used as the <em>de facto</em> beginning of a service's node graph.</dd>
      </di>

      <di>
        <dt>Subscription Depth</dt>
        <dd>How deep the collection node graph will be traversed when determining whether notifications will be sent. May be any integer, 0 or greater, or "all".</dd>
      </di>

      <di>
        <dt>Subscription Type</dt>
        <dd>The type of notification, either "nodes", "items", or "all" which the subscriber is interested in.</dd>
      </di>
    </dl>
  </section1>

  <section1 topic='Preliminaries' anchor='preliminaries'>
    <section2 topic='Collection Nodes' anchor='collection-nodes'>
      <p>Collection nodes link nodes together to unify notifications from a set of collection or leaf nodes. An entity can subscribe to the collection and receive notifications of any associated leaf nodes.</p>

      <p>A collection node can link with any other node in order to create a directed acyclic graph (DAG). Collection nodes MUST NOT be linked in such a way as to produce a cyclic graph (<em>i.e.</em>, they cannot link to nodes that eventually link back to the initial node).</p>

      <p>Collection nodes only contain other nodes and MUST NOT contain published items (therefore a collection MUST NOT support the "publish" feature or related features such as "persistent-items").</p>
    </section2>
  </section1>

  <section1 topic='Entity Use Cases' anchor='entity'>
    <section2 topic='Discovering Support for Collection Nodes' anchor='disco-support'>
      <p>An entity might wish to discover if a service implements collection nodes; in order to do so, it sends a service discovery information ("disco#info") query to the component's JID using &xep0030;. If a service supports collection nodes it MUST return a "pubsub#collections" feature. In addition, if the service supports associating a node with more than one collection it MUST return a feature of "pubsub#multi-collections".</p>

      <example caption='Entity requests features from a service'><![CDATA[
<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='info1'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>

      <example caption='Service responds with support for collections'><![CDATA[
<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='info1'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    ...
    <feature var='http://jabber.org/protocol/pubsub#collections'/>
    <feature var='http://jabber.org/protocol/pubsub#multi-collections'/>
    ...
  </query>
</iq>
]]></example>
    </section2>

    <section2 topic='Discover Nodes' anchor='disco-nodes'>
      <p>The service discovery items ("disco#items") protocol enables an entity to query a service for a list of associated items, which, in the case of collection nodes would consist of the children associated with a given node.</p>

      <section3 topic='Request' anchor='disco-nodes-request'>
        <example caption='Entity requests child node discovery'><![CDATA[
<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='disco1'>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='blogs'/>
</iq>
]]></example>
      </section3>

      <section3 topic='Success Case' anchor='disco-nodes-success'>
        <example caption='Service responds with child nodes'><![CDATA[
<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='disco1'>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='blogs'>
    <item node='Romeoance'
          name='Letters to my Beloved'
          jid='pubsub.shakespeare.lit'/>
    <item node='Julliennui'
          name='A Rose by Another Name'
          jid='pubsub.shakespeare.lit'/>
  </query>
</iq>
]]></example>
      </section3>
    </section2>

    <section2 topic='Notifications' anchor='notifications'>
      <section3 topic='Generating Notifications for Collections' anchor='notify'>
        <p>If a notification on a child node is created and then delivered via the collection then the notifications generated by the service MUST contain additional information. The 'node' attribute of the &ITEM; or &lt;node/&gt; element contained in the notification message MUST specify the node identifier of the node that generated the notification (not the collection) and the &MESSAGE; stanza MUST contain &xep0131; that specifies the node identifier of the collection.</p>

        <p class='em'>Note: The delivery options (such as "pubsub#deliver_payloads") are determined by the publishing leaf node, not by the collection node. If the owner of a collection node sets delivery options for a collection node, the service SHOULD ignore those options and apply the options set for the leaf node that publishes an item.</p>

        <section4 topic='Notifications about Items' anchor='notify-items'>
          <p>Item notifications are notifications about the contents of a leaf node, and are generated by a publish, retract, or purge request.</p>

          <example caption='Subscriber receives a publish notification from a collection'><![CDATA[
<message to='francisco@denmark.lit' from='pubsub.shakespeare.lit'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='princely_musings'>
      <item id='ae890ac52d0df67ed7cfdf51b644e901'>
        ...
      </item>
    </items>
  </event>
  <headers xmlns='http://jabber.org/protocol/shim'>
    <header name='Collection'>blogs</header>
  </headers>
</message>
]]></example>
        </section4>

        <section4 topic='Notifications about Nodes' anchor='notify-items'>
          <p>Node notifications are notifications about nodes themselves, and are generated by a create, delete, or configure request.</p>

          <example caption='Subscriber receives a creation notification from a collection'><![CDATA[
<message to='francisco@denmark.lit' from='pubsub.shakespeare.lit'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <create node='princely_musings'/>
  </event>
  <headers xmlns='http://jabber.org/protocol/shim'>
    <header name='Collection'>blogs</header>
  </headers>
</message>
]]></example>
        </section4>
    </section3>

      <section3 topic='Node Association and Dissociation' anchor='notify-associate-dissociate'>
        <p>If a collection node is configured to send notification of node associations and disassociations, the service shall send an event that contains a &lt;collection/&gt; element whose 'node' attribute specifies the NodeID of the collection; this element in turn contains an &lt;associate/&gt; or &lt;dissociate/&gt; element whose 'node' attribute specifies the NodeID of node that has been associated with the collection.</p>

        <example caption='Notification of node association'><![CDATA[
<message from='pubsub.shakespeare.lit'
         to='francisco@denmark.lit'
         id='newnode1'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <collection node='some-collection'>
      <associate node='new-node-id'>
    </collection>
  </event>
</message>
]]></example>

        <example caption='Notification of node dissociation'><![CDATA[
<message from='pubsub.shakespeare.lit'
         to='francisco@denmark.lit'
         id='newnode1'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <collection node='some-collection'>
      <dissociate node='old-node-id'>
    </collection>
  </event>
</message>
]]></example>

        <section4 topic='Including Node Meta-Data' anchor='notify-metadata'>
          <p>The notification event MAY also include the node meta-data, formatted using the &xep0004; protocol.</p>

          <example caption='Notification of node association'><![CDATA[
<message from='pubsub.shakespeare.lit'
         to='francisco@denmark.lit'
         id='newnode2'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <collection node='some-collection'>
      <associate node='new-node-id'>
        <x xmlns='jabber:x:data' type='result'>
          <field var='FORM_TYPE' type='hidden'>
            <value>http://jabber.org/protocol/pubsub#meta-data</value>
          </field>
          <field var='pubsub#creation_date'>
            <value>2003-07-29T22:56Z</value>
          </field>
          <field var='pubsub#creator'>
            <value>hamlet@denmark.lit</value>
          </field>
          <field var='pubsub#description'>
            <value>Atom feed for my blog.</value>
          </field>
          <field var='pubsub#language'>
            <value>en</value>
          </field>
          <field var='pubsub#contact'>
            <value>bard@shakespeare.lit</value>
          </field>
          <field var='pubsub#owner'>
            <value>hamlet@denmark.lit</value>
          </field>
          <field var='pubsub#title'>
            <value>Princely Musings (Atom).</value>
          </field>
          <field var='pubsub#type'
            ><value>http://www.w3.org/2005/Atom</value>
          </field>
        </x>
      </node>
    </collection>
  </event>
</message>
]]></example>
        </section4>
      </section3>
    </section2>
  </section1>

  <section1 topic='Subscriber Use Cases' anchor='subscriber'>
    <section2 topic='Subscribe to a Collection Node' anchor='subscribe'>
      <p>A service that implements collection nodes SHOULD allow entities to subscribe to collection nodes (subject to access models and local security policies).</p>
      <p>In addition to the subscription configuration options already defined in <cite>XEP-0060</cite>, there are two subscription configuration options specific to collection nodes:</p>
      <ul>
        <li>
          <p><strong>pubsub#subscription_type</strong></p>
          <p>This subscription option enables the subscriber to subscribe either to notifications about items or notifications about nodes.</p>

          <p>If the subscription type is "items", the subscriber shall be notified whenever any node contained in the collection has an item published to it, retracted from it, or the node is purged, as modified by the value of the "pubsub#subscription_depth" option.</p>

          <p>If the subscription type is "nodes", the subscriber shall be notified whenever a new node is added to the collection, removed from the collection, or the configuration of a node within the collection has changed, as modified by the value of the "pubsub#subscription_depth" option.</p>

          <p>If the subscription type is "all", the subscriber shall be notified about both "items" and "nodes" types of events, as modified by the value of the "pubsub#subscription_depth" option.</p>

          <p>The default value of this subscription option SHOULD be "nodes".</p>
        </li>

        <li>
          <p><strong>pubsub#subscription_depth</strong></p>

          <p>This subscription option enables the subscriber to specify how far to traverse the node graph when determining whether a notification will be sent. It may be any integer value, 0 or greater, or the value "all" which means that any node within the collection will generate a notification.</p>

          <p>The default value of this subscription option SHOULD be "1".</p>
        </li>
      </ul>
      <p>In order to subscribe to a collection node, an entity MUST send a subscription request to the node; the subscription request MAY include subscription options, but this is not strictly necessary (especially if the entity does not wish to override the default settings for the "pubsub#subscription_type" and "pubsub#subscription_depth" options).</p>

      <section3 topic='Request' anchor='subscribe-request'>
        <example caption='Entity subscribes to a collection node (no configuration)'><![CDATA[
<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='collsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe jid='francisco@denmark.lit'
               node='blogs'/>
  </pubsub>
</iq>
]]></example>

        <p>The subscriber will now receive notification of new first-level nodes created within the "blogs" collection.</p>

        <example caption='Entity subscribes to a collection node (with configuration)'><![CDATA[
<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='collsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe jid='francisco@denmark.lit'
               node='blogs'/>
    <options>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
        </field>
        <field var='pubsub#subscription_type'>
          <value>items</value>
        </field>
        <field var='pubsub#subscription_depth'>
          <value>all</value>
        </field>
      </x>
    </options>
  </pubsub>
</iq>
]]></example>
      </section3>

      <section3 topic='Success Case' anchor='subscribe-success'>
        <p>If the service allows the subscription it MUST inform the requesting entity that it is now subscribed.</p>
        <example caption='Service responds with success'><![CDATA[
<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='collsub1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscription node='blogs'
                  jid='francisco@denmark.lit'
                  subscription='subscribed'/>
  </pubsub>
</iq>
]]></example>
      </section3>

      <section3 topic='Error Cases' anchor='subscribe-errors'>
        <p>A service MAY allow an entity to subscribe to a collection node in two ways, once with a subscription of type "nodes" (to receive notification of any new nodes added to the collection or the entire tree) and once with a subscription of type "items" (to receive all items published within the tree). However, a service SHOULD NOT allow an entity to subscribe twice to a collection node (once with a subscription depth of "1" and once with a subscription depth of "all") for the same subscription type, since two such subscriptions are unnecessary (a depth of "all" includes by definition a depth of "1"); in this case the service SHOULD return a &conflict; error to the requesting entity.</p>

        <example caption='Service does not allow mulitple subscriptions to the same node'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='collsub1'>
  <error type='cancel'>
    <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>

        <p>Depending on the nature of the node graph, a subscription type of "items" and depth of "all" may result in an extremely large number of notifications. Therefore, a service MAY disallow such a combination of subscription options, in which case it MUST return a &notallowed; error to the requesting entity.</p>

        <example caption='Service does not allow requested options'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='collsub1'>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>
      </section3>
    </section2>

    <section2 topic='Retrieving Items on Collection Nodes' anchor='retrieve-items'>
      <p>When an entity requests items on a collection node the service SHOULD return the items on any leaf nodes associated with it subject to the access model of the collection node.</p>

      <section3 topic='Request' anchor='retrieve-request'>
        <example caption='Subscriber requests all items on a collection'><![CDATA[
<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='blogs'/>
  </pubsub>
</iq>
]]></example>
      </section3>

      <section3 topic='Success Case' anchor='retrieve-request'>
        <p>When a collection contains multiple nodes with items it MUST return multiple &ITEMS; elements, one per node.</p>

        <example caption='Service returns items on leaf nodes'><![CDATA[
<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='Romeoance'>
      <item id='368866411b877c30064a5f62b917cffe'>
        ...
      </item>
    </items>
    <items node='Julliennui'>
      <item id='3300659945416e274474e469a1f0154c'>
        ...
      </item>
    </items>
  </pubsub>
</iq>
]]></example>
      </section3>

      <section3 topic='Error Cases' anchor='retrieve-errors'>
        <p>Depending on the nature of the node graph it may be expensive to allow item retrieval from a collection node. Therefore the service MAY disallow item retrieval via collection nodes, in which case it MUST return a &feature; error to the requesting entity.</p>

        <example caption='Service cannot fulfil request'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='items1'>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>
      </section3>
    </section2>
  </section1>

  <section1 topic='Owner Use Cases' anchor='owner'>
    <section2 topic='Create a New Collection Node' anchor='createnode'>
      <p>To create a new collection node, the requesting entity MUST include a Data Form containing a "pubsub#node_type" field whose &lt;value/&gt; element contains "collection". The default value for "pubsub#node_type" SHOULD be "leaf".</p>

      <section3 topic='Request' anchor='createnode-request'>
        <example caption='Entity requests a new collection node'><![CDATA[
<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='create3'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='announcements'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#node_type'><value>collection</value></field>
      </x>
    </configure>
  </pubsub>
</iq>
]]></example>
      </section3>

      <section3 topic='Success Case' anchor='createnode-success'>
        <example caption='Service responds with success'><![CDATA[
<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='create3'/>
]]></example>
      </section3>

      <section3 topic='Error Cases' anchor='createnode-errors'>
        <p>In addition to the errors already defined for leaf node creation, there are several reasons why the collection node creation request might fail:</p>

        <ol>
          <li>The service does not support collection nodes.</li>
          <li>The service does not support creation of collection nodes.</li>
          <li>The requesting entity does not have sufficient privileges to create collection nodes.</li>
        </ol>

        <p>These error cases are described more fully in the following sections.</p>

        <section4 topic='Collection Nodes Unsupported' anchor='error-create-unsupported'>
          <p>If the service does not support collection nodes, it MUST respond with a &feature; error, specifying a pubsub-specific error condition of &lt;unsupported/&gt; and a feature of "collections".</p>

          <example caption='Service does not support collection nodes'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='create3'>
  <error type='cancel'>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
                 feature='collections'/>
  </error>
</iq>
]]></example>
        </section4>

        <section4 topic='Collection Nodes Can&apos;t be Created' anchor='error-create-notallowed'>
          <p>If the service supports collection nodes but does not allow new collection nodes to be created, it MUST respond with a &notallowed; error.</p>

          <example caption='Service does not allow creation of collection nodes'><![CDATA[
<iq type='error'
    from='hamlet@denmark.lit/elsinore'
    to='pubsub.shakespeare.lit'
    id='create3'>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>
        </section4>

        <section4 topic='Entity is not Authorized' anchor='error-create-forbidden'>
          <p>If the requesting entity has insufficient privileges to create new collections, the service MUST respond with a &forbidden; error.</p>

          <example caption='Requesting entity has insufficient privileges to create collection nodes'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='create3'>
  <error type='auth'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>
        </section4>
      </section3>
    </section2>

    <section2 topic='Configuring a Collection Node' anchor='configure-collection'>
      <section3 topic='Request' anchor='configure-request'>
        <p>In addition to the node configuration options specified in <cite>XEP-0060</cite>, there are three additional node configuration options that a service which supports collection nodes MUST supply.</p>

        <ul>
          <li><strong>pubsub#node_type</strong>
          <p>Whether this is a "leaf" or "collection" node.</p></li>
          <li><strong>pubsub#collection</strong>
          <p>The parents of this node.</p></li>
          <li><strong>pubsub#children</strong>
          <p>The children of this node.</p></li>
        </ul>

        <p>To associate the root node to the collection the &lt;value/&gt; element MUST be empty.</p>

      <p>A service MAY offer some node configuration options that are specific to collection nodes and SHOULD NOT be provided in configuration forms related to leaf nodes. The following are RECOMMENDED:</p>

      <ul>
        <li><strong>pubsub#children_association_policy</strong>
        <p>The policy regarding who may associate child nodes with the collection (values: all, owner, whitelist).</p></li>
        <li><strong>pubsub#children_association_whitelist</strong>
        <p>The whitelist of entities that may associate child nodes with the collection.</p></li>
        <li><strong>pubsub#children_max</strong>
        <p>The maximum number of child nodes that may be associated with a collection.</p></li>
      </ul>


        <example caption='Entity configures a collection node'><![CDATA[
<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='config1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <configure node='blogs'>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#node_type'>
          <value>collection</value>
        </field>
        <field var='pubsub#children'>
          <value>Romeoance</value>
          <value>Julliennui</value>
        </field>
        <field var='pubsub#collection'>
          <value/>
        </field>
      </x>
    </configure>
  </pubsub>
</iq>
]]></example>
      </section3>

      <section3 topic='Success Case' anchor='configure-success'>
        <example caption='Service successfully updates configuration'><![CDATA[
<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='config1'/>
]]></example>
      </section3>

      <section3 topic='Error Cases' anchor='configure-errors'>
        <section4 topic='Configuring a Leaf Node with Children' anchor='error-children-on-leaf'>
          <p>Leaf nodes only contain published items and MUST NOT have any children. If an entity attempts to add children to a leaf node (either via "pubsub#children" on the leaf node or "pubsub#collection" on another node) the service MUST return a &notallowed; error with a pubsub-specific error condition of &lt;invalid-options/&gt;.</p>

          <example caption='Attempt to add a leaf node as the parent of another node'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='config1'>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-options xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
]]></example>
        </section4>

        <section4 topic='Entity is not Authorized' anchor='error-config-not-authorized'>
          <p>If the requesting entity is not authorized to add the node to a collection then the service MUST return a &forbidden; error.</p>

          <example caption='Entity is not authorized to add node to a collection'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='config1'>
  <error type='cancel'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>
        </section4>

        <section4 topic='Maximum Number of Children Exceeded' anchor='error-max-children'>
          <p>If the configuration would exceed the maximum number of children allowed on a node, either because the node's "pubsub#children" exceeds it's own "pubsub#children_max" value or because adding this node to a parent via "pubsub#collection" would exceed the parent's "pubsub#children_max" value, the service MUST return a &notallowed; error with a pubsub-specific error condition of &lt;max-nodes-exceeded/&gt;.</p>

          <example caption='Node would contain too many children'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='config1'>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <max-nodes-exceeded xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
]]></example>
        </section4>

        <section4 topic='Changing Node Types' anchor='error-node-type'>
          <p>The service MUST NOT allow the node type to be changed. If it is attempted the service MUST return a &notallowed; error, specifying a pubsub-specific error condition of &lt;invalid-options/&gt;</p>

          <example caption='Attempt to change node type'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='config1'>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-options xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
]]></example>
        </section4>

        <section4 topic='Creating a Cycle in the Collection' anchor='error-collection-cycle'>
          <p>The service MUST NOT allow a cycle to be created in the node graph (<em>e.g.</em>, node A to B to C to A). If an entity attempts to submit a configuration that would create a cycle the service MUST return a &notallowed; error, specifying a pubsub-specific error condition of &lt;invalid-options/&gt;.</p>

          <example caption='Cycle created in node graph'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='config1'>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-options xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
]]></example>
        </section4>
      </section3>
    </section2>

    <section2 topic='Deleting a Collection Node' anchor='delete-node'>
      <section3 topic='Request' anchor='delete-node-request'>
        <p>If a service supports collection node creation it MUST support collection node deletion.</p>

        <example caption='Owner attempts to delete a collection node'><![CDATA[
<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='delete1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <delete node='blogs'/>
  </pubsub>
</iq>
]]></example>
      </section3>

      <section3 topic='Success Case' anchor='delete-node-success'>
        <p>If no error occurs, the service MUST inform the owner of success.</p>

        <example caption='Collection node was deleted'><![CDATA[
<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='delete1'/>
]]></example>
      </section3>

      <section3 topic='Error Cases' anchor='delete-node-errors'>
        <section4 topic='Deleting the Root Node' anchor='delete-root-node'>
          <p>If the requesting entity attempts to delete the root node, the service MUST return a &notallowed; error.</p>

          <example caption='Node is the root'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='delete1'>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>
        </section4>
      </section3>
    </section2>

    <section2 topic='Associating a Node to a Collection' anchor='associate-node'>
      <section3 topic='Request' anchor='associate-request'>
      <p>A service MAY allow collection nodes to have children associated with them without changing the rest of the configuration. If the service allows this an entity can send and &lt;associate/&gt; element with a 'node' attribute that contains the child node within a &lt;collection/&gt; element that posesses a 'node' attribute containing the parent node to the service.</p>

        <example caption='Entity requests node association'><![CDATA[
<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='assoc1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <collection node='some-collection'>
      <associate node='new-child-node'/>
    </collection>
  </pubsub>
</iq>
]]></example>
      </section3>

      <section3 topic='Success Case' anchor='associate-success'>
        <p>If the service allows the node association then it MUST confirm the association with an empty result.</p>

        <example caption='Service associates the node'><![CDATA[
<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit'
    id='assoc1'/>
]]></example>
      </section3>

      <section3 topic='Error Cases' anchor='associate-errors'>
        <section4 topic='Entity is not Authorized' anchor='error-assoc-auth'>
          <example caption='Entity is not authorized to associate the node'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='assoc1'>
  <error type='cancel'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>
        </section4>

        <section4 topic='Maximum Number of Children Exceeded' anchor='error-assoc-too-many-nodes'>
          <p>If the configuration would exceed the maximum number of children allowed on a node, either because the node's "pubsub#children" exceeds it's own "pubsub#children_max" value or because adding this node to a parent via "pubsub#collection" would exceed the parent's "pubsub#children_max" value, the service MUST return a &notallowed; error with a pubsub-specific error condition of &lt;max-nodes-exceeded/&gt;.</p>

          <example caption='Node would contain too many children'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='assoc1'>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <max-nodes-exceeded xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
]]></example>
        </section4>

        <section4 topic='Creating a Cycle in the Collection' anchor='error-assoc-cycle'>
          <p>The service MUST NOT allow a cycle to be created in the node graph (<em>e.g</em>., node A to B to C to A). If an entity attempts to submit a configuration that would create a cycle the service MUST return a &notallowed; error, specifying a pubsub-specific error condition of &lt;invalid-options/&gt;.</p>

          <example caption='Cycle created in node graph'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='assoc1'>
  <error type='cancel'>
    <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <invalid-options xmlns='http://jabber.org/protocol/pubsub#errors'/>
  </error>
</iq>
]]></example>
        </section4>
      </section3>
    </section2>

    <section2 topic='Dissociating a Node from a Collection' anchor='associate-node'>
      <section3 topic='Request' anchor='dissociate-request'>
      <p>A service MAY allow collection nodes to have children dissociated from them without changing the rest of the configuration. If the service allows this an entity can send and &lt;dissociate/&gt; element with a 'node' attribute that contains the child node within a &lt;collection/&gt; element that posesses a 'node' attribute containing the parent node to the service.</p>

        <example caption='Entity requests node dissociation'><![CDATA[
<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='dissoc1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
    <collection node='some-collection'>
      <dissociate node='old-child-node'/>
    </collection>
  </pubsub>
</iq>
]]></example>
      </section3>

      <section3 topic='Success Case' anchor='dissociate-success'>
        <p>If the service allows the node dissociation then it MUST confirm the association with an empty result.</p>

        <example caption='Service dissociates the node'><![CDATA[
<iq type='result'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit'
    id='dissoc1'/>
]]></example>
      </section3>

      <section3 topic='Error Cases' anchor='dissociate-errors'>
        <section4 topic='Node is not Associated' anchor='error-dissoc-not-assoc'>
          <p>If a dissociation is requested between two nodes that are not already associated then the service MUST return a &badrequest; error.</p>

          <example caption='Node is not associated'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit'
    id='dissoc1'>
  <error type='modify'>
    <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>
        </section4>

        <section4 topic='Entity is not Authorized' anchor='error-dissoc-auth'>
          <example caption='Entity is not authorized to dissociate the node'><![CDATA[
<iq type='error'
    from='pubsub.shakespeare.lit'
    to='francisco@denmark.lit/barracks'
    id='dissoc1'>
  <error type='cancel'>
    <forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>
        </section4>
      </section3>
    </section2>
  </section1>

  <section1 topic='Implementation Notes' anchor='impl-notes'>
    <section2 topic='Root Node' anchor='root'>
      <p>To provide a starting point for service discovery a service SHOULD support a root node. A root node represents the node belonging to a given service and MUST be identified by the lack of a node identifier (<em>i.e.</em>, the address of the pubsub service itself, such as "pubsub.shakespeare.lit"). Because the root node is owned by the service itself an entity SHOULD NOT be allowed create, delete, or configure the root node.</p>

      <p>If a node is created or configured without any parents specified, a service MAY automatically associate otherwise orphaned nodes directly to the root node. If a service automatically associates a node with the root it MUST reflect that in the node configuration data form.</p>

      <example caption='Entity subscribes to the root node'><![CDATA[
<iq type='set'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='root1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscribe jid='francisco@denmark.lit'/>
  </pubsub>
</iq>
]]></example>
    </section2>

    <section2 topic='Handling Collection Node Deletion' anchor='imple-delete'>
      <p>Deletion of collection nodes can have a number of side effects due to implementation. Depending on the nature of the collection any of the following MAY happen when a collection node is deleted:</p>

      <ul>
        <li>When the collection node is deleted and the child nodes have no other parents the child nodes are orphaned; meaning that they will have no parent node, but continue to exist.</li>
        <li>When the collection node is deleted and the child nodes have no other parents the child nodes are re-assigned as children of the root node.</li>
        <li>When the collection node is deleted and the child nodes have no other parents the child nodes are also deleted.</li>
        <li>When the collection node is deleted and the child nodes have at least one other node the child nodes MUST remain associated with remaining parent nodes.</li>
      </ul>
    </section2>

    <section2 topic='Updating Node Configuration When Associating or Dissociating Nodes' anchor='impl-config'>
      <p>Node configuration MUST always reflect the current state of the node graph. Because node configuration contains both a pointer to its parents as well as its children an update to a primary node's "pubsub#collection" value will change the value of the secondary node's "pubsub#children" value, and vice-versa. A service MAY send a notification of the configuration change on the secondary node to subscribers if "pubsub#notify_config" is enabled on the secondary node.</p>
    </section2>
  </section1>

  <section1 topic='Security Considerations' anchor='security'>
    <section2 topic='Access Models' anchor='security-access'>
      <p>Collection nodes can be used to associate almost any node within the service, but only the access model of the collection node itself is used to determine what an entity is allowed to see. Therefore care should be taken that nodes are not linked in such a way as to leak private data (e.g., from a "closed" leaf node through an "open" collection) unless that behavior is specifically desired.</p>
    </section2>
  </section1>

  <section1 topic='IANA Considerations' anchor='iana'>
    <p>This document requires no interaction with &IANA;.</p>
  </section1>

  <section1 topic='XMPP Registrar Considerations' anchor='registrar'>
    <p class='em'>Note: These options are in addition to the standard options described in <cite>XEP-0060</cite> and related XEPs.</p>

    <section2 topic='Service Discovery Features' anchor='registrar-features'>
      <code><![CDATA[
<var>
  <name>pubsub#collections</name>
  <desc>Support for collection nodes</desc>
  <doc>XEP-0248</doc>
</var>
<var>
  <name>pubsub#multi-collections</name>
  <desc>Support for multiple collections on a node</desc>
  <doc>XEP-0248</doc>
</var>
]]></code>
    </section2>

    <section2 topic='Field Standardization' anchor='registrar-formtypes'>
      <code><![CDATA[
<form_type>
  <name>http://jabber.org/protocol/pubsub#subscribe_options</name>
  <doc>XEP-0248</doc>
  <desc>Options for collection node subscription</desc>
  <field
      var='pubsub#subscription_depth'
      type='text-single'>
      label='How far to traverse the node graph for notifications'/>
  <field
      var='pubsub#subscription_type'
      type='list-single'>
    <option label='Receive notification of items only'>
      items
    </option>
    <option label='Receive notification of nodes only'>
      nodes
    </option>
    <option label='Receive notification of items and nodes'>
      all
    </option>
  </field>
</form_type>
<form_type>
  <name>http://jabber.org/protocol/pubsub#node_config</name>
  <doc>XEP-0248</doc>
  <desc>Options for collection node configuration</desc>
  <field
      var='pubsub#node_type'
      type='list-single'>
    <option label='The node contains items'>
      leaf
    </option>
    <option label='The node contains other nodes'>
      collection
    </option>
  </field>
  <field
      var='pubsub#collection'
      type='text-multi'
      label='The collections of which this node is a child'/>
  <field
      var='pubsub#children'
      type='text-multi'
      label='The nodes of which this node is a parent'/>
  <field
      var='pubsub#children_association_policy'
      type='list-single'>
    <option label='Only the owners of this node may associate other nodes to this collection'>
      owners
    </option>
    <option label='Only those on the children association whitelist may associate other nodes to this collection'>
      whitelist
    </option>
    <option label='Anyone may associate nodes with this collection'>
      all
    </option>
  </field>
  <field
      var='pubsub#children_association_whitelist'
      type='jid-multi'
      label='JIDs who can associate nodes to this collection'/>
  <field
      var='pubsub#children_max'
      type='text-single'
      label='The maximum number of children for this collection'/>
</form_type>
]]></code>
    </section2>

    <section2 topic='SHIM Headers' anchor='registrar-shim'>
      <code><![CDATA[
<header>
  <name>Collection</name>
  <desc>The node of subscription that sent a notification</desc>
  <doc>XEP-0248</doc>
</header>
]]></code>
    </section2>
  </section1>

  <section1 topic='XML Schema' anchor='schema'>
    <p>REQUIRED.</p>
  </section1>

  <section1 topic='Acknowledgements' anchor='acknowledgements'>
    <p>Many thanks to Dave Cridland for his feedback and advice.</p>
  </section1>
</xep>
