<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xep SYSTEM "xep.dtd" [
<!ENTITY % ents SYSTEM "xep.ent">
%ents;
<!ENTITY actor "&lt;actor/&gt;">
<!ENTITY invalidactor "&lt;invalid-actor/&gt;">
<!ENTITY invalidnode "&lt;invalid-node/&gt;">
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
    <header xml:base="sections/header.xml">
    <title>Buddycloud Channels</title>
    <abstract>This document describes a profile and conventions for usage of the PubSub protocol in the context of a new type of communication.</abstract>
    <number>xxxx</number>
    <status>ProtoXEP</status>
    <type>Standards Track</type>
    <sig>Standards</sig>
    <approver>Council</approver>
    <revision>
        <version>0.0.2</version>
        <date>2014-04-29</date>
        <initials>sdt</initials>
        <remark>
            <p>First draft.</p>
        </remark>
    </revision>
    <shortname>NOT_YET_ASSIGNED</shortname>
    <legal>
    <copyright>This XMPP Extension Protocol is copyright (c) 1999 - 2014
        by the XMPP Standards Foundation (XSF).
    </copyright>
    <permissions> Permission is hereby granted, free of charge, to any
        person obtaining a copy of this specification (the
        "Specification"), to make use of the Specification without
        restriction, including without limitation the rights to implement
        the Specification in a software program, deploy the Specification in
        a network service, and copy, modify, merge, publish, translate,
        distribute, sublicense, or sell copies of the Specification, and to
        permit persons to whom the Specification is furnished to do so,
        subject to the condition that the foregoing copyright notice and
        this permission notice shall be included in all copies or
        substantial portions of the Specification. Unless separate
        permission is granted, modified works that are redistributed shall
        not contain misleading information regarding the authors, title,
        number, or publisher of the Specification, and shall not claim
        endorsement of the modified works by the authors, any organization
        or project to which the authors belong, or the XMPP Standards
        Foundation.
    </permissions>
    <warranty> ## NOTE WELL: This Specification is provided on an
        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
        KIND, express or implied, including, without limitation, any
        warranties or conditions of TITLE, NON-INFRINGEMENT,
        MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. In no event
        shall the XMPP Standards Foundation or the authors of this
        Specification be liable for any claim, damages, or other liability,
        whether in an action of contract, tort, or otherwise, arising from,
        out of, or in connection with the Specification or the
        implementation, deployment, or other use of the Specification. ##
    </warranty>
    <liability> In no event and under no legal theory, whether in tort
        (including negligence), contract, or otherwise, unless required by
        applicable law (such as deliberate and grossly negligent acts) or
        agreed to in writing, shall the XMPP Standards Foundation or any
        author of this Specification be liable for damages, including any
        direct, indirect, special, incidental, or consequential damages of
        any character arising out of the use or inability to use the
        Specification (including but not limited to damages for loss of
        goodwill, work stoppage, computer failure or malfunction, or any and
        all other commercial damages or losses), even if the XMPP Standards
        Foundation or such author has been advised of the possibility of
        such damages.
    </liability>
    <conformance>
        This XMPP Extension Protocol has been contributed in full
        conformance with the XSF's Intellectual Property Rights Policy (a
        copy of which may be found at &lt;
        <link url="http://xmpp.org/extensions/ipr-policy.shtml">http://xmpp.org/extensions/ipr-policy.shtml</link>
        &gt; or obtained by writing to XSF, P.O. Box 1641, Denver, CO 80201
        USA).
    </conformance>
</legal>
    <dependencies>
        <spec>XMPP Core</spec>
        <spec>XEP-0059</spec>
        <spec>XEP-0060</spec>
        <spec>XEP-0313</spec>
        <spec>XEP-0255</spec>
        <spec>XEP-0107</spec>
    </dependencies>
    <supersedes/>
    <supersededby/>
    <author xml:base="authors/simon-tennant.xml">
	<firstname>Simon</firstname>
	<surname>Tennant</surname>
	<email>simon@buddycloud.com</email>
	<jid>simon@buddycloud.com</jid>
</author>
    <author xml:base="authors/lloyd-watkin.xml">
	<firstname>Lloyd</firstname>
	<surname>Watkin</surname>
	<email>lloyd@evilprofessor.co.uk</email>
	<jid>lloyd@evilprofessor.co.uk</jid>
</author>
    <author xml:base="authors/ashley-ward.xml">
	<firstname>Ashley</firstname>
	<surname>Ward</surname>
	<email>ashley.ward@surevine.com</email>
	<jid>ashley.ward@surevine.com</jid>
</author>
</header>
    <section1 topic="Buddycloud Introduction" anchor="Buddycloud Introduction" xml:base="sections/10.intro.xml">
	<section2 topic="About Buddycloud" anchor="about-buddycloud">
		<p>The Buddycloud project is a set of independently deployable services, that
			inter-operate to create a rich collaboration service.
		</p>
		<p>Buddycloud Channels build on XMPP's native federation and publish-subscribe
			principles to connect to, and synchronise content with users on local and
			remote domains. Services are designed to interoperate. For example, the Media
			Server, Friend Finder, and content recommendation engine work together to help
			developers build a unified collaboration services for individual and groups
			of users.
		</p>
		<p>This XEP seeks to define how the Buddycloud Channel service currently
			functions. It also seeks stay extensible for accommodate future, undefined
			use cases.
		</p>
	</section2>
	<section2 topic="Buddycloud Channels" anchor="Buddycloud Channels">
		<p>
			Buddycloud channels are a bundle of <cite>XEP-0060</cite> publish-subscribe nodes with 
			identical subscribers and permissions presented as a JID-like
			name (example:
			<link url="buddycloud:juliet@capulit.lit">juliet@capulet.lit</link>
			. Content posted into channels is automatically synchronised to the correct
			followers on other Buddycloud domains.
		</p>
	</section2>
	<section2 topic="Glossary" anchor="glossary">
		<dl>
			<di>
				<dt>Personal Channel</dt>
				<dd> Personal channels are a group of pub-sub nodes that have the same
					owner, followers and access permissions.
				</dd>
			</di>
			<di>
				<dt>Topic Channel</dt>
				<dd>Topic channels are for group discussions and decoupled from the owners
					jid. For example balcony-speeches@topics.montague.lit could be owned by
					speechwriter@montague.lit.
				</dd>
			</di>
			<di>
				<dt>Ephemeral Channel</dt>
				<dd>
					Ephemeral channels, are generated for one-off use and automatically removed
					by the Buddycloud service after the last participant unfollows them
					(similar to the Google Hangout service) An example ephemeral channel would
					be
					<code>125bd2c4-afc2-4d4c-b869-efc0c0dad8c5@montague.lit</code>
					.
				</dd>
			</di>
			<di>
				<dt>Buddycloud Service</dt>
				<dd>An XMPP component which hosts channel nodes and provides an interface
					conforming to this document to allow access to them via XMPP.
				</dd>
			</di>
			<di>
				<dt>Home server</dt>
				<dd>The Buddycloud service responsible for a JID's channels and Inbox.
				</dd>
			</di>
			<di>
				<dt>Remote Server</dt>
				<dd>Buddycloud service that run on other XMPP domains.
				</dd>
			</di>
			<di>
				<dt>Buddycloud Inbox</dt>
				<dd>Service on the entity's home Buddycloud service which subscribes to
					nodes on the Entity's behalf, and may cache node data and provide an
					ability to replay recent messages.
				</dd>
			</di>
		</dl>
	</section2>
</section1>
    <section1 topic="Service Discovery" anchor="Finding-the-right-Buddycloud-server" xml:base="sections/30.discovery.xml">
	<p>Each XMPP domain can have one Buddycloud server that serves user's channels.
		Buddycloud clients and servers need to be able to discover the authoratative
		Buddycloud server. find the
	</p>
	<section2 topic="Discovery order" anchor="DISCOthenDNS">
		<p>
			To find the correct remote Buddycloud service for a domain, the Buddycloud
			server should:
			<ol>
				<li>Use a disco#items query against the XMPP service for the remote
					Buddycloud domain.
				</li>
				<li>If no answer is returned (perhaps the remote site doesn't run a full
					XMPP service) the Buddycloud service should proceed to use the DNS
					discovery method.
				</li>
			</ol>
		</p>
	</section2>
	<section2 topic="Discovery using Disco" anchor="disco-discovery">
		<p>The Buddycloud service first sends an items discovery request to the domain
			to discover all the available components.
		</p>
		<example caption="The Entity sends a disco#items request to the domain">
<![CDATA[
<iq type='get' from='juliet@capulet.lit/balcony' to='capulet.lit' id='items1'>
  <query xmlns='http://jabber.org/protocol/disco#items'/>
</iq>]]>
		</example>
		<p>The server replies with the list of available components, along with their
			associated JIDs.
		</p>
		<example caption="The server replies with a list of available components.">
  <![CDATA[
<iq type='result' from='capulet.lit' to='juliet@capulet.lit/balcony' id='items1'>
  <query xmlns='http://jabber.org/protocol/disco#items'>
    <item jid='muc.capulet.lit' name='Chatrooms' />
    <item jid='buddycloud.capulet.lit' name='Buddycloud Server' />
  </query>
</iq>
  ]]>
		</example>
		<p>The entity then iterates through the &lt;item/&gt; elements, sending an
			info discovery request to each JID. 
		</p>
		<example caption="The Entity sends a disco#info request to each component">
<![CDATA[
<iq type='get' from='juliet@capulet.lit/balcony' to='buddycloud.capulet.lit' id='info1'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]>
		</example>
		<p>Each component replies with its identity. The Buddycloud server has an
			identity of category 'pubsub' and type 'channels'.
		</p>
		<p>A domain MUST only host one component with an identity of category 'pubsub'
			and type 'channels'.
		</p>
		<example caption="The Buddycloud server replies with its identity">
  <![CDATA[
<iq type='result' from='buddycloud.capulet.lit' to='juliet@capulet.lit/BuddycloudApp' id='info2'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    <identity category='pubsub' type='channels' />
    <identity category='pubsub' type='inbox' />
    <feature var='jabber:iq:register' />
    <feature var='http://jabber.org/protocol/disco#info' />
    <feature var='jabber:iq:search' />
  </query>
</iq>
  ]]>
		</example>
	</section2>
	<section2 topic="Discovery using DNS" anchor="DNS-discovery">
		<p>In the case that no server is found via disco, DNS should be used to
			discover the Buddycloud server. A PTR record can be used to delegate
			Buddycloud services to a remote Buddycloud server.
		</p>
		<example caption="PTR record for buddycloud server discovery">
    <![CDATA[
    _buddycloud-server._tcp.montague.lit. PTR buddycloud-component.verona.lit.
    ]]>
		</example>
		<p>
			This example delegates all the Buddycloud service to an XMPP component
			running the Buddycloud named
			<i>buddycloud-component.verona.lit</i>
			.
		</p>
	</section2>
</section1>
    <section1 topic="Register" anchor="register" xml:base="sections/40.register.xml">
  <p>Upon connection to the buddycloud server a user should send a register 
     stanza.</p>

  <example caption="The Entity sends a register request to the domain">
  <![CDATA[
  <iq type='set'
  from='juliet@capulet.lit/balcony'
  to='channels.capulet.lit'
  id='register1'>
  <query xmlns='jabber:iq:register'/>
  </iq>
  ]]>
  </example>

  <p>The register request creates the user's personal channels on first use 
  and has the additional benefit of creating additional new channel nodes 
  as they become available on the server (e.g. 'status' node, 'geoloc' nodes).
  </p>
  
</section1>
    <section1 topic="Channel and Node Configuration" anchor="channel-config" xml:base="sections/50.node-config.xml">
	<p>Node metadata is used to describe the channel to users. All nodes in a
		channel have the same metadata and permission.
	</p>
	<section2 topic="Get Node Configuration" anchor="get-node-config"> - using disco-info
		with the node specified - using <cite>XEP-0060</cite> 5.4 Discover Node Metadata
	</section2>
	<section2 topic="Set Node Configuration" anchor="set-node-config"> set Not sure what
		goes here?
	</section2>
	<section2 topic="Default roles" anchor="default-roles">
		<p> minimum setting/optional recommended fallbacks
		</p>
		<p>Channel metadata is stored as node metadata against the /posts node of the
			channel. It is recommended that all channel nodes have the same permissions
			and an update to one updates the others.
		</p>
		<p>
			Most metadata fields used for Channels are already defined in <cite>XEP-0060</cite>. The relevant ones are listed below.
		</p>
		<table caption="Channel Metadata Fields">
			<tr>
				<th>Metadata</th>
				<th>Field</th>
				<th>Example</th>
				<th>Notes</th>
				<th>Defaults</th>
			</tr>
			<tr>
				<td>Channel Title</td>
				<td>pubsub#title</td>
				<td>"Juliet's musings"</td>
				<td>Should be a brief single sentence</td>
				<td>"juliet@capulet.lit's Buddycloud channel"</td>
			</tr>
			<tr>
				<td>Channel Description</td>
				<td>pubsub#description</td>
				<td>"This is a channel about the things that I like to do."</td>
				<td>A longer description of the channel</td>
				<td>&lt;empty&gt;</td>
			</tr>
			<tr>
				<td>Channel Access Model</td>
				<td>pubsub#access_model</td>
				<td>open, authorize, local</td>
				<td>The channel subscriber model</td>
				<td>Dependent on Node</td>
			</tr>
			<tr>
				<td>Channel Creator</td>
				<td>pubsub#creator</td>
				<td>mercutio@capulet.lit</td>
				<td>The channel creator's JID</td>
				<td>Dependent on Node</td>
			</tr>
			<tr>
				<td>Default Affiliation</td>
				<td>buddycloud#default_affiliation</td>
				<td>"publisher"</td>
				<td>The role given to new channel followers</td>
				<td>Dependent on Channel Type</td>
			</tr>
			<tr>
				<td>Channel Type</td>
				<td>buddycloud#channel_type</td>
				<td>"personal"</td>
				<td>The type of this channel. (see below). Set by the server at creation.
					Not user changable.
				</td>
				<td>N.A.</td>
			</tr>
			<tr>
				<td>Channel Creation Date</td>
				<td>pubsub#creation_date</td>
				<td>"1997-08-29T02:14:42-05:00Z"</td>
				<td>When the channel was created in ISO 8601 time format. Set by the server
					at creation. Not user changeable.
				</td>
				<td>N.A.</td>
			</tr>
			<tr>
				<td>Channel Updated Date</td>
				<td>buddycloud#updated_date</td>
				<td>"2011-04-21T20:11:00-05:00Z"</td>
				<td>The date the channel configuration was later updated in ISO 8601 time
					format. Set by the server. Not user changable.
				</td>
				<td>N.A.</td>
			</tr>
            <tr>
                <td>Node content type</td>
                <td>pubsub#type</td>
                <td>http://www.w3.org/2005/Atom</td>
                <td>The type of content held within this node.</td>
                <td>http://www.w3.org/2005/Atom</td>
            </tr>
		</table>
		<p>Channel owners and moderators can also set the default affiliation for the
			channel
		</p>
		<p>
			<table caption="Channel Types">
				<tr>
					<th>Channel Type</th>
					<th>Description</th>
					<th>Example</th>
				</tr>
				<tr>
					<td>personal channel</td>
					<td>Channel named after and owned by the user's JID.</td>
					<td> romeo@montague.lit</td>
				</tr>
				<tr>
					<td>Topic channel</td>
					<td>A channel features around a common topic.</td>
					<td>cauldron-recipees@coven.shakespeare.lit</td>
				</tr>
				<tr>
					<td>local</td>
					<td>
						<p>Appears as an open channel to local users on that domain.</p>
						<p>Appears as a closed channel to users on remote Buddycloud domains.
						</p>
					</td>
					<td>montague-family-channel@montague.lit
					</td>
				</tr>
			</table>
		</p>
		<p>
			<table caption="Channel Access Models">
				<tr>
					<th>Access Model</th>
					<th>Description</th>
				</tr>
				<tr>
					<td>authorize</td>
					<td>The channel is only viewable by it's producer, followers,
						followers+post and moderators.
					</td>
				</tr>
				<tr>
					<td>open</td>
					<td>Anyone can view the channel.</td>
				</tr>
				<tr>
					<td>local</td>
					<td>
						<p>Appears as an open channel to local users on that domain.</p>
						<p>Appears as a closed channel to users on remote Buddycloud domains.
						</p>
					</td>
				</tr>
			</table>
		</p>
	</section2>
	<section2 topic="Well known nodes" anchor="well-known-nodes">
		<p>Buddycloud is designed to be extended with new node and content types. To
			kickstart Buddycloud starts with some well known and used nodes. It is
			recommended that new nodes are announced publicly on the XSF standards
			mailing list and an informal registry will be kept.
		</p>
		<table caption="Well known Buddycloud nodes.">
			<tr>
				<th>Node Name</th>
				<th>Use</th>
				<th>Format</th>
				<th>Notes</th>
			</tr>
			<tr>
				<td>/user/&lt;jid&gt;&gt;/posts</td>
				<td>Activity stream</td>
				<td>Atom 1.0</td>
				<td>Activty stream formatted posts</td>
			</tr>
			<tr>
				<td>/user/&lt;jid&gt;&gt;/public-key</td>
				<td>RFC 4880 OpenPGP public key
				</td>
				<td>Key is published using ASCII Armour encoding scheme as detailed in
					RFC-2440, Section 6 and is encoded using the
					http://xmpp.org/extensions/xep-0189.xml#schema-pubkey syntax.
				</td>
				<td>Applications use the Public Key to encode messages and posts to the node
					owner.
				</td>
			</tr>
			<tr>
				<td>/user/&lt;jid&gt;&gt;/geoloc-past</td>
				<td>Describes where the channel owner was previously.</td>
				<td>XEP-0080</td>
				<td>Show's key location or place "checkins".</td>
			</tr>
			<tr>
				<td>/user/&lt;jid&gt;&gt;/geoloc</td>
				<td>Describes where the channel owner is now.</td>
				<td>XEP-0080</td>
				<td>A single item.</td>
			</tr>
			<tr>
				<td>/user/&lt;jid&gt;&gt;/geoloc-future</td>
				<td>Describe where the channel owner plans to go.</td>
				<td>XEP-0080</td>
				<td>Show's an intended location or description (for example "Juliet's
					Balcony" or "Going out this evening to read love poetry"). A good
					application will clear the geoloc-future location when it matches the
					current location.
				</td>
			</tr>
			<tr>
				<td>/user/&lt;jid&gt;&gt;/status</td>
				<td>A one line descrition of the channels status.</td>
				<td>
					Atom 1.0
				</td>
				<td>For example a user might enter "Is happy" and a topic channel for a
					development team might have a status line of "Code is building correctly"
				</td>
			</tr>
		</table>
	</section2>
</section1>
    <section1 topic="Business Logic" anchor="biz-logic" xml:base="sections/55.application-logic.xml">
	<section2 topic="PubSub for Humans" anchor="PubSub-for-humans">
		<p> Buddycloud adapts <cite>XEP-0060</cite>'s machine-to-machine design goals with logic
			and presets that work better in a social person-to-person and person-to-group
			environment. For example, to discourage "glorifying the wicked", the list of
			banned users is only presented to the channel's moderators.
		</p>
		<p>
			<table caption="channel read permissions">
				<thead>
					<tr>
						<th>Property</th>
						<th>Access model</th>
						<th>Example</th>
						<th>Channel Producer</th>
						<th>Channel Moderator</th>
						<th>Follower+post</th>
						<th>Follower</th>
						<th>Anonymous (e.g. web)</th>
						<th>Banned users</th>
					</tr>
				</thead>
				<tbody>
					<tr>
						<td>channel name</td>
						<td>all</td>
						<td>juliet@capulet.lit</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
					</tr>
					<tr>
						<td>channel title</td>
						<td>all</td>
						<td>Posts about Romeo</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
					</tr>
					<tr>
						<td>channel description</td>
						<td>all</td>
						<td>Posts and photos of my darling Romeo. This is not a place for Verona
							gossip.
						</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
					</tr>
					<tr>
						<td>banned user list</td>
						<td>all</td>
						<td>father@montague.lit</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td>pending subscription list</td>
						<td>all</td>
						<td>nurse@capulet.lit</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td rowspan="3">channel posts</td>
						<td>open</td>
						<td rowspan="3">O Romeo, Romeo! Wherefore art thou Romeo? Deny thy father
							and refuse thy name. Or, if thou wilt not, be but sworn my love, And I’ll
							no longer be a Capulet.
						</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
					</tr>
					<tr>
						<td>authorize</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td>local</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td rowspan="3">followers, moderators and owner</td>
						<td>open</td>
						<td rowspan="3">tybalt@capulet.lit, servant@capulet.lit, peter@capulet.lit
						</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
					</tr>
					<tr>
						<td>authorize</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td>local</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
					</tr>
				</tbody>
			</table>
		</p>
		<p>
			<table caption="channel write permissions">
				<thead>
					<tr>
						<th>Property</th>
						<th>Producer</th>
						<th>Moderator</th>
						<th>Follower+post</th>
						<th>Follower</th>
						<th>Anonymous (e.g. web)</th>
						<th>Banned users</th>
					</tr>
				</thead>
				<tbody>
					<tr>
						<td>change channel name</td>
						<td>only at creation time</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td>channel channel title</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td>change channel description</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td>change banned user list</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td>approve pending subscriptions</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td>create posts</td>
						<td>yes</td>
						<td>yes</td>
						<td>yes</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
					</tr>
					<tr>
						<td>delete posts</td>
						<td>yes</td>
						<td>yes</td>
						<td>own posts</td>
						<td>no</td>
						<td>no</td>
						<td>no</td>
					</tr>
				</tbody>
			</table>
		</p>
	</section2>
	<section2 topic="Maintain Similar Affiliations across Channel Nodes" anchor="rules-nodeaffiliations">
		<p>A Buddycloud server MUST maintain similar affiliations and permissions for a subscribed
			entity across all nodes that comprise a channel. For example, following the "posts" node
			would also follow the status node.
		</p>
		<p>The server should automatically ensure that all nodes belonging to that
			channel are updated with the same permissions. This helps address a common
			criticism of the "privacy confusion" of other social products where users
			need to search settings on different clients to ensure that their profile
			really is private.
		</p>
	</section2>
</section1>
    <section1 topic="Pubsub Items" anchor="items" xml:base="sections/60.items.xml">

	<p>Many of the item use cases follow those from <cite>XEP-0060</cite>. This section notes
		the departures from the parent XEP and specific	requirements.
	</p>
    

    <section2 topic="Retrieving items" anchor="items-retrieve">
        
        <section3 topic="Recent Items" anchor="items-recent">
        
            <p>It is possible to retrieve any new items since last retrieval from all subscribed channels ('<em>/posts</em>' nodes specifically) since last retrieval using the <strong>recent items</strong> functionality.
            </p>

            <example caption="Recent items query">
  <![CDATA[
<iq from="juliet@capulet.lit/bc-app" to="buddycloud.capulet.lit" type="get" id="recent-items:1"> 
  <pubsub xmlns="http://jabber.org/protocol/pubsub"> 
    <recent-items xmlns="http://buddycloud.org/v1" 
                  since="2014-04-18T10:46.100Z" 
                  max="50"
                  parent-only="true" /> 
  </pubsub> 
</iq>
  ]]>
            </example>
            
            <example caption="Recent items reply">
  <![CDATA[
<iq to="juliet@capulet.lit/bc-app" from="buddycloud.capulet.lit" type="result" id="recent-items:1"> 
  <pubsub xmlns="http://jabber.org/protocol/pubsub"> 
    <items node="/user/romeo@montague.lit/posts">
        <item id="tag:channels.capulet.lit,/users/juliet@montague.lit/posts,16584564008760001">
            ...atom payload...
        </item>
        <item id="tag:channels.capulet.lit,/users/juliet@montague.lit/posts,10070506450002">
            ...atom payload...
        </item>
    </items>
    <items node="/user/juliet@capulet.lit/posts">
        <item id="tag:channels.capulet.lit,/users/juliet@capulet.lit/posts,3252545492409">
            ...atom payload...
        </item>
    </items>
    <items node="/user/romeo@montague.lit/posts">
        <item id="tag:channels.capulet.lit,/users/juliet@montague.lit/posts,106876700003">
            ...atom payload...
        </item>
    </items>
  </pubsub> 
</iq>
  ]]>
            </example>
            
            <p>In this example <em>max</em> represents the maximum number of items the user wishes to retrieve 
            from any one channel, <em>since</em> is the datetime from which posts should start, and 
            <em>parent-only</em> allows users to requests posts which only start a discussion 
            (i.e. no reply posts).</p>
            
            <section4 topic="Error Cases" anchor="items-recent-errorcases">
                <p>The following extended error cases are used:
                </p>
                <ul>
                    <li>
                        <em>max-required</em>
                        : A maximum number of items per node is required
                    </li>
                    <li>
                        <em>invalid-max-value-provided</em>
                        : The value of <em>max</em> must be a positive integer
                    </li>
                    <li>
                        <em>since-required</em>
                        : A valid value for <em>since</em> must be provided
                    </li>
                    <li>
                        <em>invalid-since-value-provided</em>
                        : <em>since</em> must be a parsable date string (ISO-8601 format)
                    </li>
                </ul>
            </section4>
        
        </section3>
    </section2>
    
	<section2 topic="Deleting items" anchor="items-delete">
		<example caption="The client sends">
  <![CDATA[
<iq from="juliet@capulet.lit/bc-app" to="buddycloud.capulet.lit" type="set" id="retractitem:32"> 
  <pubsub xmlns="http://jabber.org/protocol/pubsub"> 
    <retract node="/user/juliet@capulet.lit/posts" notify="1"> 
      <item id="1291048772456"/> 
    </retract> 
  </pubsub> 
</iq>
  ]]>
		</example>
		<example caption="Server replies">
  <![CDATA[
<iq from="buddycloud.capulet.lit" to="juliet@capulet.lit/bc-app" type="result" id="retractitem:32"/>
  ]]>
		</example>
		A retraction message is sent to all online clients, with an Atom tombstone to
		replace the deleted post
		<example caption="The Buddycloud server sends retractions out to online clients">
  <![CDATA[
<message from="buddycloud.capulet.lit" id="bc:MGV3B" to="benvolio@montague.lit"> 
  <event xmlns="http://jabber.org/protocol/pubsub#event"> 
    <items node="/user/channeluser@example.com/posts"> 
      <retract id="1291048772456"/> 
      <item id="1291048772456">
        <deleted-entry xmlns="http://purl.org/atompub/tombstones/1.0" ref="xmpp:buddycloud.capulet.lit?pubsub;action=retrieve;node=/user/juliet@capulet.lit/posts;item=1291048772456" when="2012-07-01T15:08:32.950Z">
          <updated>2012-07-01T15:08:32.950Z</updated>
          <id xmlns="http://www.w3.org/2005/Atom">1291048772456</id>
          <link xmlns="http://www.w3.org/2005/Atom" href="xmpp:buddycloud.capulet.lit?pubsub;action=retrieve;node=/user/juliet@capulet.lit/posts;item=1291048772456" rel="self"/>
          <published xmlns="http://www.w3.org/2005/Atom">2012-07-01T15:08:30.922Z</published>
          <object xmlns="http://activitystrea.ms/spec/1.0/">
            <object-type>comment</object-type>
          </object>
          <verb xmlns="http://activitystrea.ms/spec/1.0/">post</verb>
        </deleted-entry>
      </item>
    </items> 
  </event> 
</message>
  ]]>
		</example>
	</section2>
	<section2 topic="Item Payload" anchor="item-payload">
		<p>Buddycloud
			item data are formatted according to &amp;
			<strong>atom</strong>;
			standards and optionally making use of &amp;
			<strong>thread</strong>;
			and &amp;
			<strong>review</strong>
			; extensions.
		</p>
		<section3 topic="Publishing" anchor="item-publishing"/>
		<p>The minimal payload for a publish request must be formatted as follows:
		</p>
		<example caption="The Entity publishes to a node">
  <![CDATA[
<iq from="juliet@montague.lit/balcony" to="channels.montague.lit" type="set" id="publish:20">
   <pubsub xmlns="http://jabber.org/protocol/pubsub">
      <publish node="/user/romeo@capulet.lit/posts">
         <item>
            <entry xmlns="http://www.w3.org/2005/Atom">
               <content type="text">O Romeo, Romeo! wherefore art thou Romeo?</content>
             </entry>
         </item>
      </publish>
   </pubsub>
</iq>
  ]]>
		</example>
		<p>This payload will be extended with default data by the server if not
			provided. The final payload looking as follows:
		</p>
		<example caption="Payload with server-added elements">
        <![CDATA[
            <entry xmlns="http://www.w3.org/2005/Atom">
               <id>fc362eb42085f017ed9ccd9c4004b095</id>
               <title>Post title</title>
               <published>2014-01-01T00:00:00.000Z</published>
               <updated>2014-01-01T00:00:00.000Z</updated>
               <author>
                  <name>juliet@montague.lit</name>
                  <jid xmlns="http://buddycloud.com/atom-elements-0">juliet@montague.lit</jid>
               </author>
               <content type="text">O Romeo, Romeo! wherefore art thou Romeo?</content>
               <activity:verb>post</activity:verb>
               <activity:object>
                  <activity:object-type>post</activity:object-type>
               </activity:object>
             </entry>
]]>
		</example>
		<section4 topic="Error Cases" anchor="item-publishing-errorcases">
			<p>Beyond
				standard &amp;
				<strong>xep0060</strong>
				; error cases additional errors are used:
			</p>
			<ul>
				<li>
					<em>entry-element-required</em>
					: Where no entry element has been provided in the payload
				</li>
				<li>
					<em>content-element-required</em>
					: Where no content element or an empty content element is provided
				</li>
				<li>
					<em>unsupported-content-type</em>
					: If provided the 'type' attribute of the content element must be either
					'text' or 'xhtml'. If not provided value will default to 'text'
				</li>
			</ul>
		</section4>
		<section3 topic="Threading" anchor="item-threading"/>
		<p>
			Posts in Buddycloud can be formed into threads consisting of a parent post
			and comments to a maximum thread depth of 1. Posts follow the
			<a href="http://tools.ietf.org/html/rfc4685">ATOM threading specification</a>
			and utilise the &amp;
			<strong>thread</strong>
			; namespace with the 'ref' attribute referring to the full global ID of the
			parent post.
		</p>
		<example caption="A valid payload for replying in a thread">
        <![CDATA[
            <entry xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/">
               <id>96da02ee1baef61e767742844207bec4</id>
               <title>Post title</title>
               <published>2014-01-01T00:00:00.000Z</published>
               <updated>2014-01-01T00:00:00.000Z</updated>
               <author>
                  <name>romeo@capulet.lit</name>
                  <jid xmlns="http://buddycloud.com/atom-elements-0">romeo@capulet.lit</jid>
               </author>
               <content type="text">Shall I hear more, or shall I speak at this?</content>
               <activity:verb>post</activity:verb>
               <activity:object>
                  <activity:object-type>comment</activity:object-type>
               </activity:object>
               <thr:in-reply-to ref="tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,fc362eb42085f017ed9ccd9c4004b095" />
            </entry>
        ]]>
		</example>
		<section4 topic="Error Cases" anchor="item-threading-errorcases"/>
		<ul>
			<li>
				<em>parent-item-not-found</em>
				: A reply must be made to an existing post within the same node
			</li>
			<li>
				<em>max-thread-depth-exceeded</em>
				: An attempt to comment on a comment will result in this error response
			</li>
		</ul>
		<section3 topic="Referencing" anchor="item-referencing"/>
		<p>Within a single thread comments can reference other comments or the parent
			item. This is for the purpose of making a comment to a post further back in
			the thread.
		</p>
		<example caption="A valid payload for referencing another post within a thread">
        <![CDATA[
            <entry xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/">
               <id>96da02ee1baef61e767742844207bec4</id>
               <title>Post title</title>
               <published>2014-01-01T00:00:00.000Z</published>
               <updated>2014-01-01T00:00:00.000Z</updated>
               <author>
                  <name>romeo@capulet.lit</name>
                  <jid xmlns="http://buddycloud.com/atom-elements-0">romeo@capulet.lit</jid>
               </author>
               <content type="text">Shall I hear more, or shall I speak at this?</content>
               <activity:verb>post</activity:verb>
               <activity:object>
                  <activity:object-type>comment</activity:object-type>
               </activity:object>
               <thr:in-reply-to ref="tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,fc362eb42085f017ed9ccd9c4004b095" />
<activity:target>                 <id>tag:channels.capuet.lit,/users/romeo@capulet.lit/posts,fc362eb42085f017ed9ccd9c4004b095</id>
               </activity:target>
            </entry>
        ]]>
		</example>
		<section4 topic="Error Cases" anchor="item-referencing-errorcases">
			<ul>
				<li>
					<em>missing-in-reply-to</em>
					: As posts referencing other posts can only be comments then attempting to
					do so results in this error
				</li>
				<li>
					<em>missing-target-id</em>
					: A target ID must be specificed as text to the target element
				</li>
				<li>
					<em>targeted-item-not-found</em>
					: If the targetted item can not be found in the current thread this error
					response will be returned
				</li>
				<li>
					<em>target-outside-thread</em>
					: The targetted item must be within the same thread as the new post
				</li>
			</ul>
		</section4>
		<section3 topic="Rating" anchor="item-rating">
			<p>By
				making use of the &amp;
				<strong>review</strong>;
				extension of activity streams and the &amp;
				<strong>target</strong>
				; element outline above Buddycloud is able to support 'rating' a post.
			</p>
			<p>Posts can be rated an integer value between 1 and 5, although may only
				wish to provide a binary setting to match popular services which provide
				'likes', '+1', etc.
			</p>
			<p>
				Any post content is discarded and replaced with
				<strong>rating:X.0</strong>
				(where
				<em>X</em>
				is the rating value). The activity verb is also overwritten with 'rated'.
			</p>
			<example caption="A valid payload for rating another post">
        <![CDATA[
            <entry xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/">
               <id>96da02ee1baef61e767742844207bec4</id>
               <title>Post title</title>
               <published>2014-01-01T00:00:00.000Z</published>
               <updated>2014-01-01T00:00:00.000Z</updated>
               <author>
                  <name>romeo@capulet.lit</name>
                  <jid xmlns="http://buddycloud.com/atom-elements-0">romeo@capulet.lit</jid>
               </author>
               <content type="text">rating:5.0</content>
               <activity:verb>rated</activity:verb>
               <activity:object>
                  <activity:object-type>comment</activity:object-type>
               </activity:object>
               <thr:in-reply-to ref="tag:channels.capulet.lit,/users/romeo@capulet.lit/posts,fc362eb42085f017ed9ccd9c4004b095" />
<activity:target>                 <id>tag:channels.capuet.lit,/users/romeo@capulet.lit/posts,fc362eb42085f017ed9ccd9c4004b095</id>
               </activity:target>
               <review:rating>5.0</review:rating>
            </entry>
        ]]>
			</example>
			<section4 topic="Error cases" anchor="item-rating-errorcases">
				<ul>
					<li>
						<em>invalid-rating</em>
						: A non-numerically parsable rating value will result in this error
						message
					</li>
					<li>
						<em>rating-out-of-range</em>
						: A rating can only have an integer value between 1 and 5 (inclusive)
					</li>
					<li>
						<em>invalid-rating-request</em>
						: Ratings can only be made against post types 'post' and 'comment' i.e. it
						is not possible to rate a rating
					</li>
					<li>
						<em>item-already-rated</em>
						: A user can only rate a single post once
					</li>
				</ul>
			</section4>
		</section3>
	</section2>
</section1>
    <section1 topic="Channel subscriptions" anchor="subscriptions" xml:base="sections/70.subscriptions.xml">
    <p>Buddycloud clients follow <cite>XEP-0060</cite> subscription mechanisms for following and unfollowing a channel.</p>
</section1>
    <section1 topic="Channel affiliations" anchor="affiliations" xml:base="sections/80.affiliations.xml">
  <section2 topic="Buddycloud to XEP-0060 mappings" anchor="affiliation-to-xep-0060-mappings">
    <p>
      Buddycloud channels build on XEP-0060's node affiliations.
      <table caption="Channel Affiliations">
        <tr>
          <th>XEP-0060 Affiliation</th>
          <th>Buddycloud Affiliation</th>
          <th>Description</th>
          <th>Required?</th>
        </tr>
        <tr>
          <td>Owner</td>
          <td>owner</td>
          <td>The channel owner. Full access rights. Can add and delete
            moderators.
          </td>
          <td>REQUIRED</td>
        </tr>
        <tr>
          <td>-</td>
          <td>moderator</td>
          <td>A follower who has follower+post rights, rights to manage the
            affiliation of entites with the node (except changing ownership),
            and rights to manage the subscriptions of entities with the node.
          </td>
          <td>REQUIRED</td>
        </tr>
        <tr>
          <td>Publisher</td>
          <td>follower+post</td>
          <td>Entity can view posts and replies, publish new posts, and publish
            replies to posts.
          </td>
          <td>REQUIRED</td>
        </tr>
        <tr>
          <td>Member</td>
          <td>follower</td>
          <td>Entity can view posts and replies for whitelist and open channels,
            but cannot publish new posts or replies.
          </td>
          <td>REQUIRED</td>
        </tr>
        <tr>
          <td>None</td>
          <td>none</td>
          <td>Entity can view posts and replies for open channels, but cannot
            publish new posts or replies.
          </td>
          <td>REQUIRED</td>
        </tr>
        <tr>
          <td>Outcast</td>
          <td>outcast</td>
          <td>Entity cannot view any posts or replies, and cannot publish new
            posts or replies.
          </td>
          <td>RECOMMENDED</td>
        </tr>
      </table>
    </p>
  </section2>
</section1>
    <section1 topic="Federation" anchor="federation" xml:base="sections/90.federation.xml">
	<section2 topic="Inbox" anchor="inbox">
	</section2>
	<section2 topic="Interaction With Other Services" anchor="Interaction-With-Other-Services">
		<p>The Buddycloud service is designed to work with interchangeable components
			that offer discrete services and together form a complete communication
			service.
		</p>
		<p>While the Buddycloud Server is designed to work independently of other
			services but can be enhanced with helper services. Each helper communicates
			with the Buddycloud server and other components using XEP-0114 connections.
			Examples of helper services include: push notifications, media hosting,
			contact matching, content search and channel recommendations.
		</p>
		<p>Helper services' specifications are covered in separate XEPs.
		</p>
	</section2>
</section1>
    <section1 topic="Security Considerations" anchor="security-considerations" xml:base="sections/95.security.xml">
	<section2 topic="Server Trust" anchor="server-trust">
		<p>
			The Buddycloud server should make sure that the remote server
			component is the authoritative Buddycloud server for the domain it
			claims to represent. This is done by running the server discovery <!-- 
				how do we reference a section in this document? -->
			process and confirming the same XMPP component name.
		</p>
	</section2>
	<section2 topic="Default Role" anchor="security-considerations-with-follower+post-role">
		<p>Open channel where members join with a follow+post role present an
			attractive target for spamming and malicious behaviour. This default
			role should be use with caution especially when the Buddycloud server
			federates with remote Buddycloud-enabled domains.
		</p>
	</section2>
</section1>
</xep>
