mirror of
https://github.com/moparisthebest/xeps
synced 2024-10-31 15:35:07 -04:00
1158 lines
39 KiB
XML
1158 lines
39 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE xep SYSTEM "xep.dtd" [
|
||
<!ENTITY % ents SYSTEM "xep.ent">
|
||
%ents;
|
||
<!ENTITY actor "<actor/>">
|
||
<!ENTITY invalidactor "<invalid-actor/>">
|
||
<!ENTITY invalidnode "<invalid-node/>">
|
||
]>
|
||
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
|
||
<xep>
|
||
<header>
|
||
<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>
|
||
&LEGALNOTICE;
|
||
<number>xxxx</number>
|
||
<status>ProtoXEP</status>
|
||
<type>Standards Track</type>
|
||
<sig>Standards</sig>
|
||
<approver>Council</approver>
|
||
<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/>
|
||
<shortname>NOT_YET_ASSIGNED</shortname>
|
||
<author>
|
||
<firstname>Simon</firstname>
|
||
<surname>Tennant</surname>
|
||
<email>simon@buddycloud.com</email>
|
||
<jid>simon@buddycloud.com</jid>
|
||
</author>
|
||
<author>
|
||
<firstname>Lloyd</firstname>
|
||
<surname>Watkin</surname>
|
||
<email>lloyd@evilprofessor.co.uk</email>
|
||
<jid>lloyd@evilprofessor.co.uk</jid>
|
||
</author>
|
||
<author>
|
||
<firstname>Ashley</firstname>
|
||
<surname>Ward</surname>
|
||
<email>ashley.ward@surevine.com</email>
|
||
<jid>ashley.ward@surevine.com</jid>
|
||
</author>
|
||
<revision>
|
||
<version>0.0.2</version>
|
||
<date>2014-04-29</date>
|
||
<initials>sdt</initials>
|
||
<remark>
|
||
<p>First draft.</p>
|
||
</remark>
|
||
</revision>
|
||
</header>
|
||
<section1 topic="Buddycloud Introduction" anchor="Buddycloud Introduction">
|
||
<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">
|
||
<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:</p>
|
||
<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>
|
||
</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 <item/> 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
|
||
<em>buddycloud-component.verona.lit</em>
|
||
.
|
||
</p>
|
||
</section2>
|
||
</section1>
|
||
<section1 topic="Register" anchor="register">
|
||
<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">
|
||
<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">
|
||
<p>- using disco-info
|
||
with the node specified - using &xep0060; 5.4 Discover Node Metadata</p>
|
||
</section2>
|
||
<section2 topic="Set Node Configuration" anchor="set-node-config"><p> set Not sure what
|
||
goes here?</p>
|
||
</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><empty></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>
|
||
<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>
|
||
<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>
|
||
</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/<jid>>/posts</td>
|
||
<td>Activity stream</td>
|
||
<td>Atom 1.0</td>
|
||
<td>Activty stream formatted posts</td>
|
||
</tr>
|
||
<tr>
|
||
<td>/user/<jid>>/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/<jid>>/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/<jid>>/geoloc</td>
|
||
<td>Describes where the channel owner is now.</td>
|
||
<td>XEP-0080</td>
|
||
<td>A single item.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>/user/<jid>>/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/<jid>>/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">
|
||
<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>
|
||
<table caption="channel read permissions">
|
||
<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>
|
||
<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>
|
||
</table>
|
||
<table caption="channel write permissions">
|
||
<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>
|
||
<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>
|
||
</table>
|
||
</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">
|
||
|
||
<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>
|
||
<p>A retraction message is sent to all online clients, with an Atom tombstone to
|
||
replace the deleted post</p>
|
||
<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 &
|
||
<strong>atom</strong>;
|
||
standards and optionally making use of &
|
||
<strong>thread</strong>;
|
||
and &
|
||
<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 &
|
||
<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>
|
||
<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 &rfc4685;
|
||
and utilise the &
|
||
<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>
|
||
</section4>
|
||
</section3>
|
||
<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>
|
||
<section3 topic="Rating" anchor="item-rating">
|
||
<p>By
|
||
making use of the &
|
||
<strong>review</strong>;
|
||
extension of activity streams and the &
|
||
<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">
|
||
<p>Buddycloud clients follow <cite>XEP-0060</cite> subscription mechanisms for following and unfollowing a channel.</p>
|
||
</section1>
|
||
<section1 topic="Channel affiliations" anchor="affiliations">
|
||
<section2 topic="Buddycloud to XEP-0060 mappings" anchor="affiliation-to-xep-0060-mappings">
|
||
<p>
|
||
Buddycloud channels build on XEP-0060's node affiliations.</p>
|
||
<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>
|
||
</section2>
|
||
</section1>
|
||
<section1 topic="Federation" anchor="federation">
|
||
<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">
|
||
<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>
|